DAQ

The daq package currently provides the daq_monitor module for simplified readout using DAQ monitors. We refer to https://confluence.desy.de/display/FLASHUSER/DAQmonitor for further information on DAQ monitors. The contents of this small subpackage is presented below:

import doocspie


help(doocspie.daq)
Help on package doocspie.daq in doocspie:

NAME
    doocspie.daq - DAQ module for simplified readout using DAQ monitors.

PACKAGE CONTENTS
    daq_monitor

FILE
    /home/cbehrens/Home/Repositories/gitlab/doocspie/doocspie/daq/__init__.py


In the following, we show how to use daq_monitor for conveniently working with DAQ monitors.

DaqMonitor

The simplified readout using DAQ monitors mentioned above using the daq_monitor module is realized by means of the DaqMonitor class, and its complete documentation is presented here:

help(doocspie.daq.daq_monitor.DaqMonitor)
Help on class DaqMonitor in module doocspie.daq.daq_monitor:

class DaqMonitor(builtins.object)
 |  DaqMonitor(device, facility='FLASH.DAQ')
 |  
 |  DaqMonitor class for simplified readout using DAQ monitors.
 |  
 |  This class provides the daq monitor for simplified readout using DAQ monitors.
 |  
 |  Methods defined here:
 |  
 |  __init__(self, device, facility='FLASH.DAQ')
 |      Constructor of the daq monitor class.
 |      
 |      This constructor initializes the instance with the device and optional DAQ monitor facility.
 |      
 |      Args:
 |          device (str): The device address part of the DAQ monitor.
 |          facility (str, optional): The optional facility of the DAQ monitor.
 |  
 |  __str__(self)
 |      Special method to return a properly formatted string representation of the daq monitor.
 |  
 |  get(self, address, event=None, ignore_event_mismatch=False, timestamp_event=False, meta_event=None, start=None, elements=None)
 |      Get the readout for a given DOOCS address with optional parameters (see 'Args' below).
 |      
 |      Args:
 |          address (str): The property address of the server to get the readout from.
 |          event (int, optional): Optional event to get the data from.
 |          ignore_event_mismatch (bool, optional): Optional state for ignoring event mismatches.
 |          timestamp_event (bool, optional): Optional state to determine using the timestamp as an alternative event.
 |          meta_event (str, optional): Optional Meta property to replace the default event with.
 |          start (int, optional): Optional start position for reading out array-like types.
 |          elements (int, optional): Optional number of elements to read out for array-like types.
 |      
 |      Returns:
 |          Readout: An instance of the readout object with its properties 'data', 'type', 'timestamp', 'event' and
 |          'meta'.
 |      
 |      Raises:
 |          DoocspieException: Context-dependent exception related to DOOCS, pydoocs or doocspie itself.
 |  
 |  is_running(self)
 |      Return the DAQ monitor's 'running' state.
 |      
 |      Returns:
 |          bool: The 'running' state of the DAQ monitor.
 |      
 |      Raises:
 |          DoocspieException: Doocspie related exception for inaccessible 'running' state.
 |  
 |  map(self, address)
 |      Map the DOOCS property address to the address of the associated DAQ monitor.
 |      
 |      Args:
 |          address (str): The property address to get the mapped DAQ monitor address for.
 |      
 |      Returns:
 |          str: The address of the associated DAQ monitor mapped to the given DOOCS property address.
 |      
 |      Raises:
 |          DoocspieException: Doocspie related exception for non-existing addresses to be mapped.
 |  
 |  refresh(self)
 |      Refresh the DAQ monitor in order to detect changes of the address mapping.
 |      
 |      Returns:
 |          None
 |  
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |  
 |  available_devices(facility='FLASH.DAQ') from builtins.type
 |      List the available devices (DAQ monitors) for a given optional facility.
 |      
 |      Returns:
 |          tuple: The available devices (DAQ monitors) for a given optional facility.
 |      
 |      Raises:
 |          DoocspieException: Doocspie related exception for non-listable DAQ monitors.
 |  
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |  
 |  properties
 |      tuple: The properties available via the DAQ monitor.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)

The DaqMonitor class can simply be imported directly from the doocspie.daq subpackage as is shown in the code example below. In this example, we invoke a pythonic class method (i.e. the instantiation is dispensable) that lists all available devices of the current DAQ monitor servers.

from doocspie.daq import DaqMonitor


DaqMonitor.available_devices()
('FLASHFWD.DAQ.MONITOR',
 'FL1USER1.DAQ.MONITOR',
 'FL2USER1.DAQ.MONITOR',
 'FL1USER2.DAQ.MONITOR',
 'PBD.DAQ.MONITOR',
 'PBD2.DAQ.MONITOR',
 'SFLASH.DAQ.MONITOR',
 'PBD.DAQ.OFFL.MONITOR',
 'FL1USER2.DAQ.OFFL.MONITOR',
 'FL1USER1.DAQ.OFFL.MONITOR',
 'PBD2.DAQ.OFFL.MONITOR',
 'FL2USER1.DAQ.OFFL.MONITOR',
 'SFLASH.DAQ.OFFL.MONITOR',
 'DAQ.MONITOR',
 'DAQ.OFFL.MONITOR',
 'FLASHFWD.DAQ.OFFL.MONITOR',
 'FL1USER3.DAQ.MONITOR',
 'LASER1.DAQ.MONITOR',
 'FL2USER2.DAQ.MONITOR',
 'FL2USER2.DAQ.OFFL.MONITOR',
 'FL2USER3.DAQ.MONITOR',
 'FTX28G.DAQ.MONITOR',
 'TEST.DAQ.MONITOR')

In the example above, the default facility FLASH.DAQ is implicitly being used, and that is also the most likely use case in operation. For the remaining examples, we use the virtual FLASH_SIM.DAQ facility though. This can be realized by the optional facility parameter as is shown here:

DaqMonitor.available_devices(facility="FLASH_SIM.DAQ")
('DAQ.MONITOR',)

Once a facility has been chosen, the device parameter is required in order to create a DaqMonitor instance. Here, we create such an instance using the device DAQ.MONITOR and print it out:

daq_monitor = DaqMonitor(facility="FLASH_SIM.DAQ", device="DAQ.MONITOR")

print(daq_monitor)
DaqMonitor(facility=FLASH_SIM.DAQ, device=DAQ.MONITOR, properties=('FLASH_SIM.DIAG/TOROID/3GUN/CHARGE.TD', 'FLASH_SIM.DIAG/BPM/3GUN/X.TD'), is_running=True)

Besides facility and device, the DaqMonitor instance also has the attribute properties, which contains a tuple of DOOCS properties accessible from its instance as is presented here:

daq_monitor.properties
('FLASH_SIM.DIAG/TOROID/3GUN/CHARGE.TD', 'FLASH_SIM.DIAG/BPM/3GUN/X.TD')

The running state of the particular DAQ monitor can be requested by the is_running method:

daq_monitor.is_running()
True

The unique feature of the DAQ monitors is that any DOOCS property, once set up properly, can be accessed from the corresponding DOOCS server that is running the DAQ monitor. By doing so, the DOOCS properties of interest are intrinsically synchronized even if the underlying DOOCS servers of the different properties themselves do not provide synchronization. However, the addresses of the DAQ monitor that is mapped to the particular DOOCS properties of interest must be known in order to read from it. Fortunately, the DaqMonitor provides a method called map which allows to retrieve the mapped address of the DOOCS property of interest as is demonstrated here:

daq_monitor.map("FLASH_SIM.DIAG/TOROID/3GUN/CHARGE.TD")
'FLASH_SIM.DAQ/DAQ.MONITOR/MONITOR/SPECT.CH.000input'

With the mapping in the example above, one can readout the charge from the DAQ monitor server instead of reading it out directly from the toroid device server. As a convenience, the DaqMonitor also provides a method called get, which avoids the extra step of returning the address mapping and returns the readout directly. This method has the same signature as the get function of the io submodule and it also returns an instance of Readout. The only difference is that the get method of DaqMonitor always has GSPECTRUM as its readout.type as is shown in the following code example. For array-like DOOCS types, the optional parameters start and/or elements can be used to read out only chunks of the data. For an example of parametrized readout, refer to the get function of the doocspie.io submodule section, which provides exactly the same API.

readout = daq_monitor.get("FLASH_SIM.DIAG/TOROID/3GUN/CHARGE.TD")

print("type of readout:", type(readout))
print("readout.type:", readout.type)
type of readout: <class 'doocspie.doocspie.readout.Readout'>
readout.type: GSPECTRUM

The subsequent code example demonstrates the unique synchronization feature of DAQ monitor servers, and utilizes both the map and get method of the DaqMonitor described earlier:

import time


readout = doocspie.get("FLASH_SIM.DIAG/TOROID/3GUN/CHARGE.TD")

time.sleep(1)   # artificially introduce timing delay to make synchronization indispensable

readout_via_map = doocspie.get(daq_monitor.map("FLASH_SIM.DIAG/TOROID/3GUN/CHARGE.TD"),
                               event=readout.event)
readout_via_get = daq_monitor.get("FLASH_SIM.DIAG/TOROID/3GUN/CHARGE.TD",
                                  event=readout.event)

print("readout.event == readout_via_map.event == readout_via_get.event is",
      readout.event == readout_via_map.event == readout_via_get.event)
readout.event == readout_via_map.event == readout_via_get.event is True

Here, we show how to refresh a DaqMonitor instance when the corresponding DAQ Monitor has been configured with an extra channel in the mean time, instead of creating a new instance:

print(daq_monitor.properties)

# configure the DAQ Monitor with an extra channel in the mean time

daq_monitor.refresh()  # just refresh instead of instantiating a new DaqMonitor
print(daq_monitor.properties)
('FLASH_SIM.DIAG/TOROID/3GUN/CHARGE.TD', 'FLASH_SIM.DIAG/BPM/3GUN/X.TD')
('FLASH_SIM.DIAG/TOROID/3GUN/CHARGE.TD', 'FLASH_SIM.DIAG/BPM/3GUN/X.TD', 'FLASH_SIM.DIAG/BPM/3GUN/Y.TD')