areaDetector MarCCD driver

November 24, 2008

Mark Rivers

University of Chicago

Table of Contents

Introduction

This is a driver for the MarCCD detectors from Rayonix/MarUSA. It inherits from ADDriver and implements many of the parameters in ADStdDriverParams.h. It also implements a number of parameters that are specific to the MarCCD detectors.

The interface to the detector is via a TCP/IP socket interface to the marccd_server_socket server that MarUSA provides. The marccd_server_socket program must be started before the areaDetector software is started, by running the marccd program and executing Acquire/Remote Control/Start.

marccd must be using Version 1 of the remote protocol. This is normally done done by editing the file marccd/configuration/marccd.conf and replacing the line

include marccd_server_v0.conf
    

with

include marccd_server_v1.conf
    

The file marccd_server_v1.conf should contain the lines:

remote_mode_server_command /home/marccd/contrib/marccd_server/marccd_server_socket
remote_mode_server_arguments 2222
    

The first line points to the location of the marccd_server_socket program that is used to implement remote control. In order to work with the areaDetector driver this must be a version of this program created after November 11, 2008 when support for the get_frameshift command was added. A recent version of this program can be downloaded from the Rayonix FTP site.

The marccd program saves the data to disk as TIFF files. The areaDetector software reads these disk files in order to read the data, because marccd does not provide another mechanism to access the data.

Implementation of standard driver parameters

The following table describes how the MarCCD driver implements some of the standard driver parameters.

Implementation of Parameters in ADStdDriverParams.h and EPICS Record Definitions in ADBase.template and NDFile.template
Enum name EPICS record name Description
ADFrameType $(P$(R)FrameType The driver redefines the choices for the ADFrameType parameter (record $(P)$(R)FrameType) from ADStdDriverParams.h. The choices for the MarCCD are:
  • Normal (corrected data frame without double correlation)
  • Background (background frame with 0 exposure time, done with double correlation to remove zingers)
  • Raw (data frame without correction for background or spatial distortion)
  • DblCorrelation (two images each collected for half the nominal acquisition time, zingers removed by double correlation)
ADNumImages $(P$(R)NumImages Controls the number of images to acquire when ADImageMode is ADImageMultiple.
ADAcquirePeriod $(P$(R)AcquirePeriod Controls the period between images when ADImageMode is ADImageMultiple or ADImageContinuous. If this is greater than the acquisition time plus readout overhead then the driver will wait until the period has elapsed before starting the next acquisition.
ADFilePath $(P$(R)FilePath Controls the path for saving images. It must be a valid path for marccd and for the areaDetector driver, which is normally running in an EPICS IOC. If marccd and the EPICS IOC are not running on the same machine then soft links will typically be used to make the paths look identical.
ADFileFormat $(P)$(R)FileFormat marccd only supports TIFF files.

It is useful to use NDPluginROI to define an ROI containing the entire marccd detector. The MaxValue_RBV PV in this ROI can be monitored to make sure that the 16-bit limit of 65,535 is not being approached in any pixel.

MarCCD specific parameters

The MarCCD driver implements the following parameters in addition to those in ADStdDriverParams.h. Note that to reduce the width of this table the enum names have been split into 2 lines, but these are just a single name, for example marCCDState.

Parameter Definitions in marccd.cpp and EPICS Record Definitions in marccd.template
Enum name asyn interface Access Description drvUser string EPICS record name EPICS record type
Status parameters
marCCD
State
asynInt32 r/o State word returned by marccd server. The low-order 4-bits of this word are the state of the marccd server, and will be Idle (0x0), Error (0x7), or Busy (0x8). The next 20 bits encode the state of the 5 server tasks (Acquire, Readout, Correct, Save, Dezinger) with 4-bits per task. Each task can be in the state Idle (0x0), Queued (0x1), Executing (0x2), Error (0x4), or Reserved (0x8). MAR_STATE $(P)$(R)MarState_RBV longin
marCCD
Status
asynInt32 r/o Status of the marccd server task (Idle, Error, or Busy) MAR_STATUS $(P)$(R)MarStatus_RBV mbbi
marCCDTask
AcquireStatus
asynInt32 r/o Status of the marccd server acquire task (Idle, Queued, Executing, Error, or Reserved) MAR_ACQUIRE_STATUS $(P)$(R)MarAcquireStatus_RBV mbbi
marCCDTask
ReadoutStatus
asynInt32 r/o Status of the marccd server readout task (Idle, Queued, Executing, Error, or Reserved) MAR_READOUT_STATUS $(P)$(R)MarReadoutStatus_RBV mbbi
marCCDTask
CorrectStatus
asynInt32 r/o Status of the marccd server correct task (Idle, Queued, Executing, Error, or Reserved) MAR_CORRECT_STATUS $(P)$(R)MarCorrectStatus_RBV mbbi
marCCDTask
WritingStatus
asynInt32 r/o Status of the marccd server file writing task (Idle, Queued, Executing, Error, or Reserved) MAR_WRITING_STATUS $(P)$(R)MarWritingStatus_RBV mbbi
marCCDTask
DezingerStatus
asynInt32 r/o Status of the marccd server dezinger task (Idle, Queued, Executing, Error, or Reserved) MAR_DEZINGER_STATUS $(P)$(R)MarDezingerStatus_RBV mbbi
marCCD
ReadStatus
asynInt32 r/w Writing 1 to this parameter causes the status to be read from the marccd server. By processing or periodically scanning this record the status information can be refreshed. This is normally not necessary, but if ADArrayCallbacks is 0 and marCCDOverlap is 1 then the status will not indicate that the system is idle when acquisition is complete, because the driver polling stops before the file is written. This record can be used to eliminate the confusion that might cause. MAR_READ_STATUS $(P)$(R)MarReadStatus bo
Optimization parameters
marCCD
Overlap
asynInt32 r/w The marccd server has 5 tasks (Acquire, Readout, Correct, Write, Dezinger) that can overlap their operation. The areaDetector driver can exploit this to improve performance in some circumstances. If this parameter is set to 1 (Overlap) then the ADAcquire parameter will go to 0 (Done) when the Readout task is done executing, but before the Correct and Write tasks have finished correcting and saving the file to disk. This improves performance because the next image can begin as soon as ADAcquire goes to done, and hence before the previous image is written to disk. Note, however that this parameter must be set to 0 (Sequential) if callbacks are being used to compute ROIs that are being used in data collection, e.g. in a scan. If this is not done then the ROI information will be grabbed before it is updated and incorrect scan data will result. MAR_OVERLAP $(P)$(R)OverlapMode
$(P)$(R)OverlapMode_RBV
bo
bi
Frameshift parameters
marCCD
Frameshift
asynInt32 r/w marccd can be used for time-resolved studies by collecting multiple data sets before reading out the detector. This is done by placing a mask in front of the detector that restricts the x-rays to horizontal stripe. An exposure is made, and then an external signal causes the detector to shift the image by the number of lines given by this parameter. A number of images separated by times of a few milliseconds can be collected, and then the detector is read out. Set this parameter to 0 to disable frameshift mode. MAR_FRAME_SHIFT $(P)$(R)FrameShift
$(P)$(R)FrameShift_RBV
longout
longin
Timeout parameters
marCCD
TiffTimeout
asynFloat64 r/w Timeout in seconds when reading a TIFF file. It should be set to several seconds, because there it can take some time for the marccd server to write the file. MAR_TIFF_TIMEOUT $(P)$(R)ReadTiffTimeout ao
Ancillary parameters. These parameters are written to the header of the marccd TIFF file.
marCCD
DetectorDistance
asynFloat64 r/w Distance from the sample to the detector (mm) MAR_DETECTOR_DISTANCE $(P)$(R)DetectorDistance ao
marCCD
BeamX
asynFloat64 r/w X position of the direct beam on the detector (mm) MAR_BEAM_X $(P)$(R)BeamX ao
marCCD
BeamY
asynFloat64 r/w Y position of the direct beam on the detector (mm) MAR_BEAM_Y $(P)$(R)BeamY ao
marCCD
StartPhi
asynFloat64 r/w Starting value of phi rotation (deg) MAR_START_PHI $(P)$(R)StartPhi ao
marCCD
RotationAxis
asynOctet r/w Rotation axis being used (phi, omega, etc.) MAR_ROTATION_AXIS $(P)$(R)RotationAxis ao
marCCD
RotationRange
asynFloat64 r/w Rotation range of the rotation axis. MAR_ROTATION_RANGE $(P)$(R)RotationRange ao
Debugging
N/A N/A N/A asyn record to control debugging communication with marccd_server_socket program N/A $(P)$(R)marSserverAsyn asyn

Unsupported standard driver parameters

The MarCCD driver does not support the following standard driver parameters because they are not supported in the marccd program:

Configuration

The MarCCD driver is created with the following command, either from C/C++ or from the EPICS IOC shell.

   
marCCDConfig(const char *portName, const char *marCCDPort, 
             int maxBuffers, size_t maxMemory);
  
Argument Description
portName The name of the asyn port for this detector.
marCCDPort The name of the asyn TCP/IP port to communicate with marccd_server_socket. This must have been previously created with drvAsynIPPortConfig(),
maxBuffers Maximum number of buffers to be created for plugin callbacks. Passed to the constructor for the ADDriver base class.
maxMemory Maximum number of bytes of memory to be allocated for plugin callbacks. Passed to the constructor for the ADDriver base class.

The following is an example st.cmd startup script:

< envPaths
errlogInit(20000)

dbLoadDatabase("$(AREA_DETECTOR)/dbd/marCCDApp.dbd")
marCCDApp_registerRecordDeviceDriver(pdbbase) 

###
# Create the asyn port to talk to the MAR on port 2222
drvAsynIPPortConfigure("marServer","gse-marccd2.cars.aps.anl.gov:2222")
# Set the input and output terminators.
asynOctetSetInputEos("marServer", 0, "\n")
asynOctetSetOutputEos("marServer", 0, "\n")
#asynSetTraceMask("marServer",0,9)
asynSetTraceIOMask("marServer",0,2)

marCCDConfig("MAR", "marServer", 20, 200000000)
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/ADBase.template",  "P=13MARCCD1:,R=cam1:,PORT=MAR,ADDR=0,TIMEOUT=1")
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/marCCD.template","P=13MARCCD1:,R=cam1:,PORT=MAR,ADDR=0,TIMEOUT=1,MARSERVER_PORT=marServer")
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/NDFile.template","P=13MARCCD1:,R=cam1:,PORT=MAR,ADDR=0,TIMEOUT=1")

# Create a standard arrays plugin
drvNDStdArraysConfigure("MARImage", 5, 0, "MAR", 0, -1)
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/NDPluginBase.template","P=13MARCCD1:,R=image1:,PORT=MARImage,ADDR=0,TIMEOUT=1,NDARRAY_PORT=MAR,NDARRAY_ADDR=0")
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/NDStdArrays.template", "P=13MARCCD1:,R=image1:,PORT=MARImage,ADDR=0,TIMEOUT=1,SIZE=16,FTVL=SHORT,NELEMENTS=1200000")

# Create an ROI plugin
drvNDROIConfigure("MARROI", 5, 0, "MAR", 0, 10, -1)
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/NDPluginBase.template","P=13MARCCD1:,R=ROI1:,  PORT=MARROI,ADDR=0,TIMEOUT=1,NDARRAY_PORT=MAR,NDARRAY_ADDR=0")
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/NDROI.template",       "P=13MARCCD1:,R=ROI1:,  PORT=MARROI,ADDR=0,TIMEOUT=1")
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/NDROIN.template",      "P=13MARCCD1:,R=ROI1:0:,PORT=MARROI,ADDR=0,TIMEOUT=1,HIST_SIZE=256")
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/NDROIN.template",      "P=13MARCCD1:,R=ROI1:1:,PORT=MARROI,ADDR=1,TIMEOUT=1,HIST_SIZE=256")
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/NDROIN.template",      "P=13MARCCD1:,R=ROI1:2:,PORT=MARROI,ADDR=2,TIMEOUT=1,HIST_SIZE=256")
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/NDROIN.template",      "P=13MARCCD1:,R=ROI1:3:,PORT=MARROI,ADDR=3,TIMEOUT=1,HIST_SIZE=256")
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/NDROIN.template",      "P=13MARCCD1:,R=ROI1:4:,PORT=MARROI,ADDR=3,TIMEOUT=1,HIST_SIZE=256")
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/NDROIN.template",      "P=13MARCCD1:,R=ROI1:5:,PORT=MARROI,ADDR=3,TIMEOUT=1,HIST_SIZE=256")
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/NDROIN.template",      "P=13MARCCD1:,R=ROI1:6:,PORT=MARROI,ADDR=3,TIMEOUT=1,HIST_SIZE=256")
dbLoadRecords("$(AREA_DETECTOR)/ADApp/Db/NDROIN.template",      "P=13MARCCD1:,R=ROI1:7:,PORT=MARROI,ADDR=3,TIMEOUT=1,HIST_SIZE=256")

# Create "fastSweep" drivers for the MCA record to do on-the-fly scanning of ROI data
initFastSweep("MARSweepTotal", "MARROI", 8, 2048, "TOTAL_ARRAY", "CALLBACK_PERIOD")
initFastSweep("MARSweepNet", "MARROI", 8, 2048, "NET_ARRAY", "CALLBACK_PERIOD")

# Load MCA records for the fast sweep drivers
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:0:TotalArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepTotal 0)")
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:1:TotalArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepTotal 1)")
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:2:TotalArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepTotal 2)")
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:3:TotalArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepTotal 3)")
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:4:TotalArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepTotal 4)")
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:5:TotalArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepTotal 5)")
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:6:TotalArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepTotal 6)")
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:7:TotalArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepTotal 7)")

dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:0:NetArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepNet 0)")
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:1:NetArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepNet 1)")
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:2:NetArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepNet 2)")
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:3:NetArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepNet 3)")
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:4:NetArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepNet 4)")
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:5:NetArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepNet 5)")
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:6:NetArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepNet 6)")
dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=13MARCCD1:,M=ROI1:7:NetArray,DTYP=asynMCA,NCHAN=2048,INP=@asyn(MARSweepNet 7)")


#asynSetTraceMask("MARROI",0,3)
#asynSetTraceIOMask("MARROI",0,4)

# Load scan records
dbLoadRecords("$(SSCAN)/sscanApp/Db/scan.db", "P=13MARCCD1:cam1:,MAXPTS1=2000,MAXPTS2=200,MAXPTS3=20,MAXPTS4=10,MAXPTSH=10")

set_requestfile_path("./")
set_savefile_path("./autosave")
set_requestfile_path("$(AREA_DETECTOR)/ADApp/Db")
set_requestfile_path("$(SSCAN)/sscanApp/Db")
set_pass0_restoreFile("auto_settings.sav")
set_pass1_restoreFile("auto_settings.sav")
save_restoreSet_status_prefix("13MARCCD1:")
dbLoadRecords("$(AUTOSAVE)/asApp/Db/save_restoreStatus.db", "P=13MARCCD1:")

iocInit()

# save things every thirty seconds
create_monitor_set("auto_settings.req", 30,"P=13MARCCD1:,D=cam1:")

MEDM screens

The following show the MEDM screens that are used to control the MarCCD detector. Note that the general purpose screen ADBase.adl can be used, but it exposes many controls that are not applicable to the MarCCD, and lacks some fields that are important for the MarCCD.

marccd.adl is the main screen used to control the MarCCD driver.

marccd.adl

marCCD.png

marccdAncillary.adl is the screen used to input ancillary information that is written to the MarCCD TIFF files.

marccdAncillary.adl

MarCCDAncillary.png

asynRecord.adl is used to control the debugging information printed by the asyn TCP/IP driver (asynTraceIODriver) and the EPICS device support (asynTraceIODevice).

asynRecord.adl

MarCCDAsynRecord.png

asynOctet.adl can be used to send any command to the marccd remote server and display the response. It can be loaded from the More menu in asynRecord.adl above.

asynOctet.adl

MarCCDAsynOctet.png

Performance measurements

The following measurements were done to demonstrate the performance that can be obtained with the areaDetector MarCCD driver. These measurements were made with a MAR-165 CCD. The EPICS IOC was running on the same Linux machine as the marccd program. The acquisition time was 1 second.

Binning Image size marCCDOverlap Time for 10 images Overhead per image Time per task
2x2 2048x2048 Sequential 50.0 4.00 Readout: 3.02
Correct: 0.56
Save: 0.20
2x2 2048x2048 Overlap 46.2 3.62 Same
4x4 1024x1024 Sequential 29.0 1.90 Readout: 1.30
Correct: 0.28
Save: 0.06
4x4 1024x1024 Overlap 28.7 1.87 Same
8x8 512x512 Sequential 24.0 1.40 Readout: 0.78
Correct: 0.29
Save: 0.06
8x8 512x512 Overlap 23.6 1.36 Same

Restrictions

The following are some current restrictions of the MarCCD driver: