Skip to content

Instantly share code, notes, and snippets.

@tjlane
Created June 17, 2013 00:03
Show Gist options
  • Save tjlane/5793931 to your computer and use it in GitHub Desktop.
Save tjlane/5793931 to your computer and use it in GitHub Desktop.
This script converts cheetah pixelmaps from the explicit-pixel cheetah format (which stores the x/y/z values for each pixel) to an Odin Detector object, which employs a basis representation.
#!/usr/bin/env python
"""
This script converts cheetah pixelmaps from the explicit-pixel cheetah format
(which stores the x/y/z values for each pixel) to an Odin Detector object,
which employs a basis representation.
-- TJL June 2013
"""
import sys
import h5py
import numpy as np
from pypad import read
from pypad.plot import sketch_2x1s
from odin import xray
pixel_size = 0.10992 # mm
def convert_cheetah_pixelmap_to_odin(filename, energy, distance_offset):
"""
Convert a cheetah pixelmap to an Odin Detector object.
Parameters
----------
filename : str
The path to the cheetah pixelmap.
energy : float
The energy of the beam, in eV.
distance_offset : float
A distance offset (along the z-direction), in mm. This can be measured
directly using a pypad.autogeom.score.PowderReference instance.
Returns
-------
dtc : xray.Detector
An Odin detector object.
"""
f = h5py.File(filename)
if not f.keys() == ['x', 'y', 'z']:
raise IOError('File: %s is not a valid pixel map, should contain fields'
' ["x", "y", "z"] exlusively' % filename)
# convert m --> mm
x = read.enforce_raw_img_shape( np.array(f['x']) * 1000.0 )
y = read.enforce_raw_img_shape( np.array(f['y']) * 1000.0 )
# for some reason z is in microns, so um --> mm
z = read.enforce_raw_img_shape( np.array(f['z']) / 1000.0 )
f.close()
bg = xray.BasisGrid()
shape = (185, 194) # will always be this for each ASIC
# loop over each ASIC, and convert it into a basis grid
for i in range(4):
for j in range(16):
# extract all the corner positions (code ineligant but explicit)
# corners are numbered 0 -> 4, starting top left and continuing cw
corners = np.zeros(( 4, 3 ))
corners[0,:] = ( x[i,j,0,0], y[i,j,0,0], z[i,j,0,0] )
corners[1,:] = ( x[i,j,0,-1], y[i,j,0,-1], z[i,j,0,-1] )
corners[2,:] = ( x[i,j,-1,-1], y[i,j,-1,-1], z[i,j,-1,-1] )
corners[3,:] = ( x[i,j,-1,0], y[i,j,-1,0], z[i,j,-1,0] )
# dont use this -- takes the vectors from 2 px inside the ASIC
# if your starting pixel map is good, this should give the same
# result as the above
# corners[0,:] = ( x[i,j,2,2], y[i,j,2,2], z[i,j,2,2] )
# corners[1,:] = ( x[i,j,2,-3], y[i,j,2,-3], z[i,j,2,-3] )
# corners[2,:] = ( x[i,j,-3,-3], y[i,j,-3,-3], z[i,j,-3,-3] )
# corners[3,:] = ( x[i,j,-3,2], y[i,j,-3,2], z[i,j,-3,2] )
# average the vectors formed by the corners to find f/s vects
# the fast scan direction is the last index, s is next
# f points left -> right, s points bottom -> top
f = (( corners[1,:] - corners[0,:] ) + ( corners[2,:] - corners[3,:] ))
s = (( corners[3,:] - corners[0,:] ) + ( corners[2,:] - corners[1,:] ))
# make them pixel-size magnitude
f = f * (pixel_size / np.linalg.norm(f))
s = s * (pixel_size / np.linalg.norm(s))
# center is just the average of the 4 corners
c = np.mean( corners, axis=0 )
assert c.shape == (3,)
c[2] += distance_offset
bg.add_grid_using_center(c, s, f, shape)
# recall that pypad assumes the beam is along the z-direction (CXI conven.)
energy /= 1000.0 # convert to keV : pypad is eV, Odin is keV
b = xray.Beam(1e11, energy=energy) # 1e11 photons per shot
d = xray.Detector(bg, b)
return d
def sketch_detector(detector):
"""
Sketch the ASICs of a detector.
Parameters
----------
detector : odin.xray.Detector
"""
pix_pos = np.zeros((3, 4, 16, 185, 194))
for i in range(4):
for j in range(16):
grid = d._basis_grid.grid_as_explicit(i*16 + j)
if grid.shape == (194,185,3):
for k in range(3):
pix_pos[k,i,j,:,:] = grid[:,:,k].T
else:
for k in range(3):
pix_pos[k,i,j,:,:] = grid[:,:,k]
sketch_2x1s(pix_pos)
return
if __name__ == '__main__':
print "Usage: %s <pixelmap.h5> <energy [keV]> <distance [mm]>" % sys.argv[0]
pixelmap = sys.argv[1]
energy = float(sys.argv[2])
distance_offset = float(sys.argv[3])
# the values for sellberg
# pixelmap = 'CSPAD2-Alignment-PostRun3_pixelmap.h5'
# energy = 9392.4 # avg eV, from sellberg
# distance_offset = 139.002 # mm, from sellberg
output = pixelmap[:-3] + '.dtc'
d = convert_cheetah_pixelmap_to_odin(pixelmap, energy, distance_offset)
sketch_detector(d)
d.save(output)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment