Data Acquisition Guide

This guide demonstrates different Data Acquisition use-cases with focus on the interaction with OCM to act as a guide when e.g. writing Sequencer templates/scripts. The provided examples use the same simulators used in daqOcmServer and daqDpmServer integration tests. These provide limited simulation capabilities but is useful in this case since they are easy to deploy.

For details on more realistic deployment please refer to section Deployment and sections for daqOcmServer and daqDpmServer.

Note

Although daqDpmServer is required to produce the final Data Product it is not a software component the end user interacts with directly, rather it is daqOcmServer that commands the daqOcmServer. As such the guide does not contain any examples of how to interact with daqDpmServer, other than how to start and stop it.

Prerequisites

The guide below assumes the runtime environment has been configured and daqOcmServer and optionally daqDpmServer has been deployed and is running. This section provide the minimal number of steps to achieve that.

The following standard ICS Framework environment variables are expected to be defined:

$DATAROOT

Will be used by default by daqOcmServer and daqDpmServer for their respective workspaces:

  • $DATAROOT/ocm

  • $DATAROOT/dpm

$CFGPATH

Will be used to resolve configuration paths (see Config Path). To use configuration files when building from source add the path $PREFIX/resource to $CFGPATH, where $PREFIX is the installation prefix.

The examples further assume the following environment variables are defined. The endpoint URIs should reflect what is in your configuration, and using the example configuration above it would be:

  • OCM_REQUEST_EP=zpb.rr://127.0.0.1:12081 (replaces option --rep in daqOcmCtl)

  • OCM_PUBLISH_EP=zpb.ps://127.0.0.1:12082 (replaces option --pep in daqOcmCtl)

  • DCS_REQUEST_EP=zpb.rr://127.0.0.1:12090 (DCS simulator request endpoint)

  • DCS_DAQ_EP=${DCS_REQUEST_EP}/rec (DCS service endpoint)

  • FCF_REQUEST_EP=zpb.rr://127.0.0.1:12091 (FCF simulator request endpoint)

  • FCF_DAQ_EP=${FCF_REQUEST_EP}/daq (FCF service endpoint)

Or as console commands:

$ export OCM_REQUEST_EP=zpb.rr://127.0.0.1:12081
$ export OCM_PUBLISH_EP=zpb.ps://127.0.0.1:12082
$ export DCS_REQUEST_EP=zpb.rr://127.0.0.1:12090
$ export DCS_DAQ_EP=$DCS_REQUEST_EP/rec
$ export FCF_REQUEST_EP=zpb.rr://127.0.0.1:12091
$ export FCF_DAQ_EP=$FCF_REQUEST_EP/daq

Note

Examples in this guide use the command line client daqOcmCtl provided with the ifw-daq project. To facilitate use from scripts daqOcmCtl can provide return values in JSON format with the --json option. Alternatively the MAL API daqif.OcmDaqControl may be used directly from e.g. Python scripts.

Important

Many examples in this guide include references to components with names such as “fcf1”, “fcf2”, or “dcs1” with MAL URIs such as “zpb.rr://insws:12345/daq”. These components are assumed to be deployed and operational. This means that the examples must be modified to suit your environment to instead reference your components.

Lifecycle Control

Startup

For testing purposes the default daqOcmServer sample configuration provided by the ifw-daq project may be used (config/ifw/daq/daqOcmServer/config.yaml)

The configuration is

cfg:
    instrument_id: "UNDEF"
    req_endpoint: "zpb.rr://127.0.0.1:12081/" # IP address and port used to accept requests
    pub_endpoint: "zpb.ps://127.0.0.1:12082/" # IP address and port used to accept requests
    oldb_conn_timeout: 2 # timeout in seconds when connecting to runtime DB
    sm_scxml: "config/ifw/daq/daqOcmServer/sm.xml"
    log_properties: "config/ifw/daq/daqOcmServer/log.properties"

    # DPM communication configuration
    dpm:
        req_endpoint: "zpb.rr://127.0.0.1:12083/"
        pub_endpoint: "zpb.ps://127.0.0.1:12084/"

In which case the following steps can be performed to start daqOcmServer and simulators used for demonstration purposes.

Start the servers using default configuration and export environment variables to simplify daqOcmCtl interaction. The configuration must be found as a Config Path using $CFGPATH environment variable.

$ daqOcmServer -l DEBUG &
$ daqDpmServer -l DEBUG &

Additionally we start the simulators we can acquire data from:

$ daqSimMetadaqif fcf $FCF_REQUEST_EP &

The simulated DCS should be deployed in foreground mode to allow control when recording should stop. This is done by sending a line break using Enter to stdin after recording has started.

$ daqSimRecif -v dcs $DCS_REQUEST_EP

Once started we bring daqOcmServer operational with:

$ daqOcmCtl std.init
"OK"
$ daqOcmCtl std.enable
"OK"

Note

To use a custom configuration create a new configuration file using with the help of sections Configuration File and Configuration File. Then specify the configuration file when starting daqOcmServer and daqDpmServer with the --config PATH argument.

Shutdown

To shut daqOcmServer down the signal SIGINT (Ctrl-c) or the command Exit() can be sent using e.g. the daqOcmCtl application:

$ daqOcmCtl std.exit

To shut daqDpmServer and the simulators down send signal SIGINT (Ctrl-c).

Observing Status Changes

To observe the published state changes in OCM it is possible to use daqOcmCtl without a command with the --status option, in which case it will subscribe and remain running until stopped with Ctrl-c while printing any received topic samples to stderr. This is an example of the output during a Data Acquisition:

$ daqOcmCtl --status
no command provided -> will subscribe indefinitely
status: Operational;Active
daq: id=UNDEF.2023-11-22T10:36:32.078, file_id=UNDEF.2023-11-22T10:36:32.078, \
state=StateAcquiring, substate=NotStarted, error=false, message=[]
daq: id=UNDEF.2023-11-22T10:36:32.078, file_id=UNDEF.2023-11-22T10:36:32.078, \
state=StateAcquiring, substate=Starting, error=false, message=[]
daq: id=UNDEF.2023-11-22T10:36:32.078, file_id=UNDEF.2023-11-22T10:36:32.078, \
state=StateAcquiring, substate=Acquiring, error=false, message=[]
daq: id=UNDEF.2023-11-22T10:36:32.078, file_id=UNDEF.2023-11-22T10:36:32.078, \
state=StateAcquiring, substate=Stopping, error=false, message=[]
daq: id=UNDEF.2023-11-22T10:36:32.078, file_id=UNDEF.2023-11-22T10:36:32.078, \
state=StateAcquiring, substate=Stopped, error=false, message=[]
daq: id=UNDEF.2023-11-22T10:36:32.078, file_id=UNDEF.2023-11-22T10:36:32.078, \
state=StateMerging, substate=NotScheduled, error=false, message=[]
daq: id=UNDEF.2023-11-22T10:36:32.078, file_id=UNDEF.2023-11-22T10:36:32.078, \
state=StateMerging, substate=Scheduled, error=false, message=[]
daq: id=UNDEF.2023-11-22T10:36:32.078, file_id=UNDEF.2023-11-22T10:36:32.078, \
state=StateMerging, substate=Collecting, error=false, message=[]
daq: id=UNDEF.2023-11-22T10:36:32.078, file_id=UNDEF.2023-11-22T10:36:32.078, \
state=StateMerging, substate=Merging, error=false, message=[]
daq: id=UNDEF.2023-11-22T10:36:32.078, file_id=UNDEF.2023-11-22T10:36:32.078, \
state=StateMerging, substate=Releasing, error=false, message=[]
status: Operational;Idle

Note

The status is published by OCM for any change, some of which are not caused by state transitions. This may lead to the same status line being repeated multiple times.

The --status option can be passed when executing a command as well, but often the commands complete before any topic samples are received. The exception to this is the daq.awaitstate which only completes when the specified state is achieved or operation times out.

Automatic Stop Sequence

Automatic stop is the typical scenario when a Data Acquisition includes one or more primary data sources (usually detectors) that are configured with a fixed integration time. When all primary data sources stop (also referred to as Completed or Stopped in recif) as observed by OCM, which monitors all the sources, OCM will proceed and stop all metadata sources automatically. This condition can then be awaited on to then trigger other activities such as configuring the instrument for the next Data Acquisition.

Note

Multiple sources in each category are provided by space-separating each source, e.g:

"fcf1@zpb.rr://insws1:12345/daq fcf2@zpb.rr://insws2:12345/daq"

Data Acquisition is started with the daq.start command which takes two[1] space separated lists of sources or daq.startv2 which takes a JSON-encoded specification of the Data Acquisition to perform. The second form is necessary if additional control is required.

The following example starts a new Data Acquisition with a single primary source named dcs1 and a single metadata source named fcf1. The names are only used to give a friendly name to a possibly anonymous URI and is so far not used for anything but logging activities.

$ daqOcmCtl --json daq.start "dcs1@${DCS_DAQ_EP}" "fcf1@${FCF_DAQ_EP}"
{
  "id": "UNDEF.2023-11-22T12:33:53.856",
  "error": false
}

Using the request daq.startv2 (StartDaqV2()) the following yields same results. To simplify the usage the JSON specification is read from stdin as specified with @- and then provided using a bash Here Document:

$ daqOcmCtl daq.startv2 @- <<EOF
{
  "sources": [
   {
      "type": "primarySource",
      "sourceName": "dcs1",
      "rrUri": "${DCS_DAQ_EP}"
    },
    {
      "type": "metadataSource",
      "sourceName": "fcf1",
      "rrUri": "${FCF_DAQ_EP}"
    }
 ],
 "mergeTarget": {
   "sourceName": "dcs1"
 }
}
EOF

{
  "id": "UNDEF.2023-11-22T12:33:53.856",
  "error": false
}

Since the DCS simulator will run until we ask it to stop the Data Acquisition will remain in state daqif.DaqState.StateAcquiring and substate daqif.DaqSubState.Acquiring.

We can check the list of active Data Acquisitions using daq.getactivelist. We expect a single Data Acquisition at this point:

$ daqOcmCtl --json daq.getactivelist
[
  {
    "error": false,
    "fileId": "UNDEF.2023-11-22T12:33:53.856",
    "id": "UNDEF.2023-11-22T12:33:53.856",
    "message": "[]",
    "result": "",
    "state": "StateAcquiring",
    "substate": "Acquiring",
    "timestamp": 1700656433.8668084
  }
]

Data Acquisition status can be checked with the daq.getstatus command by providing the Data Acquisition id from the start command:

$ daqOcmCtl --json daq.getstatus UNDEF.2023-11-22T12:33:53.856
{
  "error": false,
  "fileId": "UNDEF.2023-11-22T12:33:53.856",
  "id": "UNDEF.2023-11-22T12:33:53.856",
  "message": "[]",
  "result": "",
  "state": "StateAcquiring",
  "substate": "Acquiring",
  "timestamp": 1700656433.8668084
}

When dcs1 completes OCM will issue the equivalent of the StopDaq command to stop all metadata sources. To await the completion of all FITS files the daq.awaitstate command is issued with states daqif.DaqState.StateAcquiring / daqif.DaqSubstate.Stopped and then in the terminal running daqSimRecif simulating DCS hit Enter to simulate that it completed automatically. If performed within the timeout the result would look similar to:

$ daqOcmCtl --json daq.awaitstate UNDEF.2023-11-22T12:33:53.856 StateAcquiring Stopped 60
Note: Setting request timeout to 62s due to await timeout exceeding request timeout
{
  "status": {
    "error": false,
    "fileId": "UNDEF.2023-11-22T12:33:53.856",
    "id": "UNDEF.2023-11-22T12:33:53.856",
    "message": "[]",
    "result": "",
    "state": "StateAcquiring",
    "substate": "Stopped",
    "timestamp": 1700657163.9278564
  },
  "timeout": false
}

At this point the data sources are finished with their contribution and the merging process is started if daqOcmServer can communicate with daqDpmServer. Since the simulated files are small it is likely already complete.

Checking the status again reports Data Acquisition is in state daqif.DaqState.StateCompleted and where the merged file is located:

$ daqOcmCtl --json daq.getstatus UNDEF.2023-11-22T12:33:53.856
{
  "error": false,
  "fileId": "UNDEF.2023-11-22T12:33:53.856",
  "id": "UNDEF.2023-11-22T12:33:53.856",
  "message": "[]",
  "result": "/var/run/dataroot/dpm/result/UNDEF.2023-11-22T12:33:53.856.fits",
  "state": "StateCompleted",
  "substate": "Completed",
  "timestamp": 1700657164.0261965
}

Manual Stop Sequence

Manual stop is used either when there is no fixed integration time on all primary data sources or when no primary sources are used at all (in which case there is nothing to inform OCM when to stop except for the user).

In this example data is acquired from fcf1 only, so user must decide when to stop manually.

$ daqOcmCtl --json daq.start "" "fcf1@${FCF_DAQ_EP}"
{
  "id": "TEST.2021-03-09T18:48:05.967",
  "error": false
}

Or using daq.startv2

$ daqOcmCtl --json daq.startv2 @- <<EOF
{
  "sources": [
    {
      "type": "metadataSource",
      "sourceName": "fcf1",
      "rrUri": "${FCF_DAQ_EP}"
    }
 ]
}
EOF

{
  "id": "UNDEF.2023-11-22T12:56:47.200",
  "error": false
}

At a later point the Data Acquisition can be stopped using daq.stop by specifying the id returned by daq.start.

$ daqOcmCtl --json daq.stop UNDEF.2023-11-22T12:56:47.200
{
  "id": "UNDEF.2023-11-22T12:56:47.200",
  "error": false
}

If we check status we see that it is indeed stopped and likely completed if daqOcmServer can reach daqDpmServer:

$ daqOcmCtl --json daq.getstatus UNDEF.2023-11-22T12:56:47.200
{
  "error": false,
  "fileId": "UNDEF.2023-11-22T12:56:47.200",
  "id": "UNDEF.2023-11-22T12:56:47.200",
  "message": "[]",
  "result": "/var/run/dataroot/dpm/result/UNDEF.2023-11-22T12:56:47.200.fits",
  "state": "StateCompleted",
  "substate": "Completed",
  "timestamp": 1700657840.7738013
}