PSCalib/src/SegGeometryCspad2x1V1.py

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

Generated on 19 Dec 2016 for PSANAmodules by  doxygen 1.4.7