xspress3 EPICS Support Module

1-3

Introduction

This EPICS module provides areaDetector based control of the Xspress3 Readout System. It uses an API provided by Quantum Detectors and STFC to control the hardware and readout data.

This documentation will provide intructions on how to use the EPICS software interface to Xspress 3. More detailed user instructions are provided by Quantum Detectors.

This software is licensed under the GNU Lesser General Public License

User Manual

Connecting To The Xspress 3

Once the EPICS IOC is running it is necessary to connect to the Xspress 3 system. This can be done by setting the following PVs. The {P} is the base part of the PV name, which is system dependent. PVs with an _RBV on the end are readback PVs that can be used to confirm that a parameter has successfully been changed.

{P}:NUM_CHANNELS The number of channels this system is configured for. Must be less than or equal to {P}:MAX_NUM_CHANNELS_RBV, which is the value passed into xspress3Config (a function used at IOC initilization by the IOC developer).
{P}:NUM_FRAMES_CONFIG The number of frames to configure the system with. This must be less than or equal to {P}:MAX_FRAMES_RBV, which is the value passed into xspress3Config. Normally this should be set equal to {P}:MAX_FRAMES_RBV.
{P}:CONFIG_PATH This is the path to the Xspress 3 configuration files. These files should have been provided with the system.
{P}:NDAttributesFile This is the path to the Xspress 3 XML file saving configuration files. This file should have been provided with the IOC software. It defines what parameters are saved in the HDF file and what can be visualized when running the system. An example that can be used is packaged in the IOC data directory.

Once the above PVs are set, connection can take place by writing 1 to {P}:CONNECT. If connection was successful then {P}:CONNECTED will be set to 1. EPICS ca_put_callback is supported by the {P}:CONNECT PV.

When connection occurs the following API functions are called by the EPICS driver:

  1. xsp3_config
  2. xsp3_clocks_setup
  3. xsp3_restore_settings
  4. xsp3_format_run
  5. xsp3_set_run_flags

In additon, if connection was successful, several parameters are read from the system so the EPICS driver can update RBV type PVs (eg. scaler window limits).

Data Acquisition

The following PVs are involved in data acqusition or monitoring. Some of the PVs map directly onto Xspress 3 API functions, and this will be noted below.

The basic flow of control, after connection, will be:

  1. Set trigger mode (Select 'TTL Veto Only' for external triggering, where a LVTTL high signal will enable counting and the rising and falling edge will define the frame start and end points).
  2. Set up file related PVs - FilePath, FileName. Check FilePath exists.
  3. Set file number, if needed. This is the index used in the filename. This is auto incrementing each time a new file is saved, but is reset if the IOC is restarted.
  4. If the IOC has just been restarted it will be neccessary to take a single frame to configure the file writing areaDetector plugin:
    1. Set number of frames to 1.
    2. Start acqusition and generate a single external trigger.
    3. Wait until acqusition has finished.

Then for each acqusition:

  1. Erase the data.
  2. Set the number of frames for the real data collection.
  3. Start file saving.
  4. Start acqusition.
  5. Wait until acqusition has finished, then check status and number of frames processed.
  6. Update the visualization arrays before reading the array data over channel access (also do this during acqusition before reading arrays).
  7. Wait until file saving has finished, then check status and number of frames saved to disk.

The user may also wish to set up regions of interest (ROIs) (see section below), which must be done before starting an acqusition.

{P}:Acquire
{P}:Acquire_RBV
This is used to start and stop acqusition. Write a 1 to this to begin acqusition. Normally the data collection will finish automatically once NumImages is reached. However, to manually stop a data collection write a 0 to this PV. If the driver is in the process of reading a large number of frames, for example at high frame rates, it will finish this before the stop completes. This PV maps directly to xsp3_histogram_start and xsp3_histogram_stop. When writing a 1 to {P}:Acquire, ca_put_callback is supported. NOTE: it can take about 2s after starting acqusition before the system is ready to accept triggers.
{P}:ERASE This will call the Xspress 3 API xsp3_histogram_clear function. It will also clear any data held by EPICS PVs, including the array PVs. Do this before starting a new data collection.
{P}:UPDATE This does a manual update on all the scaler and ROI arrays, to ensure that they contain the latest data. It is necessary to write a 1 to this at the end of an acqusition, or during acquisition, if reading the data over channel access.
{P}:NumImages
{P}:NumImages_RBV
Set and read the number of frames to acquire. This number must be less than {P}:NUM_FRAMES_DRIVER_RBV, which was set when the IOC was configured by the developer. Acquisition will automatically stop when the number of frames acquired equals NumImages_RBV.
{P}:CTRL_MCA_ROI
{P}:CTRL_MCA_ROI_RBV
This is used to enable and disable ROI calculations. To enable ROI calculations set this to 1 and set the ROI limits. To turn ROI calculations off set this to 0, which can save CPU time if operating at high frame rates and ROIs are not needed.
{P}:CTRL_DTC
{P}:CTRL_DTC_RBV
This is used to determine if dead time corrected data is read out. If this PV is enabled then the MCA spectra will be dead time corrected, using the API function xsp3_hist_dtc_read4d. If this PV is disabled then un-corrected MCA spectra data is read out using xsp3_histogram_read4d. This option does not affect scaler data, which is always dead time corrected. The dead time corrected parameters are saved in the HDF file (see below).
{P}:TriggerMode
{P}:TriggerMode_RBV
Set and read the triggering mode. This PV maps directly on to the API function xsp3_set_glob_timeA. In simulation mode any mode can be selected. Options are:
  • Fixed - Corresponds to API option XSP3_GTIMA_SRC_FIXED
  • Internal - Corresponds to API option XSP3_GTIMA_SRC_INTERNAL
  • IDC - Corresponds to API option XSP3_GTIMA_SRC_IDC
  • TTL Veto Only - Use this for external triggering using a gate signal. Corresponds to API option XSP3_GTIMA_SRC_TTL_VETO_ONLY
  • TTL Both - Corresponds to API option XSP3_GTIMA_SRC_TTL_BOTH
  • LVDS Veto Only - Corresponds to API option XSP3_GTIMA_SRC_LVDS_VETO_ONLY
  • LVDS Both - Corresponds to API option XSP3_GTIMA_SRC_LVDS_BOTH
{P}:StatusMessage_RBV This contains a string to describe the current state of the EPICS driver. Any error should result in a meaningful message in this PV.
{P}:DetectorState_RBV This PV contains the current state of the EPICS driver. See the areaDetector documentation for a list of the possible states. Most of the time the state will be either Idle or Acquire. In the event of an error it will be Error.
{P}:FRAME_COUNT_RBV This contains the number of frames read out of the Xspress 3 each time the driver checks for new data. Only really useful for debugging.
{P}:ArrayCounter_RBV Contains the total number of frames acquired during the current or last acqusition. It is reset to zero at the beginning of the next acqusition. The rate of change of this PV also indicates the frame rate we are operating at.
{P}:ArrayRate_RBV This is a rough indication of the frame rate we are operating at. It is calculated every second, and uses the rate of change of the ArrayCounter_RBV PV.

HDF File Saving

This software makes use of the areaDetector HDF file writing plugin. Full documentation for this is provided here. Some of the most relevant PVs are exposed on the main GUI, and these are detailed below:

{P}:HDF5:Capture
{P}:HDF5:Capture_RBV
Write a 1 to this PV before starting an acqusition. This will trigger the HDF software to start capturing data to write a file, and set {P}:HDF5:Capture_RBV to 1. At the end of the acquisition it is necessary to write a 0 to this PV, unless {P}:HDF5:Capture_RBV has already been set to zero because the required number of frames have been saved.
{P}:HDF5:FilePath
{P}:HDF5:FilePath_RBV
The file system path to use for file saving. If the path exists then {P}:HDF5:FilePathExists_RBV will go to 1.
{P}:HDF5:FilePathExists_RBV A flag indicating if the set file path is valid.
{P}:HDF5:FileName
{P}:HDF5:FileName_RBV
The file name to use.
{P}:HDF5:FileNumber
{P}:HDF5:FileNumber_RBV
This is the index of the next file that will be saved. If using EPICS autosave this will be reset to the last value when the IOC is rebooted.
{P}:HDF5:WriteStatus The status of the file writing. 1=Error. This should be checked at the end of each acqusition, once file saving has completed.
{P}:HDF5:WriteMessage The error message if {P}:HDF5:WriteStatus is 1.
{P}:HDF5:NumCaptured_RBV This is the number of files saved to disk by the areaDetector HDF plugin. At the end of file saving this should equal the number of frames in {P}:ArrayCounter_RBV.

Saving a region of interest (ROI) to disk

In order to save a ROI of data to disk the data is sent through an Epics areaDetector ROI plugin. Full documentation is here. However, the average user need only use the following PVs. For each frame, the data is arranged in an X*Y array. X is energy and Y is channel number. The user can set the start and end point in terms of energy, and which channels to save. It is only possible to save a contiguous range of energy or channels.

These PVs have to be set before the beginning of an acqusition.

{P}:ROIDATA:MinX
{P}:ROIDATA:MinX_RBV
The start point in units of energy bin (0 based)
{P}:ROIDATA:SizeX
{P}:ROIDATA:SizeX_RBV/td>
The size of the energy ROI to save.
{P}:ROIDATA:MinY
{P}:ROIDATA:MinY_RBV
The start point in channel number (0 based, so channel 1 is 0, and channel 8 is 7).
{P}:ROIDATA:SizeY
{P}:ROIDATA:SizeY_RBV
The number of channels to save.

By restricting the energy range that is saved to disk, and the number of channels, the file size can be significantly reduced.

Scaler Data and Window Settings

The following PVs provide access to the scalers over channel access, and allow the user to set scaler related parameters. The 'C1' part of the PV name indicates channel 1. The lists is duplicated for each channel: 'C2', 'C3' etc.

The first table shows the single value PVs that show the latest scaler value during an acqusition.

{P}:C1_SCA0:Value_RBV The Time scaler.
{P}:C1_SCA1:Value_RBV The Reset Ticks scaler.
{P}:C1_SCA2:Value_RBV The Reset Count scaler.
{P}:C1_SCA3:Value_RBV The All Event scaler.
{P}:C1_SCA4:Value_RBV The All Good scaler.
{P}:C1_SCA5:Value_RBV The Scaler 1 scaler. The lower and upper window limits for this are set using {P}:C1_SCA5_LLM and {P}:C1_SCA5_HLM. The window limits are set using API function xsp3_set_window
{P}:C1_SCA6:Value_RBV The Scaler 2 scaler. The lower and upper window limits for this are set using {P}:C1_SCA6_LLM and {P}:C1_SCA6_HLM. The window limits are set using API function xsp3_set_window
{P}:C1_SCA7:Value_RBV The Pileup scaler.

The following table shows the set and read parameters for the All Good, Scaler 1 and Scaler 2 scalers.

{P}:C1_SCA4_THRESHOLD
{P}:C1_SCA4_THRESHOLD_RBV
Set and read the All Good scaler window threshold. This is set using the API function xsp3_set_good_thres The readback value is also read at connection time.
{P}:C1_SCA5_LLM
{P}:C1_SCA5_LLM_RBV
Set and read the Scaler 1 scaler window lower limit. This is set using the API function xsp3_set_window. The readback value is also read at connection time.
{P}:C1_SCA5_HLM
{P}:C1_SCA5_HLM_RBV
Set and read the Scaler 1 scaler window upper limit. This is set using the API function xsp3_set_window The readback value is also read at connection time.
{P}:C1_SCA6_HLM
{P}:C1_SCA6_LLM_RBV
Set and read the Scaler 2 scaler window lower limit. This is set using the API function xsp3_set_window The readback value is also read at connection time.
{P}:C1_SCA6_HLM
{P}:C1_SCA6_HLM_RBV
Set and read the Scaler 2 scaler window upper limit. This is set using the API function xsp3_set_window The readback value is also read at connection time.

The following table shows the scaler data array PVs. These arrays accumulate the scaler data during an acqusition to provide live feedback if needed. At the end of the acqusition the arrays are updated with the final scaler data, providing {P}:UPDATE has been triggered.

{P}:C1_SCA0:ArrayData_RBV The Time scaler array.
{P}:C1_SCA1:ArrayData_RBV The Reset Ticks scaler array.
{P}:C1_SCA2:ArrayData_RBV The Reset Count scaler array.
{P}:C1_SCA3:ArrayData_RBV The All Event scaler array.
{P}:C1_SCA4:ArrayData_RBV The All Good scaler array.
{P}:C1_SCA5:ArrayData_RBV The Scaler 1 scaler array.
{P}:C1_SCA6:ArrayData_RBV The Scaler 2 scaler array.
{P}:C1_SCA7:ArrayData_RBV The Pileup scaler.

The above parameters are saved in the HDF file.

MCA Spectra and ROI Data

The following table lists the array PVs for the MCA spectra, as well as the ROI window settings and readback values. There are 16 regions of interest per channel, so only the PVs for the first one are listed in the table below. The ROI PVs below have 'ROI1' in the name, so simply substute this for 'ROI2', 'ROI3', etc, for the other regions of interest.

The ROI limit PVs have to set before the beginning of an acqusition.

{P}:ARR1:ArrayData The MCA spectra data (dead time corrected, or un-corrected, depending on {P}:CTRL_DTC. This is updated during a scan when a new frame is read out.
{P}:ARRSUM1:ArrayData The cummulative MCA spectra data. This is updated during a scan when a new frame is read out. This is the sum of all the spectra data from {P}:ARR1:ArrayData.
{P}:C1_MCA_ROI1_LLM The lower limit for the first ROI.
{P}:C1_MCA_ROI1_HLM The upper limit for the first ROI.
{P}:C1_ROI1:Value_RBV The ROI readback value for each frame. This is updated during acqusition.
{P}:C1_ROI1:ValueSum_RBV The integrated ROI readback value. This is updated during acqusition.
{P}:C1_ROI1:ArrayData_RBV The ROI reacback array that holds the ROI for every frame from an acqusition. This is updated during acqusition. The PV {P}:C1_ROI1:ValueSum_RBV will hold the integral of the array.
{P}:C1_ROI1:EnableCallbacks This can be used to enable or disable visualization of the ROI data during acqusition. Other PVs are provided that allow the user to globally disable all ROIs per channel, so this is only available for fine control if needed. By default only ROIs 1-4 are enabled by the high level plugin control PVs.

The above parameters are saved in the HDF file. All the MCA spectra arrays are also saved.

The Dead Time Correction Parameters

When the Epics IOC starts up it reads the dead time correction (DTC) parameters for each channel. These are set by the system configuration files supplied with the readout system.

{P}:C1_DTC_FLAGS_RBV The DTC Flags parameter.
{P}:C1_DTC_AEG_RBV The DTC All Good Event Gradient parameter.
{P}:C1_DTC_AEO_RBV The DTC All Good Event Offset parameter.
{P}:C1_DTC_IWG_RBV The DTC In Window Gradient parameter.
{P}:C1_DTC_IWO_RBV The DTC In Window Offset parameter.

The above parameters are saved in the HDF file.

PVs used to enable and disable data visualization during acqusition

There are several PVs provided that allow the user to enable and disable data visualization. This does not affect file saving or ROI calculation, only the online display of the data during an acqusition. This is provided to allow the user to only enable what is needed, as it can be CPU intensive to visualize the data at high frame rates. It has been found that by having too many channels enabled for visualization, or too many ROIs, the data readout rate can drop. For full speed acqusition, turn off all data visualization, or only enable a single channel.

The following PVs are available for each channel. Substitute the number in 'C1' for the other channel numbers.

These PVs have to set before the beginning of an acqusition.

{P}:C1_PluginControlVal This controls the areaDetector plugins responsible for data visualization for channel 1. This includes the spectra, scaler and ROIs 1-4 only. ROIs 5-16 are not affected by this PV. To control ROIs 5-16 use {P}:C1_PluginControlValExtraROI instead.
{P}:C1_PluginControlValExtraROI This controls the areaDetector plugins responsible for data visualization for the ROIs 5-16. These are not always used, which is why they are separated from the PV {P}:C1_PluginControlVal. It would not normally be desirable to automatically enable ROIs 5-16 when a channel is enabled.

Python script to demonstrate basic usage. This uses the DLS Python cothread library to do channel access, which is available here.

#!/bin/env dls-python2.6

# Library version specification required for dls libraris
from pkg_resources import require
import sys
require('cothread==2.8')

import cothread
from cothread.catools import *

base_pv = "mp49:XSP3"
hdf_pv = "mp49:XSP3:HDF5"
timeout_ = 100

num_channels = 4
config_path = "/dls_sw/work/R3.14.11/support/xspress3/xspress3_settings/"
trigger_mode = 3
nd_attributes_file = "//dls_sw/work/R3.14.11/support/xspress3/data/xsp3.xml"
run_flags = 1 #0=normal, 1=playback
file_path = "/tmp/"
file_name = "xsp"

num_frames = 10


def connect():
   print "Connecting..."
   connected = caget(base_pv + ":CONNECTED")
   if (not connected): 
      caput(base_pv + ":NUM_CHANNELS", num_channels, wait=True)
      caput(base_pv + ":CONFIG_PATH", config_path, wait=True, datatype=cothread.catools.DBR_CHAR_STR)
      caput(base_pv + ":RUN_FLAGS", run_flags, wait=True)
      caput(base_pv + ":NDAttributesFile", nd_attributes_file, wait=True, datatype=cothread.catools.DBR_CHAR_STR)
      caput(base_pv + ":CONNECT", 1, wait=True, timeout=timeout_)

def file_setup():
   print "Setting up file parameters..."
   caput(hdf_pv + ":FilePath", file_path, wait=True, datatype=cothread.catools.DBR_CHAR_STR)
   path_exists = caget(hdf_pv + ":FilePathExists_RBV")
   if (not path_exists):
      print "ERROR: file path doesn't exist"
      sys.exit(1)
   caput(hdf_pv + ":FileName", file_name, wait=True, datatype=cothread.catools.DBR_CHAR_STR)
   

def acquire():
   print "Acquire..."
   #Acquire, but don't wait (this only returns when acqusition is complete).
   caput(base_pv + ":Acquire", 1, wait=False)
   #Wait until Acquire_RBV is set (or, in this case, just wait a sec).
   cothread.Sleep(1.0)
   #Now generate the triggers
   cothread.Sleep(1.0) #Or, wait on an event from a different thread

def acquireAndCapture():
   print "Acquire and capture..."
   caput(hdf_pv + ":Capture", 1, wait=False) #Don't wait, this blocks until capture finished.
   #Wait until Capture_RBV is set
   capture_rbv = 0
   while (not capture_rbv):
      capture_rbv = caget(hdf_pv + ":Capture_RBV")
      cothread.Sleep(0.1)
   acquire()
   

def setNumFrames(num_frames):
   print "Set number of frames to " + str(num_frames)
   #Set the number of frames to collect
   caput(base_pv + ":NumImages", num_frames, wait=True)


def main():
   print "Testing Xspress3..."

   #Connect to the Xspress3 (if the IOC has been restarted)  
   connect()

   #Set up trigger mode
   caput(base_pv + ":TriggerMode", trigger_mode, wait=True)

   #Set up file saving plugin
   file_setup()

   #Do we need to set up the plugins by taking a single frame?
   hdf_dims = caget(hdf_pv + ":NDimensions_RBV")
   if (hdf_dims == 0):
      #Take a single frame to set up the plugins
      setNumFrames(1)
      acquire()

   #Erase data
   caput(base_pv + ":ERASE", 1, wait=True)

   #Now do the real data collection
   setNumFrames(num_frames)
   acquireAndCapture()

   #Generate num_frames triggers now

   #Wait on event here, or poll the Acquire_RBV PV
   acquire_rbv = 1
   while(acquire_rbv):
      acquire_rbv = caget(base_pv + ":Acquire_RBV")
      cothread.Sleep(0.1)

   #Acqusition is finished, although file saving might still be progressing in the file saving plugin.

   #Check detector status here
   ad_status = caget(base_pv + ":DetectorState_RBV")
   if (ad_status != 0):
      print "ERROR: data collected failed"
      ad_string = caget(base_pv + ":StatusMessage_RBV")
      print ad_string
      sys.exit(1)

   #Do final update on all visualization arrays
   caput(base_pv + ":UPDATE", 1, wait=True)

   #Check number of frames read out
   num_frames_readout = caget(base_pv + ":ArrayCounter_RBV")
   print "Num frames read out: " + str(num_frames_readout
                                       
   #Wait for file saving to end and check status
   saving = 1
   while (saving):
      saving = caget(hdf_pv + ":Capture_RBV")
      cothread.Sleep(0.1)
   #Check status
   num_captured = caget(hdf_pv + ":NumCaptured_RBV")
   if (num_captured != num_frames):
      print "ERROR: we did not collect all the frames."
      print "num_captured: " + str(num_captured)
   write_status = caget(hdf_pv + ":WriteStatus")
   if (write_status):
      print "ERROR: problem writing file."
      hdf_string = caget(hdf_pv + ":WriteMessage")
      print hdf_string
      sys.exit(1)

   print "Finshed"
   print "Saved " + str(num_captured) + " frames."

if __name__ == "__main__":
        main()
 All Classes Files Functions Defines