Skip to content
Snippets Groups Projects
Commit 9257fa88 authored by Valerio Mariani's avatar Valerio Mariani
Browse files

Improved geometry parsing and added functions to apply the geometry. Mostly Andrew's work

parent d083025d
No related branches found
No related tags found
No related merge requests found
......@@ -23,8 +23,140 @@ files.
import numpy
def apply_geometry_from_file(data_as_slab, geometry_filename):
"""Parse a geometry file and applies the geometry to detector data in 'slab' format.
Turns a 2d array of pixel values into an array containing a representation of the
physical layout of the detector, keeping the origin of the reference system at the
beam interaction point.
Args:
data_as_slab (numpy.ndarray): the pixel values to which geometry is to be applied.
geometry_filename (str): geometry filename.
Returns:
im_out (numpy.ndarray data_as_slab.dtype): Array containing a representation of the
physical layout of the detector, with the origin of the reference system at the
beam interaction point.
"""
yx, slab_shape, img_shape = pixel_maps_for_image_view(geometry_filename)
im_out = numpy.zeros(img_shape, dtype=data_as_slab.dtype)
im_out[yx[0], yx[1]] = data_as_slab.ravel()
return im_out
def apply_geometry_from_pixel_maps(data_as_slab, yx, im_out=None):
"""Applies geometry, in the form of pixel maps, to detector data in 'slab' format.
Turns a 2d array of pixel values into an array containing a representation of the
physical layout of the detector, keeping the origin of the reference system at the
beam interaction point.
Args:
data_as_slab (numpy.ndarray): the pixel values to which geometry is to be applied.
yx (tuple): the yx pixel maps describing the geometry of the detector.
Each map is a numpy.ndarray
im_out (numpy.ndarray) optional: array to hold the output. If not provided,
one will be generated automatically.
Returns:
im_out (numpy.ndarray data_as_slab.dtype): Array containing a representation of the
physical layout of the detector, with the origin of the reference system at the
beam interaction point.
"""
if im_out is None:
im_out = numpy.zeros(data_as_slab.shape, dtype=data_as_slab.dtype)
im_out[yx[0], yx[1]] = data_as_slab.ravel()
return im_out
def pixel_maps_for_image_view(geometry_filename):
"""Parse the geometry file and pixel maps for an array in 'slab' format
containing pixel values. The pixel maps can be used to create a representation
of the physical layout of the detector in a pyqtgraph ImageView widget (i.e.
they apply the detector geometry setting the origin of the reference
system is in the top left corner of the output array).
Args:
geometry_filename (str): geometry filename.
Returns:
(y, x) (numpy.ndarray int, numpy.ndarray int): pixel maps
slab_shape tuple (int, int): shape of the original geometry uncorrected array
(the pixel values in "slab" format).
img_shape tuple (int, int): shape of the array needed to contain the
representation of the physical layout of the detector.
"""
pixm = pixel_maps_from_geometry_file(geometry_filename)
x, y = pixm[0], pixm[1]
slab_shape = x.shape
# find the smallest size of cspad_geom that contains all
# xy values but is symmetric about the origin
n = 2 * int(max(abs(y.max()), abs(y.min()))) + 2
m = 2 * int(max(abs(x.max()), abs(x.min()))) + 2
# convert y x values to i j values
i = numpy.array(y, dtype=numpy.int) + n/2 - 1
j = numpy.array(x, dtype=numpy.int) + m/2 - 1
yx = (i.flatten(), j.flatten())
img_shape = (n, m)
return yx, slab_shape, img_shape
def parse_xy(string):
"""Parse the x, y values from strings that have the format:
'1x + 2.0y'.
Args:
string (str): the string to be parsed.
Returns:
[x, y] [float, float]:
len two list of floats, e.g.:
1x + 2.y --> [1., 2.]
1x --> [1., 0.]
x --> [1., 0.]
"""
x = y = 0
if string.find('x') is not -1:
xs = string.split('x')[0].split(' ')[-1]
if len(xs) > 0:
x = float(xs)
else:
x = 1.
if string.find('y') is not -1:
ys = string.split('y')[0].split(' ')[-1]
if len(ys) > 0:
y = float(ys)
else:
y = 1.
return [x, y]
def pixel_maps_from_geometry_file(fnam):
"""Extracts pixel maps from a CrystFEL-style geometry file.
"""Extracts pixel maps from a CrystFEL-style geometry file. The pixel maps
can be used to create a representation of the physical layout of the
detector, keeping the origin of the reference system at the beam interaction
point.
Args:
......@@ -35,7 +167,6 @@ def pixel_maps_from_geometry_file(fnam):
x,y,r (numpy.ndarray float, numpy.ndarray float, numpy.ndarray float):
slab-like pixel maps with respectively x, y coordinates of the pixel
and distance of the pixel from the center of the reference system
(usually the beam position).
"""
f = open(fnam, 'r')
......@@ -46,7 +177,9 @@ def pixel_maps_from_geometry_file(fnam):
detector_dict = {}
panel_lines = [x for x in f_lines if '/' in x and len(x.split('/')) == 2 and x.split('/')[1].split('=')[0].strip() in keyword_list]
panel_lines = [x for x in f_lines if '/' in x and
len(x.split('/')) == 2 and x.split('/')[1].split('=')[0].strip() in keyword_list and
'bad_' not in x.split('/')[0].strip()]
for pline in panel_lines:
items = pline.split('=')[0].split('/')
......@@ -67,12 +200,8 @@ def pixel_maps_from_geometry_file(fnam):
parsed_detector_dict[p]['max_fs'] = int(detector_dict[p]['max_fs'])
parsed_detector_dict[p]['min_ss'] = int(detector_dict[p]['min_ss'])
parsed_detector_dict[p]['max_ss'] = int(detector_dict[p]['max_ss'])
parsed_detector_dict[p]['fs'] = []
parsed_detector_dict[p]['fs'].append(float(detector_dict[p]['fs'].split('x')[0]))
parsed_detector_dict[p]['fs'].append(float(detector_dict[p]['fs'].split('x')[1].split('y')[0]))
parsed_detector_dict[p]['ss'] = []
parsed_detector_dict[p]['ss'].append(float(detector_dict[p]['ss'].split('x')[0]))
parsed_detector_dict[p]['ss'].append(float(detector_dict[p]['ss'].split('x')[1].split('y')[0] ) )
parsed_detector_dict[p]['fs'] = parse_xy(detector_dict[p]['fs'])
parsed_detector_dict[p]['ss'] = parse_xy(detector_dict[p]['ss'])
parsed_detector_dict[p]['corner_x'] = float(detector_dict[p]['corner_x'])
parsed_detector_dict[p]['corner_y'] = float(detector_dict[p]['corner_y'])
......@@ -85,7 +214,8 @@ def pixel_maps_from_geometry_file(fnam):
for p in parsed_detector_dict.keys():
# get the pixel coords for this asic
i, j = numpy.meshgrid(numpy.arange(parsed_detector_dict[p]['max_ss'] - parsed_detector_dict[p]['min_ss'] + 1),
numpy.arange(parsed_detector_dict[p]['max_fs'] - parsed_detector_dict[p]['min_fs'] + 1), indexing='ij')
numpy.arange(parsed_detector_dict[p]['max_fs'] - parsed_detector_dict[p]['min_fs'] + 1),
indexing='ij')
#
# make the y-x ( ss, fs ) vectors, using complex notation
......@@ -95,8 +225,11 @@ def pixel_maps_from_geometry_file(fnam):
#
r = i * dy + j * dx + r_0
#
y[parsed_detector_dict[p]['min_ss']: parsed_detector_dict[p]['max_ss'] + 1, parsed_detector_dict[p]['min_fs']: parsed_detector_dict[p]['max_fs'] + 1] = r.real
x[parsed_detector_dict[p]['min_ss']: parsed_detector_dict[p]['max_ss'] + 1, parsed_detector_dict[p]['min_fs']: parsed_detector_dict[p]['max_fs'] + 1] = r.imag
y[parsed_detector_dict[p]['min_ss']: parsed_detector_dict[p]['max_ss'] + 1,
parsed_detector_dict[p]['min_fs']: parsed_detector_dict[p]['max_fs'] + 1] = r.real
x[parsed_detector_dict[p]['min_ss']: parsed_detector_dict[p]['max_ss'] + 1,
parsed_detector_dict[p]['min_fs']: parsed_detector_dict[p]['max_fs'] + 1] = r.imag
r = numpy.sqrt(numpy.square(x) + numpy.square(y))
......@@ -123,7 +256,7 @@ def coffset_from_geometry_file(fnam):
for line in f_lines:
if line.startswith('coffset'):
coffset = float(line.split('=')[1].split('#')[0])
coffset = float(line.split('=')[1].split(';')[0])
return coffset
......@@ -148,6 +281,6 @@ def res_from_geometry_file(fnam):
for line in f_lines:
if line.startswith('res'):
res = float(line.split('=')[1].split('#')[0])
res = float(line.split('=')[1].split(';')[0])
return res
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment