00001
00002
00003
00004
00005
00006
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
00083
00084 __version__ = "$Revision: 12085 $"
00085
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
00101 _cols = 388
00102 _pixs = 109.92
00103 _pixw = 274.80
00104 _pixd = 400.00
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
00114
00115 SegGeometry.__init__(sp)
00116
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
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
00137
00138
00139
00140
00141
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
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
00361 mask[0, :] = zero_row
00362 mask[-1,:] = zero_row
00363 mask[:, 0] = zero_col
00364 mask[:,-1] = zero_col
00365
00366 if mbits & 2 :
00367
00368 mask[:,sp._colsh-1] = zero_col
00369 mask[:,sp._colsh] = zero_col
00370
00371 if mbits & 4 or mbits & 8 or mbits & 16 :
00372
00373 for p in range(0, sp._rows, 10) :
00374 h = sp._colsh
00375
00376 if mbits & 16 :
00377
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
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
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
00415
00416
00417
00418
00419 if __name__ == "__main__" :
00420 import pyimgalgos.GlobalGraphics as gg
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
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
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
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
00471 print 'ysize =', ysize
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))
00480 gg.show()
00481
00482
00483
00484 def test_2x1_img_easy() :
00485 pc2x1 = SegGeometryCspad2x1V1(use_wide_pix_center=False)
00486
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