Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

This note describes imaging detectors' hierarchical geometry model which is implemented in LCLS offline software releases since release ana-0.13.1.

 

Content

Table of Contents

 

Introduction

Analysis of LCLS data from imaging experiments requires precise coordinate definition of the photon detection spot.  In pixel array detectors photon energy usually deposited in a single pixel and hence pixel location precision should be comparable or better than its size, about 100μm.  Apparently, calibration of the detector and entire experimental setup geometry with such a precision is a challenging task for many reasons; 

...

This note contains description of the implemented hierarchical geometry model, coordinate transformation algorithms, tabulation of the hierarchical objects and calibration file format, description of software interface in C++ and Python, details of calibration, etc.                                                           

Coordinate frames

In this section we list tentative objects and associated coordinate frames which may be involved in typical LCLS experimental setup and explain how they can be inscribed in the hierarchical model.

Experimental setup

On the very top level of hierarchical structure there should be a global coordinate frame associated with entire experimental setup. All other setup components are defined relative to the global coordinate frame. In diffraction experiments origin of the coordinate frame is usually associated with IP. Choice of axes directions depends on experimental preferences. In some of LCLS experiments Cartesian coordinate system of the setup is defined by the three mutually orthogonal right-hand-indexed axes with origin in the IP:

...

In this frame photon-hit pixel coordinates (x, y, z) can be easily transformed to the photon diffraction angle θ,

      (1)

Sensor

On the very bottom level of hierarchy structure there should be self-sufficient components of the detector - sensors a.k.a. tiles, segments, pixel arrays/matrix etc. We assume that

...

where y coordinate is proportional to the row index, while x coordinate needs to be tabulated as a function of the column index due to the gap in the tile central columns braking matrix uniformity. Detector data record consists of consecutive tile-memory blocks, in accordance with numeration adopted in DAQ. For effective memory management, some of the tile-blocks may be missing due to current detector configuration. Available configuration of the detector tile-blocks should be marked in a configuratiomn bit-mask word in positional order (bit position from lower to higher is associated with the tile number in DAQ).

Child geometry object in the parent frame

Full description of a composite detector (beside top and bottom level hierarchical objects) needs in definition of intermediate objects with their arbitrary location and orientation. Any geometry object coordinate system may have a translation and rotation with respect to the parent object, which can be defined by the 3 vectors in the setup frame as shown in Figure

...

around appropriate axes, defined as

           (5)

This transformation algorithm is implemented in class PSCalib.GeometryObject as discussed below.

 

 

Example of composite detector

As an example we show how composite CXI-like CSPAD detector with moving quads can be inscribed in the hierarchical geometry model and how geometry parameters can be retrieved in each level.

...

FIG. 6: Example: detector position in the experiment coordinate frame with origin at IP.          

 

 

Optical measurements

Precise pixel coordinates can be retrieved in a few steps using

...

In this section we describe a procedure of optical measurements, its potential problem, and method to fix it.

Metrology file

Optical measurements with microscope give the most precise information about sensors’ positions in the parent structure. Estimated accuracy of measurements is σRMS ∼ 10μm in x-y plane, and about the same amount in z. Optical measurements provide 3-d coordinates of 4 corners for all tiles in the (sub-)detector in some arbitrary microscope plane which coincides with detector imaging array (tiles) plane within precision of installation.

...

  • Metrology files are produced by the detector group for new or repaired detectors.

Quality check

Measurements with microscope are not automated. Results are manually saved in the metrology file, which may have non-intentional typos. If the number of typos is small they can be tracked down in the quality check and fixed. Quality check of optical measurement may test for each tile:

...

Report table about all deviations is generated by the python script processing the metrology file. Large deviations exceeding standard precision >3σ(RMS) indicate on problem with measurement. A few corrections are usually applied for each metrology file.

Calibration file

In this section we discuss requirements to the geometry alignment parameters and describe chosen file format.

Hierarchical structure

In the calibration file/table we need to save links between parent and child objects. Tree-like structure assumes that each parental object may have many children and each child object has only one parent. It is easier for each object to keep information about its parent and object location and orientation parameters with respect to the parent, as implemented in class PSCalib.GeometryObject. One fixed length record per object is convenient to keep this information in memory and file as a table. Scan over all objects allows to retrieve all hierarchical links and use them further in recursive processing. This algorithm is implemented in the class PSCalib.GeometryAccess.

 

Object identification

Composite detector usually consists of similar sub-detectors. In particular, CSPAD consists of four quads, quad consists of eight 2x1 sensors. Sub-detectors of the same type should be treated by the same code. To distinguish between sub-detectors we introduce two variable for each object, name and index. For example, CSPAD quads have an arbitrary symbolic name “QUAD” and indexes from 0 to 3, their children have a symbolic name “CSPAD2X1V1” and indexes from 0 to 7. The name of low level objects, “CSPAD2X1V1”, is used in the factory method PSCalib.SegGeometryStore.Create in order to instatiate instantiate associated PSCalib.SegGeometry object. This and all other names are also used to set child-parent relations between objects. 

 

Assumptions about detector geometry

In most cases we deal with planar detectors and we assume that:

...

in this plane, as explained below. These assumptions are not necessary for all algorithms. But, in many cases it may be convenient to use small angle approximation or ignore angular misalignment for image mapping between tiles and 2-d image array. For this reason in calibration file we split all angles for rotation and tilt in order to have direct access to the designed and corrected values, respectively.

File format

From metrology file we may evaluate the tile center coordinates as an average over 4 corners. Tilt angles are defined as projected angles of the tile sides on relevant planes. Each angle is evaluated as an averaged angle for 2 sides. The tile location and orientation in the parent frame can be saved in the table record where

...

First four fields are intended to set parent-to-child relations between geometry objects. Python script in CalibManager reads data from the metrology file and generates the geometry file consisting of records in this format. Thus tabulated geometry parameters allow to

...

Result of multiple geometry transformations depends on their order. In coordinate reconstruction algorithms we use particular order for rotations and translations.

 

 

Calibration file example

CalibManager under the tabs Geometry / Metrology has a GUI which processes metrology file and generates the calibration file like shown below for CXI-like CSPAD with moving quads (see example of file: geometry/0-end.data)

Code Block
# TITLE      Geometry parameters of CSPAD-CXI
# DATE_TIME  2014-10-03 12:20:44 PDT
# METROLOGY  /reg/neh/home1/dubrovin/LCLS/CSPadMetrologyProc/2014-05-15-CSPAD-CXI-DS1-Metrology-corr.txt
# AUTHOR     dubrovin
# EXPERIMENT Any
# DETECTOR   CSPAD-CXI
# CALIB_TYPE geometry
# COMMENT:01 Table contains the list of geometry parameters for alignment of 2x1 sensors, quads, CSPAD, etc
# COMMENT:02 All translation and rotation pars of the object are defined w.r.t. parent object Cartesian frame
# PARAM:01 PARENT     - name and version of the parent object
# PARAM:02 PARENT_IND - index of the parent object
# PARAM:03 OBJECT     - name and version of the object
# PARAM:04 OBJECT_IND - index of the new object
# PARAM:05 X0         - x-coordinate [um] of the object origin in the parent frame
# PARAM:06 Y0         - y-coordinate [um] of the object origin in the parent frame
# PARAM:07 Z0         - z-coordinate [um] of the object origin in the parent frame
# PARAM:08 ROT_Z      - object design rotation angle [deg] around Z axis of the parent frame
# PARAM:09 ROT_Y      - object design rotation angle [deg] around Y axis of the parent frame
# PARAM:10 ROT_X      - object design rotation angle [deg] around X axis of the parent frame
# PARAM:11 TILT_Z     - object tilt angle [deg] around Z axis of the parent frame
# PARAM:12 TILT_Y     - object tilt angle [deg] around Y axis of the parent frame
# PARAM:13 TILT_X     - object tilt angle [deg] around X axis of the parent frame
 
# HDR PARENT IND        OBJECT IND    X0[um]  Y0[um]  Z0[um]   ROT-Z ROT-Y ROT-X     TILT-Z   TILT-Y   TILT-X
 
QUAD:V1        0  SENS2X1:V1     0     21757   33110      51       0     0     0    0.04474 -0.14079 -0.00274
QUAD:V1        0  SENS2X1:V1     1     21769   10457      18       0     0     0    0.01053 -0.11974  0.00000
QUAD:V1        0  SENS2X1:V1     2     33464   68275     -28     270     0     0   -0.01645  0.10414  0.09737
QUAD:V1        0  SENS2X1:V1     3     10769   68299      18     270     0     0   -0.02828  0.02740  0.13418
QUAD:V1        0  SENS2X1:V1     4     68489   56732      71     180     0     0   -0.05128 -0.11309  0.06303
QUAD:V1        0  SENS2X1:V1     5     68561   79628     -20     180     0     0   -0.03552  0.07104 -0.11788
QUAD:V1        0  SENS2X1:V1     6     77637   21754     -15     270     0     0   -0.33657 -0.00821  0.01183
QUAD:V1        0  SENS2X1:V1     7     54810   21558     -54     270     0     0   -0.06315  0.00000  0.00658
 
QUAD:V1        1  SENS2X1:V1     0     21757   33329     178       0     0     0    0.08883  0.03158 -0.20830
QUAD:V1        1  SENS2X1:V1     1     21773   10446      61       0     0     0   -0.01448  0.04211 -0.24943
QUAD:V1        1  SENS2X1:V1     2     33430   68158     257     270     0     0    0.02698 -0.04660 -0.07370
QUAD:V1        1  SENS2X1:V1     3     10628   68183     247     270     0     0    0.04014 -0.08498 -0.06448
QUAD:V1        1  SENS2X1:V1     4     68349   56949     161     180     0     0   -0.00066 -0.02895  0.05481
QUAD:V1        1  SENS2X1:V1     5     68345   79783     231     180     0     0    0.06843 -0.13948  0.03836
QUAD:V1        1  SENS2X1:V1     6     77454   21811     111     270     0     0    0.05919 -0.06029 -0.11707
QUAD:V1        1  SENS2X1:V1     7     54729   21779     106     270     0     0    0.07632 -0.04933 -0.16580
 
QUAD:V1        2  SENS2X1:V1     0     21741   33265       0       0     0     0   -0.06053  0.00000  0.00000
QUAD:V1        2  SENS2X1:V1     1     21752   10493       0       0     0     0    0.10132  0.00000  0.00000
QUAD:V1        2  SENS2X1:V1     2     32869   68638       0     270     0     0    0.07036  0.00000  0.00000
QUAD:V1        2  SENS2X1:V1     3     10462   68624       0     270     0     0    0.00658  0.00000  0.00000
QUAD:V1        2  SENS2X1:V1     4     68166   57261       0     180     0     0    0.17894  0.00000  0.00000
QUAD:V1        2  SENS2X1:V1     5     68109   79832       0     180     0     0    0.11972  0.00000  0.00000
QUAD:V1        2  SENS2X1:V1     6     77482   21698       0     270     0     0   -0.02762  0.00000  0.00000
QUAD:V1        2  SENS2X1:V1     7     54709   21779       0     270     0     0    0.02499  0.00000  0.00000
 
QUAD:V1        3  SENS2X1:V1     0     21730   33098     102       0     0     0    0.09278 -0.05132 -0.27140
QUAD:V1        3  SENS2X1:V1     1     21755   10477      40       0     0     0    0.06580 -0.02369 -0.32612
QUAD:V1        3  SENS2X1:V1     2     33193   68452     272     270     0     0    0.34083 -0.02192 -0.18687
QUAD:V1        3  SENS2X1:V1     3     10904   68416     270     270     0     0    0.01645  0.00823 -0.15397
QUAD:V1        3  SENS2X1:V1     4     68570   56923     194     180     0     0    0.12435  0.06974  0.07401
QUAD:V1        3  SENS2X1:V1     5     68456   79666     246     180     0     0    0.20857  0.04737  0.12882
QUAD:V1        3  SENS2X1:V1     6     77425   21681      60     270     0     0    0.05264  0.00274 -0.30004
QUAD:V1        3  SENS2X1:V1     7     54648   21761     118     270     0     0    0.01645 -0.00822 -0.22107
 
CSPAD:V1       0  QUAD:V1        0     -4500   -4500       0      90     0     0    0.00000  0.00000  0.00000
CSPAD:V1       0  QUAD:V1        1     -4500    4500       0       0     0     0    0.00000  0.00000  0.00000
CSPAD:V1       0  QUAD:V1        2      4500    4500       0     270     0     0    0.00000  0.00000  0.00000
CSPAD:V1       0  QUAD:V1        3      4500   -4500       0     180     0     0    0.00000  0.00000  0.00000

...

Code Block
# HDR PARENT IND        OBJECT IND    X0[um]  Y0[um]  Z0[um]   ROT-Z ROT-Y ROT-X     TILT-Z   TILT-Y   TILT-X 
SETUP-IP       0   CSPAD2X2:V1   0      -100     200 1000000       0   180     0          0        0        0

 

 

Interface implementation

Program interface to the detector geometry parameters consists of a few modules with the same names up to extensions for C++ and Python in the PSCalib package. Sensor geometry:

Hierarchical model:

C++ program interface description with examples is available in Doxygen documentation. Below we consider Python interface only.

 

Access to sensor geometry information

Generic program interface to the sensors’ ideal geometry is presented by the abstract class PSCalib.SegGeometry. It declares methods returning number of pixels, rows, columns, pixel size, area, center coordinates relative to sensor coordinate frame, as listed below.

...

Currently this abstract interface has the only implementation for CSPAD2x1 in the class PSCalib.SegGeometryCspad2x1V1. Other versions of CSPAD2x1, ePix, pnccd, etc. sensors can be added later. Static factory method Create in class class PSCalib.SegGeometryStore allows to access any sensor geometry information by the detector independent way. For example, pixel x-, y-, and z-coordinate arrays can be directly retrieved from class PSCalib.SegGeometryCspad2x1V1:

Code Block
from PSCalib.SegGeometryCspad2x1V1 import cspad2x1_one
...
xarr, yarr, zarr = cspad2x1_one.pixel_coord_array()

...

This interface is used internally in the geometry service modules and, until it is absolutely necessary, should not be used directly. Doxygen/Sphinx documentation for C++/Python modules is available in References.

 

 

Pixel coordinates transformation

Child geometry object pixel coordinates are transformed to the parent frame pixel coordinates in accordance with Eqn 3. We use rotation matrix expressed in terms of cosines and sines of rotation angles as shown in Eqs. 4-5 First we apply rotations around z, y, and x axes then translation. Note, that order of operations is important. This transformation algorithm is implemented in the class PSCalib.GeometryObject. For example, in Python module PSCalib.GeometryObject.py all transformations of pixel coordinate arrays are presented by the code

Code Block
#file: pyimgalgos/src/GeometryObject.py

def rotation(X, Y, C, S) :
    Xrot = X*C - Y*S 
    Yrot = Y*C + X*S 
    return Xrot, Yrot

class GeometryObject :
    ...
    def transform_geo_coord_arrays(self, X, Y, Z) :
        ...
	    # define Cx, Cy, Cz, Sx, Sy, Sz - cosines and sines of rotation + tilt angles
        ...

        X1, Y1 = rotation(X,  Y,  Cz, Sz)
        Z2, X2 = rotation(Z,  X1, Cy, Sy)
        Y3, Z3 = rotation(Y1, Z2, Cx, Sx)

        Zt = Z3 + self.z0
        Yt = Y3 + self.y0
        Xt = X2 + self.x0

        return Xt, Yt, Zt 

 

Detector geometry access interface

Public methods of the class PSCalib.GeometryAccess:

Code Block
def __init__(self, path, pbits=0) :
"""Constructor of the class"""
def get_pixel_coords(self, oname=None, oindex=0) :
"""Returns three pixel X,Y,Z coordinate arrays for top or specified geometry object"""
def get_pixel_areas(self, oname=None, oindex=0) :
"""Returns pixel areas array for top or specified geometry object"""
def get_pixel_mask(self, oname=None, oindex=0, mbits=0377) :
"""Returns pixel mask array for top or specified geometry object.
mbits =+1 - mask edges
       +2 - two wide-pixel central columns
       +4 - non-bounded pixels
       +8 - neighbours of non-bounded pixels"""
def get_pixel_scale_size(self, oname=None, oindex=0) :
"""Returns pixel scale size for top or specified geometry object"""
def get_dict_of_comments(self) :
"""Returns dictionary of comments"""
def set_geo_pars(self, oname=None, oindex=0, x0=0, y0=0, z0=0, rot_z=0, rot_y=0, rot_x=0, tilt_z=0, tilt_y=0, tilt_x=0) :
"""Sets geometry parameters for specified or top geometry object"""
def move_geo(self, oname=None, oindex=0, dx=0, dy=0, dz=0) :
"""Moves specified or top geometry object by dx, dy, dz"""
def tilt_geo(self, oname=None, oindex=0, dt_x=0, dt_y=0, dt_z=0) :
"""Tilts specified or top geometry object by dt_x, dt_y, dt_z"""
def print_list_of_geos(self) :
def print_list_of_geos_children(self) :
def print_comments_from_dict(self) :
def print_pixel_coords(self, oname=None, oindex=0) :
"""Partial print of pixel coordinate X,Y,Z arrays for selected or top(by default) geo"""
def get_pixel_coord_indexes(self, oname=None, oindex=0, pix_scale_size_um=None, xy0_off_pix=None) :
"""Returns three pixel X,Y,Z coordinate index arrays for top or specified geometry object"""
def set_print_bits(self, pbits=0) :
""" Sets printout control bitword"""
def set_print_bits(self, pbits=0) :
""" Sets printout control bitword"""
def get_psf(self) :
"""Returns array of vectors in TJ format (psf stands for position-slow-fast vectors)"""
def print_psf(self) :
""" Gets and prints psf array for test purpose"""
#------------------------------
# private methods, which may be useful:
def get_geo(self, oname, oindex) :
"""Returns specified geometry object"""
def get_top_geo(self) :
"""Returns top geometry object"""

# global method:
def img_from_pixel_arrays(iX, iY, W=None, dtype=np.float32) :
"""Returns image from iX, iY coordinate index arrays and associated weights W"""

...

Code Block
from PSCalib.GeometryAccess import *
fname_geometry = ’<path>/geometry/0-end.data’
geometry = GeometryAccess(fname_geometry, 0377)
dict_comm = geometry.get_dict_of_comments()
pix_size = geometry.get_pixel_scale_size()

X, Y, Z = geometry.get_pixel_coords(’QUAD:V1’, 1) # for quad
X, Y, Z = geometry.get_pixel_coords() # for top object (CSPAD)
iX, iY = geometry.get_pixel_coord_indexes(’QUAD:V1’, 1, pix_scale_size_um=None, xy0_off_pix=None) # for quad
iX, iY = geometry.get_pixel_coord_indexes(xy0_off_pix=(1000, 1000)) # for top object (CSPAD)
img = img_from_pixel_arrays(iX,iY,W=<intensity-array>)
img = img_from_pixel_arrays(iX,iY) # Image of 0/1 for fake/real pixels
arr = geometry.get_pixel_mask(’QUAD:V1’, 1, 1+2+4+8)
arr.shape = (8,185,388)
d
dict_comm = geometry.get_dict_of_comments()
print d = geometry.get_dict_of_comments()
print "d[’DATE_TIME’] = %s" % d[’DATE_TIME’]

 

Summary

Pixel detector geometry generic parameterization presented in this note is implemented in LCLS analysis software releases since ana-0.13.N. Both C++ and Python interfaces are available.

...

Anchor
references
references

References

 Reference to  doxygen documentation of classes