diff --git a/documentation/pilatusDoc.html b/documentation/pilatusDoc.html index 8c66356..a0390ba 100755 --- a/documentation/pilatusDoc.html +++ b/documentation/pilatusDoc.html @@ -7,7 +7,7 @@

areaDetector Pilatus driver

- September 21, 2008

+ December 11, 2008

Mark Rivers

@@ -97,7 +97,7 @@ In External Enable mode this value is not used by camserver. However, it should be set larger than the maximum time exposure time from the external source, so that - pilatusROI.st can estimate how long to wait for the data files to be created before + the driver can estimate how long to wait for the data files to be created before timing out. @@ -162,8 +162,7 @@ using the algorithm described for ADFileTemplate under File Saving Parameters in ADStdDriverParams is used as a basename. The following examples show the interpretation of the basename. -
-Basename            Files produced
+          
Basename            Files produced
      
 test6.tif           test6_00000.tif,  test6_00001.tif, ...
 test6_.tif          test6_00000.tif,  test6_00001.tif, ...
@@ -186,7 +185,7 @@ test6_2_0035.tif    test6_2_0035.tif, test6_2_0036.tif, ...
   

Pilatus specific parameters

- The Pilatus driver implements the following parameters in addition to those in ADStdDriverParams.h:. + The Pilatus 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 PilatusDelayTime.

@@ -214,7 +213,8 @@ test6_2_0035.tif test6_2_0035.tif, test6_2_0036.tif, ... - Pilatus
DelayTime + Pilatus
+ DelayTime asynFloat64 @@ -231,7 +231,8 @@ test6_2_0035.tif test6_2_0035.tif, test6_2_0036.tif, ... - Pilatus
Threshold + Pilatus
+ Threshold asynFloat64 @@ -271,7 +272,8 @@ test6_2_0035.tif test6_2_0035.tif, test6_2_0036.tif, ... - Pilatus
Armed + Pilatus
+ Armed asynInt32 @@ -290,7 +292,8 @@ test6_2_0035.tif test6_2_0035.tif, test6_2_0036.tif, ... - Pilatus
TiffTimeout + Pilatus
+ TiffTimeout asynFloat64 @@ -310,7 +313,8 @@ test6_2_0035.tif test6_2_0035.tif, test6_2_0036.tif, ... - Pilatus
BadPixelFile + Pilatus
+ BadPixelFile asynOctet @@ -320,8 +324,7 @@ test6_2_0035.tif test6_2_0035.tif, test6_2_0036.tif, ... a valid bad pixel file then no bad pixel mapping is performed. The bad pixel map is used before making the NDArray callbacks. It does not modify the data in the files that camserver writes. This is a simple ASCII file with the following format: -
-badX1,badY1 replacementX1,replacementY1 
+          
badX1,badY1 replacementX1,replacementY1 
 badX2,badY2 replacementX2,replacementY2
 ...
           
@@ -350,7 +353,8 @@ badX2,badY2 replacementX2,replacementY2 - Pilatus
NumBadPixels + Pilatus
+ NumBadPixels asynInt32 @@ -367,7 +371,8 @@ badX2,badY2 replacementX2,replacementY2 - Pilatus
FlatFieldFile + Pilatus
+ FlatFieldFile asynOctet @@ -379,12 +384,11 @@ badX2,badY2 replacementX2,replacementY2 for spatial non-uniformity in the response of the detector. It should be collected with a spatially uniform intensity on the detector at roughly the same energy as the measurements being corrected. When the flat field file is read, the average - pixel value (averageFlatField) is computed using all pixels with intensities > PilatusMinFlatField. - All pixels with intensity < PilatusMinFlatField in the flat field are replaced with - averageFlatField. When images are collected before the NDArray callbacks are performed - the following per-pixel correction is applied: -
-ImageData[i] = 
+          pixel value (averageFlatField) is computed using all pixels with intensities >
+          PilatusMinFlatField. All pixels with intensity < PilatusMinFlatField in the flat
+          field are replaced with averageFlatField. When images are collected before the NDArray
+          callbacks are performed the following per-pixel correction is applied:
+          
ImageData[i] = 
     (averageFlatField * 
     ImageData[i])/flatField[i];
           
@@ -398,7 +402,8 @@ ImageData[i] = - Pilatus
MinFlatField + Pilatus
+ MinFlatField asynInt32 @@ -417,7 +422,8 @@ ImageData[i] = - Pilatus
FlatFieldValid + Pilatus
+ FlatFieldValid asynInt32 @@ -626,10 +632,10 @@ create_monitor_set("auto_settings.req", 30,"P=13PIL1:,D=cam1:") NDROI8.adl

NDROI8.png

- mca.adl can be used to plot the net or total counts in an ROI when - NImages>1. In this example the plot is the net counts in ROI 1 as the diffractometer - chi was scanned +- 1 degree with 1000 points at .02 seconds/point. This was done - with the SPEC command + mca.adl or mca_small.adl can be used to plot the net or total counts + in an ROI when NImages>1. In this example the plot is the net counts in ROI 1 as + the diffractometer chi was scanned +- 1 degree with 1000 points at .02 seconds/point. + This was done with the SPEC command

lup chi -1 1 1000 .02
 
@@ -638,10 +644,10 @@ create_monitor_set("auto_settings.req", 30,"P=13PIL1:,D=cam1:") motor scan with the Newport XPS putting out pulses every .02 seconds. These pulses triggered the Pilatus in External Enable mode. The Pilatus driver read each TIFF file as it was created and updated this plot every 0.2 seconds. The total time to - collect this scan with 1000 images was 20 seconds.

+ collect this scan with 1000 images was 20.8 seconds.

- mca.adl

+ mca_small.adl pilatusMCA.png

scan_more.adl is used to define a scan. In this example the sscan record @@ -650,24 +656,24 @@ create_monitor_set("auto_settings.req", 30,"P=13PIL1:,D=cam1:")

scan_more.adl

- pilatusROI_scan_more.png
+ pilatusThresholdScanSetup.png

scanDetPlot.adl is used to plot the results of a scan after it is complete. - In this example the total counts in ROI 2 are plotted as a function of the ThresholdEnergy + In this example the total counts in ROI 1 are plotted as a function of the ThresholdEnergy as it was scanned from 3000 to 10000 eV in 250 eV steps. The source was Fe55, and the cut-off is at 6 keV, as expected for the Mn Ka and Mn Kb x-rays that this source produces.

scanDetPlot.adl

- pilatus_scan_plot.png
+ pilatusThresholdScanPlot.png

asynRecord.adl is used to control the debugging information printed - by the asyn TCP/IP driver (asynTraceIODriver) and the SNL program (asynTraceIODevice).

+ by the asyn TCP/IP driver for camserver (asynTraceIODriver).

asynRecord.adl

- pilatusAsynRecord.png
+ pilatusAsyn.png

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

@@ -684,9 +690,13 @@ create_monitor_set("auto_settings.req", 30,"P=13PIL1:,D=cam1:") in both traditional step-scanning mode, as well as in trajectory scanning mode. Here are some snippets from the SPEC macros for the Pilatus. We can supply the source files on request.

-
# need some more globals (kludge)
-global    PILATUS_ROI_PV    
-global    PILATUS_imgPATH_PV
+  
  # need some more globals (kludge)
+global    PILATUS_ROI_PV   
+global    PILATUS_ROI_ARRAY_PV 
+global    PILATUS_ROI_ARRAY_START_PV
+global    PILATUS_ROI_ARRAY_NUSE_PV
+global    PILATUS_ROI_ARRAY_ACQ_PV
+global    PILATUS_IMGPATH_PV
 global    PILATUS_FNAME_PV
 global    PILATUS_FILENUMBER_PV
 global    PILATUS_FILEFORMAT_PV
@@ -695,60 +705,119 @@ global    PILATUS_NFRAME_PV
 global    PILATUS_EXPPRD_PV
 global    PILATUS_NEXPFRM_PV
 global    PILATUS_ACQ_PV
+global    PILATUS_ARMED_PV
+global    PILATUS_ABORT_PV
 global    PILATUS_ACQMODE_PV
+global    PILATUS_READOUT_TIME
+
+global    PILATUS_ROI_0_MinX_PV
+global    PILATUS_ROI_0_SizeX_PV
+global    PILATUS_ROI_0_MinY_PV
+global    PILATUS_ROI_0_SizeY_PV
+
 
 ###############################################################
 def _setup_img '{
-     local j, str
-		
-     # PILATUS_PREFIX should be detector aquisition pv (GSE-PILATUS1:)
+...          
+     # PILATUS_PREFIX detector name i.e. (GSE-PILATUS1:)
      if ( PILATUS_PREFIX == "") PILATUS_PREFIX = "GSE-PILATUS1:"
-     PILATUS_PREFIX = getval("Enter PILATUS pv prefix",PILATUS_PREFIX)
+     PILATUS_PREFIX = getsval("Enter PILATUS detector name i.e. GSE-PILATUS1:",PILATUS_PREFIX)
 
-     # rois pvs
-     PILATUS_ROI_PV    = PILATUS_PREFIX "ROI1NetCounts"
-     PILATUS_imgPATH_PV = PILATUS_PREFIX "FilePath"
-     PILATUS_FNAME_PV   = PILATUS_PREFIX "Filename"
-     PILATUS_FILENUMBER_PV   = PILATUS_PREFIX "FileNumber"
-     PILATUS_FILEFORMAT_PV = PILATUS_PREFIX "FileFormat"
-     PILATUS_EXPSRTM_PV = PILATUS_PREFIX "ExposureTime"
-     PILATUS_NFRAME_PV  = PILATUS_PREFIX "NImages"
-     PILATUS_EXPPRD_PV  = PILATUS_PREFIX "ExposurePeriod"
-     PILATUS_NEXPFRM_PV = PILATUS_PREFIX "NExposures"
-     PILATUS_ACQ_PV     = PILATUS_PREFIX "Acquire"
-     PILATUS_ACQMODE_PV = PILATUS_PREFIX "AcquireMode"
+     # PILATUS_DET_PREFIX is the pv used by areaDetector to identify a specific detector.
+     # When only one detector is used it is usally (cam1:)
+     if ( PILATUS_DET_PREFIX == "") PILATUS_DET_PREFIX = "cam1:"
+     PILATUS_DET_PREFIX = getsval("Enter PILATUS specific detector name i.e. cam1:",PILATUS_DET_PREFIX)
+
+     # PILATUS_ROI_PREFIX is the pv used by areaDetector to identify a specific a ROI plugin.
+     # When only one ROI plugin is used it is usally (ROI1:)
+     if ( PILATUS_ROI_PREFIX == "") PILATUS_DET_PREFIX = "ROI1:"
+     PILATUS_ROI_PREFIX = getsval("Enter PILATUS ROI plugin name i.e. ROI1:",PILATUS_ROI_PREFIX)
+     
+     if (PILATUS_MOUNT == "") PILATUS_MOUNT = "cars5/Data"
+     PILATUS_MOUNT = getsval("Enter mount point relative to camserver home directory",PILATUS_MOUNT)
+     if (PILATUS_SPEC_MOUNT == "") PILATUS_SPEC_MOUNT = "cars5/Data"
+     PILATUS_SPEC_MOUNT = getsval("Enter mount point relative to spec home directory",PILATUS_SPEC_MOUNT) 
+...
+     PILATUS_ROI_PV             = PILATUS_PREFIX PILATUS_ROI_PREFIX "0:Net_RBV"
+     PILATUS_ROI_ARRAY_PV       = PILATUS_PREFIX PILATUS_ROI_PREFIX "0:NetArray"
+     PILATUS_ROI_ARRAY_START_PV = PILATUS_PREFIX PILATUS_ROI_PREFIX "0:NetArrayEraseStart"
+     PILATUS_ROI_ARRAY_NUSE_PV  = PILATUS_PREFIX PILATUS_ROI_PREFIX "0:NetArray.NUSE"
+     PILATUS_ROI_ARRAY_ACQ_PV   = PILATUS_PREFIX PILATUS_ROI_PREFIX "0:NetArray.ACQG"
+     PILATUS_IMGPATH_PV         = PILATUS_PREFIX PILATUS_DET_PREFIX "FilePath"
+     PILATUS_FNAME_PV           = PILATUS_PREFIX PILATUS_DET_PREFIX "FileName"
+     PILATUS_FILENUMBER_PV      = PILATUS_PREFIX PILATUS_DET_PREFIX "FileNumber"
+     PILATUS_FILEFORMAT_PV      = PILATUS_PREFIX PILATUS_DET_PREFIX "FileTemplate"
+     PILATUS_EXPSRTM_PV         = PILATUS_PREFIX PILATUS_DET_PREFIX "AcquireTime"
+     PILATUS_NFRAME_PV          = PILATUS_PREFIX PILATUS_DET_PREFIX "NumImages"
+     PILATUS_EXPPRD_PV          = PILATUS_PREFIX PILATUS_DET_PREFIX "AcquirePeriod"
+     PILATUS_NEXPFRM_PV         = PILATUS_PREFIX PILATUS_DET_PREFIX "NumExposures"
+     PILATUS_ACQ_PV             = PILATUS_PREFIX PILATUS_DET_PREFIX "Acquire"
+     PILATUS_ARMED_PV           = PILATUS_PREFIX PILATUS_DET_PREFIX "Armed"
+     PILATUS_ABORT_PV           = PILATUS_PREFIX PILATUS_DET_PREFIX "Acquire"
+     PILATUS_ACQMODE_PV         = PILATUS_PREFIX PILATUS_DET_PREFIX "TriggerMode"
+     PILATUS_THRESHOLD_PV       = PILATUS_PREFIX PILATUS_DET_PREFIX "ThresholdEnergy"
+     PILATUS_ROI_0_MinX_PV      = PILATUS_PREFIX PILATUS_ROI_PREFIX "0:MinX"
+     PILATUS_ROI_0_SizeX_PV     = PILATUS_PREFIX PILATUS_ROI_PREFIX "0:SizeX"
+     PILATUS_ROI_0_MinY_PV      = PILATUS_PREFIX PILATUS_ROI_PREFIX "0:MinY"
+     PILATUS_ROI_0_SizeY_PV     = PILATUS_PREFIX PILATUS_ROI_PREFIX "0:SizeY"
+     PILATUS_ROI_0_BgdWidth_PV  = PILATUS_PREFIX PILATUS_ROI_PREFIX "0:BgdWidth"
 ...
 
 def epics_pilatus_count '{
 ...
-     # write to data base fields
-     # Need to convert path from string to byte array
-     # Note: we use the "wait" parameter in epics_put here (new to spec5.7.02) so that
-     # it uses ca_put_callback, to know that all PVs have been processed
-     # before we start counting.  Use 1 second timeout, will actually be
-     # much faster than this unless something is wrong.
-     array _temp[256]
-     _temp = PILATUS_IMAGE_DIR
-     # Do not change path for now
-     #epics_put(PILATUS_imgPATH_PV,_temp, 1)
-     epics_put(PILATUS_FNAME_PV,img_fname, 1)
+     # Call macro that creates and set the Pilatus path and filename
+     img_full_filename
+
+     # Setup exposure time, collection mode and number of frames
      epics_put(PILATUS_FILENUMBER_PV,NPTS, 1)
-     epics_put(PILATUS_FILEFORMAT_PV,_fileformat, 1)
-     epics_put(sc_prtm_pv,cnt_time_val, 1)
-     epics_put(PILATUS_EXPSRTM_PV,cnt_time_val, 1)
-     epics_put(PILATUS_ACQMODE_PV,0, 1)  # Internal trigger 
      epics_put(PILATUS_NFRAME_PV, 1, 1)
+     epics_put(PILATUS_ACQMODE_PV,0, 1)  # Internal trigger
+     epics_put(PILATUS_EXPSRTM_PV,cnt_time_val, 1)
      epics_put(PILATUS_NEXPFRM_PV, 1, 1)
 
+...
+     # hit the triggers
+     epics_put(PILATUS_ACQ_PV,1)
+
+     epics_put(sc_cnt_pv,1)
+
+     # wait for scaler and Pilatus AQG to finish
+     status     = 1
+     sc_done    = FALSE
+     img_done   = FALSE
+     data_done  = FALSE
+     while(status){
+         # is the scalar done
+        if (epics_get(sc_cnt_pv)=="Done"){
+             sc_done = TRUE;
+             #p "scaler done"
+        }
+
+        # is the pilatus done
+        if (epics_get(PILATUS_ACQ_PV) == "Done"){
+            img_done = TRUE;
+            #p "image collection done"
+        }
+
+        if( (sc_done==TRUE) && (img_done==TRUE)) break;
+        sleep(0.01)
+     }
+
+    
+     # use the get_counts routine to read the scalers
+     # note get_counts also calls user_getcounts
+     # thats where the rois get read.
+     get_counts  
+}'
+
 
 def user_getcounts '{
-    local pv_roi, j, pv
-
 ...
-   # using image_count routine  
+    # using image_count routine
     } else if ( EPICS_COUNT == 4 ) {
         S[iroi] = 0
         S[iroi] = epics_get(PILATUS_ROI_PV)
+
 

Performance measurements

@@ -761,7 +830,7 @@ def user_getcounts '{ was measured using the EPICS camonitor program. It printed the time when acquisition was started (Acquire changed to Acquire=1) and when acquisition was complete (Acquire changed to Done=0). The time was 10.022 seconds. This includes the time for camserver - to save all 1000 images to disk (366 MB), and for pilatusROI to read each file, + to save all 1000 images to disk (366 MB), and for the driver to read each file, correct the bad pixels and flat field, compute the ROIs, and post the ROIs to EPICS. It also posted all of the images to EPICS. The total additional time was less than 0.03 seconds for all 1000 images. @@ -772,7 +841,7 @@ def user_getcounts '{ collect each file. If there were no overhead then time to collect this series should be exactly 10.0 seconds. The actual time measured using the EPICS camonitor program was 45.514 seconds. The overhead is thus 35.514 seconds, or 35 ms per point. In - this single-frame mode pilatusROI is thus able to collect >20 images/second. For + this single-frame mode the driver is thus able to collect >20 images/second. For comparison, another measurement was done using the same EPICS sscan record, but using a Joerger VSC16 scaler as the detector trigger and detector. The preset time was also .01 seconds. The elapsed time for a 1000 point scan was 16.068 seconds, @@ -781,41 +850,38 @@ def user_getcounts '{ 1000 points using trajectory scanning mode with the Newport XPS motor controller. The following SPEC command was used: -
      lup chi -2 2 1000 .015
+      
      lup chi -1 1 1000 .02
       
This tells SPEC to do a relative scan of the chi axis from -2 degrees to +2 degrees with 1000 points at .015 seconds/point. On our kappa diffractometer this entails a coordinated motion of the phi, kappa and omega axes. The EPICS trajectory scanning software downloads the non-linear trajectory that SPEC computes into the XPS controller, which executes it. As the motors are moving the XPS outputs synchronization pulses - at the period of the collection time, .015 seconds in this case. These pulses are - stretched (see Hardware notes below) and used as the - external input to the Pilatus. The time to execute this scan should be 15.0 seconds. - The actual time was 16.3 seconds, measured using camonitor on the Acquire PV. Again, - this includes the time for camserver to save all 1000 images to disk (366 MB), and - for pilatusROI to read each file, correct the bad pixels and flat field, compute - the ROIs, and post the ROIs to EPICS. It also posted the images to EPICS at 1Hz - (15 images total). The total additional time was less than 1.3 seconds for all 1000 - images. As soon as the acquisition was complete SPEC plotted the net counts in the - first ROI (containing the Bragg peak) as follows: + at the period of the collection time, .020 seconds in this case. These pulses are + used as the external trigger to the Pilatus. The time to execute this scan should + be 20.0 seconds. The actual time was 20.8 seconds, measured using camonitor on the + Acquire PV. Again, this includes the time for camserver to save all 1000 images + to disk (366 MB), and for the Pilatus driver to read each file, correct the bad + pixels and flat field, compute the ROIs, and post the ROIs to EPICS. It also posted + all of the images to EPICS. The total additional time was less than 0.8 seconds + for all 1000 images. As soon as the acquisition was complete SPEC plotted the net + counts in the first ROI (containing the Bragg peak) as follows:

- 1000 point SPEC scan with 15 ms per point collected in 16.3 seconds

- pilatusROI_spec.png
+ 1000 point SPEC scan with 20 ms per point collected in 20.8 seconds + pilatusSPEC.png

For comparison this identical scan was executed in traditional step-scanning mode, where the motors stopped at each point in the scan. The Pilatus was run in Internal - mode with NImages=1. The total time for the scan was 870 seconds (more than 14 minutes), - compared to 16.3 seconds in trajectory mode. Most of this overhead is the settling - time for the motors, with only a small fraction due to the Pilatus single-exposure - mode. The trajectory scanning mode is thus more than 50 times faster to execute - the identical SPEC scan. + mode with NumImages=1. The total time for the scan was 870 seconds (more than 14 + minutes), compared to 20.8 seconds in trajectory mode. Most of this overhead is + the settling time for the motors, with only a small fraction due to the Pilatus + single-exposure mode. The trajectory scanning mode is thus more than 50 times faster + to execute the identical SPEC scan.

-  

-

- Hardware notes

+

Trigger pulses

@@ -893,13 +959,13 @@ def user_getcounts '{

Restrictions

- The following are some current restrictions of the pilatusROI SNL program:

+ The following are some current restrictions of the areaDetector Pilatus driver: