Content

Problem

In Run 18 planned on Aug 2019 the new single-piece 4M Jungfrau detector is going to be used with a couple of controllers. In daq and psana it will be seen as two independent detectors, i.e. MfxEndstation.0:Jungfrau.0 and 1. It seems natural to process data of these two detectors as a single piece. To make it feasible class AreaDetectorCompound was developed with functionality as explained in this note.

Details of implementation

Class AreaDetectorCompound constructor receives as input parameter a list of detector names which need to be processed together. From this list it generates a list of AreaDetector objects, which is used to wrap most of  AreaDetector interface methods. Wrapping methods concatenates numpy arrays for the 3-rd to last index, assuming that two last index describes 2-d AreaDetector. This type of concatenation can be done for identical two last indexes, e.g. for Jungfrau

raw or calib arrays:           (2, 512, 1024) (+)    (1, 512, 1024) (=)    (3, 512, 1024)
pedestals, gain and offset: (3, 2, 512, 1024) (+) (3, 1, 512, 1024) (=) (3, 3, 512, 1024)

Generalized methods from Detector interface

methods returning concatenated arrays

 raw, calib, pedestals, rms, gain, offset, bkgd, status, mask, photons,

 coords_x, coords_y, coords_z,

 indexes_x, indexes_y, indexes_z,

 common_mode_correction, common_mode_apply,

 mask_geo, mask_comb, mask_edges, mask_neighbors, mask_calib,

 datast, status_as_mask, gain_mask, gain_mask_non_zero, areas

methods returning a couple of concatenated arrays

 coords_xy, indexes_xy, indexes_xy_at_z

methods returning a list of per detector values

 list_raw, list_calib, list_shape, list_size, list_ndim, list_common_mode, list_geometry

re-implemented methods

 common_mode - returns array of the common mode parameters

Difference between compound and regular detector

Detector interface provides for user uniform access to any detector data and hides specific detector complexity. The same is valid for compound detector. There is a couple of differences too keep in mind.

  • the 1-st parameter of Detector class object should be
    • detector name in regular case
    • string or list of detector names in case of compound detector
  • calibration constants for compound detector components needs to be calibrated and provided separately. All data access and processing methods work for separate detectors and their output arrays are concatenated at return.

Code example

Compound Detector object creation

There are a few options of the detector object initialization usyng class AreaDetectorCompound directly or through the standard Detector factory.

Detector is a standard wrapper for all LCLS detectors including AreaDetectorCompound. Compound detector object can be created usind generic Detector, e.g.

import psana
# DataSource object MUST be defined before Detector.
ds = psana.DataSource(dsname) # i.e. dsname='exp=xpptut15:run=460'
det = psana.Detector(<str-or-list-of-derector-names>)

Example of direct AreaDetectorCompound object initialization:

from Detector.AreaDetectorCompound import AreaDetectorCompound
det = AreaDetectorCompound(<str-or-list-of-derector-names>, env)

Input parameters

Parammeter <str-or-list-of-derector-names> can be the space separated string of detector names prepended by keyword 'compound', e.g.

'compound MecTargetChamber.0:Cspad2x2.1 MecTargetChamber.0:Cspad2x2.2 MecTargetChamber.0:Cspad2x2.3'

or just a list of detector names, e.g.

['MecTargetChamber.0:Cspad2x2.1', 'MecTargetChamber.0:Cspad2x2.2', 'MecTargetChamber.0:Cspad2x2.3']

Second parameter, env = ds.env(), is mandatory for AreaDetectorCompound and is optional for Detector (passed from  DataSource initialization).

Complete example

### Direct usage:
# from Detector.AreaDetectorCompound import AreaDetectorCompound
# det = AreaDetectorCompound(..., env)

import psana
from Detector.GlobalUtils import print_ndarr

ds = psana.DataSource('exp=xpptut15:run=460')

# Make Detector object using:
# space separated string of detector names prepended by 'compound':
det = psana.Detector('compound MecTargetChamber.0:Cspad2x2.1'\
                             ' MecTargetChamber.0:Cspad2x2.2'\
                             ' MecTargetChamber.0:Cspad2x2.3')

# or list of string detector names:
det = psana.Detector(['MecTargetChamber.0:Cspad2x2.1',\
                      'MecTargetChamber.0:Cspad2x2.2',\
                      'MecTargetChamber.0:Cspad2x2.3'])

env = ds.env()
evt = ds.events().next()
rnum = evt.run()

if True :
    print 'rnum     :', rnum
    print 'calibdir :', str(env.calibDir())
    print 'size     :', str(det.list_size(evt))
    print 'shapes   :', str(det.list_shape(evt))
    print 'ndims    :', str(det.list_ndim(evt))

    raws = det.list_raw(evt)
    for nda in raws : print_ndarr(nda, name='-- per det list_raw', first=0, last=5)

    raw = det.raw(evt)
    print_ndarr(raw, name='raw as nda', first=0, last=5)

    calib = det.calib(evt)
    print_ndarr(calib, name='calib', first=0, last=5)

    xy0_offset = (550,550)
    img_raw   = det.image(evt, nda_in=raw, xy0_off_pix=xy0_offset)
    #img_calib = det.image(evt, nda_in=calib, xy0_off_pix=xy0_offset)
    #img_at_z  = det.image_at_z(evt, zplane=500000, nda_in=raw, xy0_off_pix=xy0_offset)

    if True : # True or False for to plot image or not 
        from pyimgalgos.GlobalGraphics import plotImageLarge, show
        img = img_raw
        plotImageLarge(img, title='img as %s' % str(img.shape), amp_range=(0,5000))
        show()

Methods for imaging

img = det.image(evt, nda_in=raw, xy0_off_pix=xy0_offset)
img = det.image_at_z(evt, zplane=500000, nda_in=raw, xy0_off_pix=xy0_offset)
det.image - generates image in the "detector plane" assuming all detector sensors are in the same plane
det.image_at_z - projects intensities from each detector to the plane orthogonal to the beam with specified z coordinate relative to IP. 

 

Compound detector image examples for three cspad2x1 from exp=xpptut15:run=460 and 1M and 512k Jungfrau from exp=mfxls4916:run=298

Geometry files from this example

/reg/d/psdm/xpp/xpptut15/calib/CsPad2x2::CalibV1/MecTargetChamber.0:Cspad2x2.1/geometry/460-460.data
/reg/d/psdm/xpp/xpptut15/calib/CsPad2x2::CalibV1/MecTargetChamber.0:Cspad2x2.2/geometry/460-460.data
/reg/d/psdm/xpp/xpptut15/calib/CsPad2x2::CalibV1/MecTargetChamber.0:Cspad2x2.3/geometry/460-460.data

The last line of each file is responsible for clpad2x1 position and rotation, i.e

IP             0  CSPAD2X2:V1    0          0        0  1000000       120     0     0    0.00000  0.00000  0.00000

See Detector Geometry for detail.

Run test example

 

Until release grater than ana-1.4.6 is available

ssh -Y pslogin.slac.stanford.edu
ssh -Y psana

. /reg/g/psdm/etc/psconda.sh
source conda_setup --reldir /reg/neh/home/dubrovin/LCLS/con-ana-1.4.6

python /reg/neh/home/dubrovin/LCLS/con-ana-1.4.6/Detector/examples/ex_AreaDetectorCompound.py 3 # or other test # from 1 to 5.

 

References

 

  • No labels