PSCalib/src/SegGeometryMatrixV1.py

Go to the documentation of this file.
00001 #--------------------------------------------------------------------------
00002 # File and Version Information:
00003 #  $Id: SegGeometryMatrixV1.py 12085 2016-06-14 01:06:47Z dubrovin@SLAC.STANFORD.EDU $
00004 #
00005 # Description:
00006 #  Module SegGeometryMatrixV1...
00007 #------------------------------------------------------------------------
00008 
00009 """Class :py:class:`PSCalib.SegGeometryMatrixV1` defines the matrix V1 (pnCCD, 512x512) sensor pixel coordinates in its local frame.
00010 
00011 Default constructor parameters are set for pnCCD; 512x512 pixels with 75x75um pixel size.
00012 In this class we use natural matrix notations like in data array
00013 (that is different from the DAQ notations where rows and cols are swapped).
00014 \n We assume that
00015 \n * segment has 512 rows and 512 columns,
00016 \n * X-Y coordinate system origin is in the top left corner,
00017 \n * ixel (r,c)=(0,0) is in the top left corner of the matrix which has coordinates (Xmin,Ymin) - is in origin.
00018 \n ::
00019 
00020   MatrixV1 sensor coordinate frame has a matrix-style coordinate system:
00021  
00022   @code
00023     (Xmin,Ymin)        (Xmin,Ymax)
00024     (0,0)              (0,512)
00025        +-----------------+----> Y
00026        |                 |
00027        |                 |
00028        |                 |
00029        |                 |
00030        |                 |
00031        |                 |
00032        |                 |
00033        |                 |
00034        +-----------------+
00035        |
00036      X V
00037     (512,0)           (512,512)
00038     (Xmax,Ymin)       (Xmax,Ymax)
00039   @endcode
00040 
00041 
00042 Usage of interface methods::
00043 
00044     from SegGeometryMatrixV1 import cspad2x1_one as sg
00045 
00046     sg.print_seg_info(0377)
00047 
00048     size_arr = sg.size()
00049     rows     = sg.rows()
00050     cols     = sg.cols()
00051     shape    = sg.shape()
00052     pix_size = pixel_scale_size()
00053 
00054     area  = sg.pixel_area_array()
00055     mask = sg.pixel_mask_array(mbits=0377)
00056     # where mbits = +1-edges, +2-wide pixels, +4-non-bonded pixels, +8-neighbours of non-bonded
00057 
00058     sizeX = sg.pixel_size_array('X')
00059     sizeX, sizeY, sizeZ = sg.pixel_size_array()
00060 
00061     X     = sg.pixel_coord_array('X')
00062     X,Y,Z = sg.pixel_coord_array()
00063     print 'X.shape =', X.shape
00064 
00065     xmin, ymin, zmin = sg.pixel_coord_min()
00066     xmax, ymax, zmax = sg.pixel_coord_max()
00067     xmin = sg.pixel_coord_min('X')
00068     ymax = sg.pixel_coord_max('Y')
00069 
00070     # global method for rotation of numpy arrays:
00071     Xrot, Yrot = rotation(X, Y, C, S)
00072     ...
00073 
00074 
00075 This software was developed for the SIT project.  If you use all or 
00076 part of it, please give an appropriate acknowledgment.
00077 
00078 @see :py:class:`PSCalib.SegGeometry`
00079 
00080 @version $Id: 2013-03-08$
00081 
00082 @author Mikhail S. Dubrovin
00083 """
00084 
00085 #--------------------------------
00086 #  Module's version from CVS --
00087 #--------------------------------
00088 __version__ = "$Revision: 12085 $"
00089 # $Source$
00090 #--------------------------------
00091 
00092 import sys
00093 import math
00094 import numpy as np
00095 from time import time
00096 
00097 from PSCalib.SegGeometry import *
00098 
00099 #------------------------------
00100 
00101 def matrix_pars(segname) :
00102     """Returns the matrix sensor parameters from its string-name, ex: MTRX:512:512:54:54
00103     """
00104     fields = segname.split(':')
00105     if len(fields)<5 :
00106         raise IOError('Matrix-sensor specification %s has less than 4 numeric fields' % segname)
00107 
00108     rows, cols, psize_row, psize_col = int(fields[1]), int(fields[2]), float(fields[3]), float(fields[4])
00109     #print 'matrix sensor %s parameters:' % (segname), rows, cols, psize_row, psize_col
00110     return rows, cols, psize_row, psize_col
00111 
00112 #------------------------------
00113 
00114 class SegGeometryMatrixV1(SegGeometry) :
00115     """Self-sufficient class for generation of CSPad 2x1 sensor pixel coordinate array"""
00116 
00117     #_rows  = 512    # Number of rows in 2x1 at rotation 0
00118     #_cols  = 512    # Number of cols in 2x1 at rotation 0
00119     #_pixs  = 75.00  # Pixel size in um (micrometer)
00120     #_pixd  = 400.00 # Pixel depth in um (micrometer)
00121 
00122 #------------------------------
00123 
00124     def __init__(sp, rows=512, cols=512, pix_size_rows=75, pix_size_cols=75, pix_size_depth=400, pix_scale_size=75) :
00125         #print 'SegGeometryMatrixV1.__init__()'
00126 
00127         SegGeometry.__init__(sp)
00128         #super(SegGeometry, self).__init__()
00129 
00130         sp._rows = rows
00131         sp._cols = cols
00132         sp._pix_size_rows  = pix_size_rows
00133         sp._pix_size_cols  = pix_size_cols
00134         sp._pix_size_depth = pix_size_depth
00135         sp._pixs           = pix_scale_size
00136 
00137         sp.x_pix_arr_um_offset  = None
00138         sp.pix_area_arr = None
00139 
00140         sp.make_pixel_coord_arrs()
00141 
00142 #------------------------------
00143 
00144     def make_pixel_coord_arrs(sp) :
00145         """Makes maps of x, y, and z of segment pixel coordinates
00146         """        
00147         sp.x_arr_um = np.arange(sp._rows)*sp._pix_size_rows
00148         sp.y_arr_um = np.arange(sp._cols)*sp._pix_size_cols
00149 
00150         # Arguments x and y are swapped in order to get grids for "matrix" coordinate system
00151         # where X is directed from up to down, Y from left to right
00152         sp.y_pix_arr_um, sp.x_pix_arr_um = np.meshgrid(sp.y_arr_um, sp.x_arr_um)
00153         sp.z_pix_arr_um = np.zeros((sp._rows,sp._cols))
00154         
00155 #------------------------------
00156 
00157     def make_pixel_size_arrs(sp) :
00158         """Makes maps of x, y, and z segment pixel size 
00159         """        
00160         if sp.pix_area_arr is not None : return
00161 
00162         x_arr_size_um = np.ones(sp._rows) * sp._pix_size_rows
00163         y_arr_size_um = np.ones(sp._cols) * sp._pix_size_cols
00164 
00165         sp.y_pix_size_um, sp.x_pix_size_um = np.meshgrid(y_arr_size_um, x_arr_size_um)
00166         sp.z_pix_size_um = np.ones((sp._rows,sp._cols)) * sp._pix_size_depth
00167  
00168         sp.pix_area_arr = np.ones((sp._rows,sp._cols))
00169 
00170 #------------------------------
00171 
00172     def print_member_data(sp) :
00173         print 'SegGeometryMatrixV1.print_member_data()'
00174         print '    _rows : %d'     % sp._rows
00175         print '    _cols : %d'     % sp._cols
00176         print '    _pixs  : %7.2f' % sp._pixs 
00177         print '    _pix_size_rows  : %7.2f' % sp._pix_size_rows 
00178         print '    _pix_size_cols  : %7.2f' % sp._pix_size_cols 
00179         print '    _pix_size_depth : %7.2f' % sp._pix_size_depth 
00180 
00181 #------------------------------
00182 
00183     def print_pixel_size_arrs(sp) :
00184         print 'SegGeometryMatrixV1.print_pixel_size_arrs()'
00185         sp.make_pixel_size_arrs()
00186         print 'sp.x_pix_size_um[0:10,190:198]:\n', sp.x_pix_size_um[0:10,190:198]
00187         print 'sp.x_pix_size_um.shape = ',         sp.x_pix_size_um.shape
00188         print 'sp.y_pix_size_um:\n',               sp.y_pix_size_um
00189         print 'sp.y_pix_size_um.shape = ',         sp.y_pix_size_um.shape
00190         print 'sp.z_pix_size_um:\n',               sp.z_pix_size_um
00191         print 'sp.z_pix_size_um.shape = ',         sp.z_pix_size_um.shape
00192         sp.make_pixel_coord_arrs()
00193         print 'sp.pix_area_arr[0:10,190:198]:\n',  sp.pix_area_arr[0:10,190:198]
00194         print 'sp.pix_area_arr.shape  = ',         sp.pix_area_arr.shape
00195 
00196 #------------------------------
00197 
00198     def print_maps_seg_um(sp) :
00199         print 'SegGeometryMatrixV1.print_maps_seg_um()'
00200         print 'x_pix_arr_um =\n',      sp.x_pix_arr_um
00201         print 'x_pix_arr_um.shape = ', sp.x_pix_arr_um.shape
00202         print 'y_pix_arr_um =\n',      sp.y_pix_arr_um
00203         print 'y_pix_arr_um.shape = ', sp.y_pix_arr_um.shape
00204         print 'z_pix_arr_um =\n',      sp.z_pix_arr_um
00205         print 'z_pix_arr_um.shape = ', sp.z_pix_arr_um.shape
00206 
00207 #------------------------------
00208 
00209     def print_xy_1darr_um(sp) :
00210         print 'SegGeometryMatrixV1.print_xy_1darr_um()'
00211         print 'x_arr_um:\n',       sp.x_arr_um
00212         print 'x_arr_um.shape = ', sp.x_arr_um.shape
00213         print 'y_arr_um:\n',       sp.y_arr_um
00214         print 'y_arr_um.shape = ', sp.y_arr_um.shape
00215 
00216 #------------------------------
00217 
00218     def print_xyz_min_max_um(sp) :
00219         print 'SegGeometryMatrixV1.print_xyz_min_max_um()'
00220         xmin, ymin, zmin = sp.get_xyz_min_um()
00221         xmax, ymax, zmax = sp.get_xyz_max_um()
00222         print 'In [um] xmin:%9.2f, xmax:%9.2f, ymin:%9.2f, ymax:%9.2f, zmin:%9.2f, zmax:%9.2f' \
00223               % (xmin, xmax, ymin, ymax, zmin, zmax)
00224 
00225 #------------------------------
00226 
00227     def get_xyz_min_um(sp) : 
00228         return sp.x_arr_um[0], sp.y_arr_um[0], 0
00229 
00230     def get_xyz_max_um(sp) : 
00231         return sp.x_arr_um[-1], sp.y_arr_um[-1], 0
00232 
00233     def get_seg_xy_maps_um(sp) : 
00234         return sp.x_pix_arr_um, sp.y_pix_arr_um
00235 
00236     def get_seg_xyz_maps_um(sp) : 
00237         return sp.x_pix_arr_um, sp.y_pix_arr_um, sp.z_pix_arr_um
00238 
00239     def get_seg_xy_maps_um_with_offset(sp) : 
00240         if  sp.x_pix_arr_um_offset is None :
00241             x_min_um, y_min_um, z_min_um = sp.get_xyz_min_um()
00242             sp.x_pix_arr_um_offset = sp.x_pix_arr_um - x_min_um
00243             sp.y_pix_arr_um_offset = sp.y_pix_arr_um - y_min_um
00244         return sp.x_pix_arr_um_offset, sp.y_pix_arr_um_offset
00245 
00246     def get_seg_xyz_maps_um_with_offset(sp) : 
00247         if  sp.x_pix_arr_um_offset is None :
00248             x_min_um, y_min_um, z_min_um = sp.get_xyz_min_um()
00249             sp.x_pix_arr_um_offset = sp.x_pix_arr_um - x_min_um
00250             sp.y_pix_arr_um_offset = sp.y_pix_arr_um - y_min_um
00251             sp.z_pix_arr_um_offset = sp.z_pix_arr_um - z_min_um
00252         return sp.x_pix_arr_um_offset, sp.y_pix_arr_um_offset, sp.z_pix_arr_um_offset
00253 
00254     def get_pix_size_um(sp) : 
00255         return sp._pixs
00256 
00257     def get_pixel_size_arrs_um(sp) :
00258         sp.make_pixel_size_arrs()
00259         return sp.x_pix_size_um, sp.y_pix_size_um, sp.z_pix_size_um
00260 
00261     def get_pixel_area_arr(sp) :
00262         sp.make_pixel_size_arrs()
00263         return sp.pix_area_arr
00264 
00265     def get_seg_xy_maps_pix(sp) :
00266         sp.x_pix_arr_pix = sp.x_pix_arr_um/sp._pixs
00267         sp.y_pix_arr_pix = sp.y_pix_arr_um/sp._pixs
00268         return sp.x_pix_arr_pix, sp.y_pix_arr_pix
00269 
00270     def get_seg_xy_maps_pix_with_offset(sp) :
00271         X, Y = sp.get_seg_xy_maps_pix()
00272         xmin, ymin = X.min(), Y.min()
00273         return X-xmin, Y-ymin
00274 
00275 #------------------------------
00276 # INTERFACE METHODS
00277 #------------------------------
00278 
00279     def print_seg_info(sp, pbits=0) :
00280         """ Prints segment info for selected bits
00281             pbits=0 - nothing
00282                  +1 - member data
00283                  +2 - coordinate maps in um
00284                  +4 - min, max coordinates in um
00285                  +8 - x, y 1-d pixel coordinate arrays in um
00286         """
00287         if pbits & 1 : sp.print_member_data()
00288         if pbits & 2 : sp.print_maps_seg_um()
00289         if pbits & 4 : sp.print_xyz_min_max_um()
00290         if pbits & 8 : sp.print_xy_1darr_um()
00291 
00292 
00293     def size(sp) :
00294         """ Returns number of pixels in segment
00295         """
00296         return sp._rows*sp._cols
00297 
00298 
00299     def rows(sp) :
00300         """ Returns number of rows in segment
00301         """
00302         return sp._rows
00303 
00304 
00305     def cols(sp) :
00306         """ Returns number of cols in segment
00307         """
00308         return sp._cols
00309 
00310 
00311     def shape(sp) :
00312         """ Returns shape of the segment (rows, cols)
00313         """
00314         return (sp._rows, sp._cols)
00315 
00316 
00317     def pixel_scale_size(sp) :
00318         """ Returns pixel size in um for indexing
00319         """
00320         return sp._pixs
00321 
00322 
00323     def pixel_area_array(sp) :
00324         """ Returns pixel area array of shape=(rows, cols)
00325         """
00326         return sp.get_pixel_area_arr()
00327 
00328 
00329     def pixel_size_array(sp, axis=None) :
00330         """ Returns numpy array of pixel sizes in um for AXIS
00331         """
00332         return sp.return_switch(sp.get_pixel_size_arrs_um, axis)
00333 
00334 
00335     def pixel_coord_array(sp, axis=None) :
00336         """ Returns numpy array of segment pixel coordinates in um for AXIS
00337         """
00338         return sp.return_switch(sp.get_seg_xyz_maps_um, axis)
00339 
00340 
00341     def pixel_coord_min(sp, axis=None) :
00342         """ Returns minimal value in the array of segment pixel coordinates in um for AXIS
00343         """
00344         return sp.return_switch(sp.get_xyz_min_um, axis)
00345 
00346 
00347     def pixel_coord_max(sp, axis=None) :
00348         """ Returns maximal value in the array of segment pixel coordinates in um for AXIS
00349         """
00350         return sp.return_switch(sp.get_xyz_max_um, axis)
00351 
00352 
00353     def pixel_mask_array(sp, mbits=0377) :
00354         """ Returns numpy array of pixel mask: 1/0 = ok/masked,
00355             mbits=1 - mask edges
00356                  +2 - mask two central columns 
00357                  +4 - mask non-bonded pixels
00358                  +8 - mask nearest neighbours of nonbonded pixels
00359         """
00360         zero_col = np.zeros(sp._rows,dtype=np.uint8)
00361         zero_row = np.zeros(sp._cols,dtype=np.uint8)
00362         mask     = np.ones((sp._rows,sp._cols),dtype=np.uint8)
00363 
00364         if mbits & 1 : 
00365         # mask edges
00366             mask[0, :] = zero_row # mask top    edge
00367             mask[-1,:] = zero_row # mask bottom edge
00368             mask[:, 0] = zero_col # mask left   edge
00369             mask[:,-1] = zero_col # mask right  edge
00370 
00371         return mask
00372 
00373   
00374 #------------------------------
00375 #------------------------------
00376 
00377 segment_one = SegGeometryMatrixV1()
00378 #seg_andor3d = SegGeometryMatrixV1(rows=2048, cols=2048, pix_size_rows=13.5, pix_size_cols=13.5, pix_size_depth=50, pix_scale_size=13.5)
00379 
00380 #------------------------------
00381 #------------------------------
00382 #------------------------------
00383 #----------- TEST -------------
00384 #------------------------------
00385 #------------------------------
00386 #------------------------------
00387 
00388 if __name__ == "__main__" :
00389     import pyimgalgos.GlobalGraphics as gg # For test purpose in main only
00390 
00391 
00392 def test_xyz_min_max() :
00393     w = SegGeometryMatrixV1()
00394     w.print_xyz_min_max_um() 
00395     print 'Ymin = ', w.pixel_coord_min('Y')
00396     print 'Ymax = ', w.pixel_coord_max('Y')
00397 
00398 #------------------------------
00399 
00400 def test_xyz_maps() :
00401 
00402     w = SegGeometryMatrixV1()
00403     w.print_maps_seg_um()
00404 
00405     titles = ['X map','Y map']
00406     #for i,arr2d in enumerate([w.x_pix_arr,w.y_pix_arr]) :
00407     for i,arr2d in enumerate( w.get_seg_xy_maps_pix() ) :
00408         amp_range = (arr2d.min(), arr2d.max())
00409         gg.plotImageLarge(arr2d, amp_range=amp_range, figsize=(10,5), title=titles[i])
00410         gg.move(200*i,100*i)
00411 
00412     gg.show()
00413 
00414 #------------------------------
00415 
00416 def test_img() :
00417 
00418     t0_sec = time()
00419     w = SegGeometryMatrixV1()
00420     print 'Consumed time for coordinate arrays (sec) =', time()-t0_sec
00421 
00422     X,Y = w.get_seg_xy_maps_pix()
00423 
00424     w.print_seg_info(0377)
00425 
00426     #print 'X(pix) :\n', X
00427     print 'X.shape =', X.shape
00428 
00429     xmin, ymin, zmin = w.get_xyz_min_um()
00430     xmax, ymax, zmax = w.get_xyz_max_um()
00431     xmin /= w.pixel_scale_size()
00432     xmax /= w.pixel_scale_size()
00433     ymin /= w.pixel_scale_size()
00434     ymax /= w.pixel_scale_size()
00435 
00436     xsize = xmax - xmin + 1
00437     ysize = ymax - ymin + 1
00438     print 'xsize =', xsize # 391.0 
00439     print 'ysize =', ysize # 185.0
00440 
00441     H, Xedges, Yedges = np.histogram2d(X.flatten(), Y.flatten(), bins=[xsize,ysize], range=[[xmin, xmax], [ymin, ymax]], normed=False, weights=X.flatten()+Y.flatten()) 
00442 
00443     print 'Xedges:', Xedges
00444     print 'Yedges:', Yedges
00445     print 'H.shape:', H.shape
00446 
00447     gg.plotImageLarge(H, amp_range=(0, 1100), figsize=(8,10)) # range=(-1, 2), 
00448     gg.show()
00449 
00450 #------------------------------
00451 
00452 def test_img_easy() :
00453     pc2x1 = SegGeometryMatrixV1()
00454     #X,Y = pc2x1.get_seg_xy_maps_pix()
00455     X,Y = pc2x1.get_seg_xy_maps_pix_with_offset()
00456     iX, iY = (X+0.25).astype(int), (Y+0.25).astype(int)
00457     img = gg.getImageFromIndexArrays(iX,iY,iX+iY)
00458     gg.plotImageLarge(img, amp_range=(0, 1100), figsize=(8,10))
00459     gg.show()
00460 
00461 #------------------------------
00462 
00463 def test_pix_sizes() :
00464     w = SegGeometryMatrixV1()
00465     w.print_pixel_size_arrs()
00466     size_arr = w.pixel_size_array('X')
00467     area_arr = w.pixel_area_array()
00468     print 'area_arr[0:10,190:198]:\n',  area_arr[0:10,190:198]
00469     print 'area_arr.shape :',           area_arr.shape
00470     print 'size_arr[0:10,190:198]:\n',  size_arr[0:10,190:198]
00471     print 'size_arr.shape :',           size_arr.shape
00472 
00473 #------------------------------
00474 
00475 def test_mask(mbits=0377) :
00476     pc2x1 = SegGeometryMatrixV1()
00477     X, Y = pc2x1.get_seg_xy_maps_pix_with_offset()
00478     mask = pc2x1.pixel_mask_array(mbits)
00479     iX, iY = (X+0.25).astype(int), (Y+0.25).astype(int)
00480     img = gg.getImageFromIndexArrays(iX,iY,mask)
00481     gg.plotImageLarge(img, amp_range=(-1, 2), figsize=(8,10))
00482     gg.show()
00483 
00484 #------------------------------
00485  
00486 if __name__ == "__main__" :
00487 
00488     if len(sys.argv)==1   : print 'For other test(s) use command: python', sys.argv[0], '<test-number=0-5>'
00489     elif sys.argv[1]=='0' : test_xyz_min_max()
00490     elif sys.argv[1]=='1' : test_xyz_maps()
00491     elif sys.argv[1]=='2' : test_img()
00492     elif sys.argv[1]=='3' : test_img_easy()
00493     elif sys.argv[1]=='4' : test_pix_sizes()
00494     elif sys.argv[1]=='5' : test_mask(mbits=1+2+4+8)
00495     else : print 'Non-expected arguments: sys.argv=', sys.argv
00496 
00497     sys.exit( 'End of test.' )
00498 
00499 #------------------------------

Generated on 19 Dec 2016 for PSANAmodules by  doxygen 1.4.7