00001
00002
00003
00004
00005
00006
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
00087
00088 __version__ = "$Revision: 12085 $"
00089
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
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
00118
00119
00120
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
00126
00127 SegGeometry.__init__(sp)
00128
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
00151
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
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
00366 mask[0, :] = zero_row
00367 mask[-1,:] = zero_row
00368 mask[:, 0] = zero_col
00369 mask[:,-1] = zero_col
00370
00371 return mask
00372
00373
00374
00375
00376
00377 segment_one = SegGeometryMatrixV1()
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 if __name__ == "__main__" :
00389 import pyimgalgos.GlobalGraphics as gg
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
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
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
00439 print 'ysize =', ysize
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))
00448 gg.show()
00449
00450
00451
00452 def test_img_easy() :
00453 pc2x1 = SegGeometryMatrixV1()
00454
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