#--------------------------------------------------------------------------
# File and Version Information:
# $Id: SegGeometryMatrixV1.py 12085 2016-06-14 01:06:47Z dubrovin@SLAC.STANFORD.EDU $
#
# Description:
# Module SegGeometryMatrixV1...
#------------------------------------------------------------------------
"""Class :py:class:`PSCalib.SegGeometryMatrixV1` defines the matrix V1 (pnCCD, 512x512) sensor pixel coordinates in its local frame.
Default constructor parameters are set for pnCCD; 512x512 pixels with 75x75um pixel size.
In this class we use natural matrix notations like in data array
(that is different from the DAQ notations where rows and cols are swapped).
\n We assume that
\n * segment has 512 rows and 512 columns,
\n * X-Y coordinate system origin is in the top left corner,
\n * ixel (r,c)=(0,0) is in the top left corner of the matrix which has coordinates (Xmin,Ymin) - is in origin.
\n ::
MatrixV1 sensor coordinate frame has a matrix-style coordinate system:
@code
(Xmin,Ymin) (Xmin,Ymax)
(0,0) (0,512)
+-----------------+----> Y
| |
| |
| |
| |
| |
| |
| |
| |
+-----------------+
|
X V
(512,0) (512,512)
(Xmax,Ymin) (Xmax,Ymax)
@endcode
Usage of interface methods::
from SegGeometryMatrixV1 import cspad2x1_one as sg
sg.print_seg_info(0377)
size_arr = sg.size()
rows = sg.rows()
cols = sg.cols()
shape = sg.shape()
pix_size = pixel_scale_size()
area = sg.pixel_area_array()
mask = sg.pixel_mask_array(mbits=0377)
# where mbits = +1-edges, +2-wide pixels, +4-non-bonded pixels, +8-neighbours of non-bonded
sizeX = sg.pixel_size_array('X')
sizeX, sizeY, sizeZ = sg.pixel_size_array()
X = sg.pixel_coord_array('X')
X,Y,Z = sg.pixel_coord_array()
print 'X.shape =', X.shape
xmin, ymin, zmin = sg.pixel_coord_min()
xmax, ymax, zmax = sg.pixel_coord_max()
xmin = sg.pixel_coord_min('X')
ymax = sg.pixel_coord_max('Y')
# global method for rotation of numpy arrays:
Xrot, Yrot = rotation(X, Y, C, S)
...
This software was developed for the SIT project. If you use all or
part of it, please give an appropriate acknowledgment.
@see :py:class:`PSCalib.SegGeometry`
@version $Id: 2013-03-08$
@author Mikhail S. Dubrovin
"""
#--------------------------------
# Module's version from CVS --
#--------------------------------
__version__ = "$Revision: 12085 $"
# $Source$
#--------------------------------
import sys
import math
import numpy as np
from time import time
from PSCalib.SegGeometry import *
#------------------------------
[docs]def matrix_pars(segname) :
"""Returns the matrix sensor parameters from its string-name, ex: MTRX:512:512:54:54
"""
fields = segname.split(':')
if len(fields)<5 :
raise IOError('Matrix-sensor specification %s has less than 4 numeric fields' % segname)
rows, cols, psize_row, psize_col = int(fields[1]), int(fields[2]), float(fields[3]), float(fields[4])
#print 'matrix sensor %s parameters:' % (segname), rows, cols, psize_row, psize_col
return rows, cols, psize_row, psize_col
#------------------------------
class SegGeometryMatrixV1(SegGeometry) :
"""Self-sufficient class for generation of CSPad 2x1 sensor pixel coordinate array"""
#_rows = 512 # Number of rows in 2x1 at rotation 0
#_cols = 512 # Number of cols in 2x1 at rotation 0
#_pixs = 75.00 # Pixel size in um (micrometer)
#_pixd = 400.00 # Pixel depth in um (micrometer)
#------------------------------
def __init__(sp, rows=512, cols=512, pix_size_rows=75, pix_size_cols=75, pix_size_depth=400, pix_scale_size=75) :
#print 'SegGeometryMatrixV1.__init__()'
SegGeometry.__init__(sp)
#super(SegGeometry, self).__init__()
sp._rows = rows
sp._cols = cols
sp._pix_size_rows = pix_size_rows
sp._pix_size_cols = pix_size_cols
sp._pix_size_depth = pix_size_depth
sp._pixs = pix_scale_size
sp.x_pix_arr_um_offset = None
sp.pix_area_arr = None
sp.make_pixel_coord_arrs()
#------------------------------
def make_pixel_coord_arrs(sp) :
"""Makes maps of x, y, and z of segment pixel coordinates
"""
sp.x_arr_um = np.arange(sp._rows)*sp._pix_size_rows
sp.y_arr_um = np.arange(sp._cols)*sp._pix_size_cols
# Arguments x and y are swapped in order to get grids for "matrix" coordinate system
# where X is directed from up to down, Y from left to right
sp.y_pix_arr_um, sp.x_pix_arr_um = np.meshgrid(sp.y_arr_um, sp.x_arr_um)
sp.z_pix_arr_um = np.zeros((sp._rows,sp._cols))
#------------------------------
def make_pixel_size_arrs(sp) :
"""Makes maps of x, y, and z segment pixel size
"""
if sp.pix_area_arr is not None : return
x_arr_size_um = np.ones(sp._rows) * sp._pix_size_rows
y_arr_size_um = np.ones(sp._cols) * sp._pix_size_cols
sp.y_pix_size_um, sp.x_pix_size_um = np.meshgrid(y_arr_size_um, x_arr_size_um)
sp.z_pix_size_um = np.ones((sp._rows,sp._cols)) * sp._pix_size_depth
sp.pix_area_arr = np.ones((sp._rows,sp._cols))
#------------------------------
def print_member_data(sp) :
print 'SegGeometryMatrixV1.print_member_data()'
print ' _rows : %d' % sp._rows
print ' _cols : %d' % sp._cols
print ' _pixs : %7.2f' % sp._pixs
print ' _pix_size_rows : %7.2f' % sp._pix_size_rows
print ' _pix_size_cols : %7.2f' % sp._pix_size_cols
print ' _pix_size_depth : %7.2f' % sp._pix_size_depth
#------------------------------
def print_pixel_size_arrs(sp) :
print 'SegGeometryMatrixV1.print_pixel_size_arrs()'
sp.make_pixel_size_arrs()
print 'sp.x_pix_size_um[0:10,190:198]:\n', sp.x_pix_size_um[0:10,190:198]
print 'sp.x_pix_size_um.shape = ', sp.x_pix_size_um.shape
print 'sp.y_pix_size_um:\n', sp.y_pix_size_um
print 'sp.y_pix_size_um.shape = ', sp.y_pix_size_um.shape
print 'sp.z_pix_size_um:\n', sp.z_pix_size_um
print 'sp.z_pix_size_um.shape = ', sp.z_pix_size_um.shape
sp.make_pixel_coord_arrs()
print 'sp.pix_area_arr[0:10,190:198]:\n', sp.pix_area_arr[0:10,190:198]
print 'sp.pix_area_arr.shape = ', sp.pix_area_arr.shape
#------------------------------
def print_maps_seg_um(sp) :
print 'SegGeometryMatrixV1.print_maps_seg_um()'
print 'x_pix_arr_um =\n', sp.x_pix_arr_um
print 'x_pix_arr_um.shape = ', sp.x_pix_arr_um.shape
print 'y_pix_arr_um =\n', sp.y_pix_arr_um
print 'y_pix_arr_um.shape = ', sp.y_pix_arr_um.shape
print 'z_pix_arr_um =\n', sp.z_pix_arr_um
print 'z_pix_arr_um.shape = ', sp.z_pix_arr_um.shape
#------------------------------
def print_xy_1darr_um(sp) :
print 'SegGeometryMatrixV1.print_xy_1darr_um()'
print 'x_arr_um:\n', sp.x_arr_um
print 'x_arr_um.shape = ', sp.x_arr_um.shape
print 'y_arr_um:\n', sp.y_arr_um
print 'y_arr_um.shape = ', sp.y_arr_um.shape
#------------------------------
def print_xyz_min_max_um(sp) :
print 'SegGeometryMatrixV1.print_xyz_min_max_um()'
xmin, ymin, zmin = sp.get_xyz_min_um()
xmax, ymax, zmax = sp.get_xyz_max_um()
print 'In [um] xmin:%9.2f, xmax:%9.2f, ymin:%9.2f, ymax:%9.2f, zmin:%9.2f, zmax:%9.2f' \
% (xmin, xmax, ymin, ymax, zmin, zmax)
#------------------------------
def get_xyz_min_um(sp) :
return sp.x_arr_um[0], sp.y_arr_um[0], 0
def get_xyz_max_um(sp) :
return sp.x_arr_um[-1], sp.y_arr_um[-1], 0
def get_seg_xy_maps_um(sp) :
return sp.x_pix_arr_um, sp.y_pix_arr_um
def get_seg_xyz_maps_um(sp) :
return sp.x_pix_arr_um, sp.y_pix_arr_um, sp.z_pix_arr_um
def get_seg_xy_maps_um_with_offset(sp) :
if sp.x_pix_arr_um_offset is None :
x_min_um, y_min_um, z_min_um = sp.get_xyz_min_um()
sp.x_pix_arr_um_offset = sp.x_pix_arr_um - x_min_um
sp.y_pix_arr_um_offset = sp.y_pix_arr_um - y_min_um
return sp.x_pix_arr_um_offset, sp.y_pix_arr_um_offset
def get_seg_xyz_maps_um_with_offset(sp) :
if sp.x_pix_arr_um_offset is None :
x_min_um, y_min_um, z_min_um = sp.get_xyz_min_um()
sp.x_pix_arr_um_offset = sp.x_pix_arr_um - x_min_um
sp.y_pix_arr_um_offset = sp.y_pix_arr_um - y_min_um
sp.z_pix_arr_um_offset = sp.z_pix_arr_um - z_min_um
return sp.x_pix_arr_um_offset, sp.y_pix_arr_um_offset, sp.z_pix_arr_um_offset
def get_pix_size_um(sp) :
return sp._pixs
def get_pixel_size_arrs_um(sp) :
sp.make_pixel_size_arrs()
return sp.x_pix_size_um, sp.y_pix_size_um, sp.z_pix_size_um
def get_pixel_area_arr(sp) :
sp.make_pixel_size_arrs()
return sp.pix_area_arr
def get_seg_xy_maps_pix(sp) :
sp.x_pix_arr_pix = sp.x_pix_arr_um/sp._pixs
sp.y_pix_arr_pix = sp.y_pix_arr_um/sp._pixs
return sp.x_pix_arr_pix, sp.y_pix_arr_pix
def get_seg_xy_maps_pix_with_offset(sp) :
X, Y = sp.get_seg_xy_maps_pix()
xmin, ymin = X.min(), Y.min()
return X-xmin, Y-ymin
#------------------------------
# INTERFACE METHODS
#------------------------------
def print_seg_info(sp, pbits=0) :
""" Prints segment info for selected bits
pbits=0 - nothing
+1 - member data
+2 - coordinate maps in um
+4 - min, max coordinates in um
+8 - x, y 1-d pixel coordinate arrays in um
"""
if pbits & 1 : sp.print_member_data()
if pbits & 2 : sp.print_maps_seg_um()
if pbits & 4 : sp.print_xyz_min_max_um()
if pbits & 8 : sp.print_xy_1darr_um()
def size(sp) :
""" Returns number of pixels in segment
"""
return sp._rows*sp._cols
def rows(sp) :
""" Returns number of rows in segment
"""
return sp._rows
def cols(sp) :
""" Returns number of cols in segment
"""
return sp._cols
def shape(sp) :
""" Returns shape of the segment (rows, cols)
"""
return (sp._rows, sp._cols)
def pixel_scale_size(sp) :
""" Returns pixel size in um for indexing
"""
return sp._pixs
def pixel_area_array(sp) :
""" Returns pixel area array of shape=(rows, cols)
"""
return sp.get_pixel_area_arr()
def pixel_size_array(sp, axis=None) :
""" Returns numpy array of pixel sizes in um for AXIS
"""
return sp.return_switch(sp.get_pixel_size_arrs_um, axis)
def pixel_coord_array(sp, axis=None) :
""" Returns numpy array of segment pixel coordinates in um for AXIS
"""
return sp.return_switch(sp.get_seg_xyz_maps_um, axis)
def pixel_coord_min(sp, axis=None) :
""" Returns minimal value in the array of segment pixel coordinates in um for AXIS
"""
return sp.return_switch(sp.get_xyz_min_um, axis)
def pixel_coord_max(sp, axis=None) :
""" Returns maximal value in the array of segment pixel coordinates in um for AXIS
"""
return sp.return_switch(sp.get_xyz_max_um, axis)
def pixel_mask_array(sp, mbits=0377) :
""" Returns numpy array of pixel mask: 1/0 = ok/masked,
mbits=1 - mask edges
+2 - mask two central columns
+4 - mask non-bonded pixels
+8 - mask nearest neighbours of nonbonded pixels
"""
zero_col = np.zeros(sp._rows,dtype=np.uint8)
zero_row = np.zeros(sp._cols,dtype=np.uint8)
mask = np.ones((sp._rows,sp._cols),dtype=np.uint8)
if mbits & 1 :
# mask edges
mask[0, :] = zero_row # mask top edge
mask[-1,:] = zero_row # mask bottom edge
mask[:, 0] = zero_col # mask left edge
mask[:,-1] = zero_col # mask right edge
return mask
#------------------------------
#------------------------------
segment_one = SegGeometryMatrixV1()
#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)
#------------------------------
#------------------------------
#------------------------------
#----------- TEST -------------
#------------------------------
#------------------------------
#------------------------------
if __name__ == "__main__" :
import pyimgalgos.GlobalGraphics as gg # For test purpose in main only
[docs]def test_xyz_min_max() :
w = SegGeometryMatrixV1()
w.print_xyz_min_max_um()
print 'Ymin = ', w.pixel_coord_min('Y')
print 'Ymax = ', w.pixel_coord_max('Y')
#------------------------------
[docs]def test_xyz_maps() :
w = SegGeometryMatrixV1()
w.print_maps_seg_um()
titles = ['X map','Y map']
#for i,arr2d in enumerate([w.x_pix_arr,w.y_pix_arr]) :
for i,arr2d in enumerate( w.get_seg_xy_maps_pix() ) :
amp_range = (arr2d.min(), arr2d.max())
gg.plotImageLarge(arr2d, amp_range=amp_range, figsize=(10,5), title=titles[i])
gg.move(200*i,100*i)
gg.show()
#------------------------------
[docs]def test_img() :
t0_sec = time()
w = SegGeometryMatrixV1()
print 'Consumed time for coordinate arrays (sec) =', time()-t0_sec
X,Y = w.get_seg_xy_maps_pix()
w.print_seg_info(0377)
#print 'X(pix) :\n', X
print 'X.shape =', X.shape
xmin, ymin, zmin = w.get_xyz_min_um()
xmax, ymax, zmax = w.get_xyz_max_um()
xmin /= w.pixel_scale_size()
xmax /= w.pixel_scale_size()
ymin /= w.pixel_scale_size()
ymax /= w.pixel_scale_size()
xsize = xmax - xmin + 1
ysize = ymax - ymin + 1
print 'xsize =', xsize # 391.0
print 'ysize =', ysize # 185.0
H, Xedges, Yedges = np.histogram2d(X.flatten(), Y.flatten(), bins=[xsize,ysize], range=[[xmin, xmax], [ymin, ymax]], normed=False, weights=X.flatten()+Y.flatten())
print 'Xedges:', Xedges
print 'Yedges:', Yedges
print 'H.shape:', H.shape
gg.plotImageLarge(H, amp_range=(0, 1100), figsize=(8,10)) # range=(-1, 2),
gg.show()
#------------------------------
[docs]def test_img_easy() :
pc2x1 = SegGeometryMatrixV1()
#X,Y = pc2x1.get_seg_xy_maps_pix()
X,Y = pc2x1.get_seg_xy_maps_pix_with_offset()
iX, iY = (X+0.25).astype(int), (Y+0.25).astype(int)
img = gg.getImageFromIndexArrays(iX,iY,iX+iY)
gg.plotImageLarge(img, amp_range=(0, 1100), figsize=(8,10))
gg.show()
#------------------------------
[docs]def test_pix_sizes() :
w = SegGeometryMatrixV1()
w.print_pixel_size_arrs()
size_arr = w.pixel_size_array('X')
area_arr = w.pixel_area_array()
print 'area_arr[0:10,190:198]:\n', area_arr[0:10,190:198]
print 'area_arr.shape :', area_arr.shape
print 'size_arr[0:10,190:198]:\n', size_arr[0:10,190:198]
print 'size_arr.shape :', size_arr.shape
#------------------------------
[docs]def test_mask(mbits=0377) :
pc2x1 = SegGeometryMatrixV1()
X, Y = pc2x1.get_seg_xy_maps_pix_with_offset()
mask = pc2x1.pixel_mask_array(mbits)
iX, iY = (X+0.25).astype(int), (Y+0.25).astype(int)
img = gg.getImageFromIndexArrays(iX,iY,mask)
gg.plotImageLarge(img, amp_range=(-1, 2), figsize=(8,10))
gg.show()
#------------------------------
if __name__ == "__main__" :
if len(sys.argv)==1 : print 'For other test(s) use command: python', sys.argv[0], '<test-number=0-5>'
elif sys.argv[1]=='0' : test_xyz_min_max()
elif sys.argv[1]=='1' : test_xyz_maps()
elif sys.argv[1]=='2' : test_img()
elif sys.argv[1]=='3' : test_img_easy()
elif sys.argv[1]=='4' : test_pix_sizes()
elif sys.argv[1]=='5' : test_mask(mbits=1+2+4+8)
else : print 'Non-expected arguments: sys.argv=', sys.argv
sys.exit( 'End of test.' )
#------------------------------