ImageD11.sinograms package¶
Submodules¶
ImageD11.sinograms.assemble_label module¶
- ImageD11.sinograms.assemble_label.filterpixels(cutimage, row, col, intensity, nnz)¶
cutimage = 2D image of thresholds to use row, col, intensity = pixels nnz = pixels per frame for a stack of images in row/col/intensity
- ImageD11.sinograms.assemble_label.getsparse(dsobj, num)¶
dsobj = DataSet object returns the pixels from the sparse segmentation
- ImageD11.sinograms.assemble_label.harvest_masterfile(dset, outname, scanmotors=('diffrz', 'diffrz_cen360', 'diffrz_center', 'fpico4', 'fpico3', 'diffty', 'diffty_center', 'rot', 'rot_cen360', 'rot_center', 'fpico6', 'dty', 'dty_center'), headermotors=('diffty', 'diffrz', 'samtx', 'samty', 'samtz', 'diffry', 'samrx', 'samry', 'dty', 'rot', 'pz', 'px', 'py', 'shtz', 'shty', 'shtx'), cutimage=None)¶
dset = ImageD11.sinograms.dataset.DataSet object outname = sparse file to write
- cut = image = 2D image of cutoffs for keeping pixels (e.g. keep high angle
and use a higher threshold for low angle or noisy)
- ImageD11.sinograms.assemble_label.main(dsname, outname=None, cutimage=None)¶
dsname = Dataset describing the masterfile + segmentation etc outname = sparse pixels file to write. Defaults to dset.sparsefile
- ImageD11.sinograms.assemble_label.testready(dsobj)¶
assume they are finish if they exist. Might be still writing ???
ImageD11.sinograms.dataset module¶
- class ImageD11.sinograms.dataset.DataSet(dataroot='.', analysisroot='.', sample='sample', dset='dataset', detector='eiger', omegamotor='rot_center', dtymotor='dty', filename=None, analysispath=None)¶
Bases:
objectOne DataSet instance per detector!
- ATTRNAMES = ('dataroot', 'analysisroot', 'sample', 'dset', 'shape', 'dsname', 'datapath', 'analysispath', 'masterfile', 'limapath', 'detector', 'omegamotor', 'dtymotor', 'monitorname', 'pksfile', 'sparsefile', 'parfile', 'e2dxfile', 'e2dyfile', 'splinefile', 'maskfile', 'bgfile', 'pksfile', 'col4dfile', 'col3dfile', 'col2dfile', 'grainsfile', 'sparsefile', 'icolfile', 'pbpfile')¶
- NDNAMES = ('omega', 'dty', 'nnz', 'frames_per_file', 'nlm', 'frames_per_scan', 'monitor')¶
- STRINGLISTS = ('scans', 'imagefiles', 'sparsefiles')¶
- check_files(path, filenames, verbose=0)¶
See whether files are created or not
- check_images()¶
Is the experiment finished ?
- check_sparse()¶
Has the segmentation been done ?
- compare(other)¶
Try to see if the load/save is working
- correct_bins_for_half_scan(y0=0)¶
Pads the dataset to become bigger and symmetric
- get_cf_2d()¶
- get_cf_2d_from_disk()¶
- get_cf_3d_from_disk()¶
- get_cf_4d()¶
- get_cf_4d_from_disk()¶
- get_colfile_from_peaks_dict(peaks_dict=None)¶
Converts a dictionary of peaks (peaks_dict) into an ImageD11 columnfile adds on the geometric computations (tth, eta, gvector, etc) Uses self.pk2d if no peaks_dict provided
- get_grains_from_disk(phase_name=None)¶
- get_monitor(name='fpico6')¶
- get_monitor_pk2d(pk2d, name='fpico6')¶
To be used to normalise the peaks 2d
- get_phases_from_disk()¶
- get_ring_current_per_scan()¶
Gets the ring current for each scan (i.e rotation/y-step) Stores it inside self.ring_currents_per_scan and a scaled version inside self.ring_currents_per_scan_scaled
- guess_detector()¶
Guess which detector we are using from the masterfile
- guess_shape()¶
Guess the shape if it was not given
- guessbins()¶
- import_all(scans=None, shape=None)¶
- import_from_sparse(hname, scans=None, shape=None)¶
hname = hdf5 file containing sparse pixels (and motors) dataset = a dataset instance to import into scans = defaults to reading all “%d.1” scans in the file
give a list to read in some other order or a subset
- import_imagefiles()¶
Get the Lima file names from the bliss master file, also scan_npoints
- import_motors_from_master()¶
read the motors from the lima file you need to import the imagefiles first these will be the motor positions to accompany the images # could also get these from sparse files if saved
- import_nnz()¶
Read the nnz arrays from the sparsefiles
- import_nnz_from_sparse()¶
Read the nnz arrays from the sparsefiles
- import_scans(scans=None, hname=None)¶
Reads in the scans from the bliss master file
- load(h5name=None, h5group='/')¶
- property peaks_table¶
- property pk2d¶
- property pk4d¶
- report()¶
- save(h5name=None, h5group='/')¶
- save_grains_to_disk(grains, phase_name=None)¶
- sinohist(weights=None, omega=None, dty=None, method='fast')¶
Bin some data onto the sinogram histogram
- update_colfile_pars(cf, phase_name=None)¶
Load parameters and update geometry for colfile
- update_paths(force=False, verbose=False)¶
- ImageD11.sinograms.dataset.check(dataroot, analysisroot, sample, dset, destination, scans=None)¶
- ImageD11.sinograms.dataset.guess_chunks(name, shape)¶
- ImageD11.sinograms.dataset.load(h5name, h5group='/')¶
ImageD11.sinograms.geometry module¶
Sinogram-related geometric functions pulled from various places. The choice of reference frames is tricky. In regular 3DXRD, the origin of the lab reference frame is defined as the intersection between the middle of the beam and the rotation axis. However, because the rotation axis is moving, this gets more difficult for scanning 3DXRD. I have therefore defined the reference frames in the following way:
Static lab frame - vectors defined by the beam vector and the dty translation axis vector. Its origin is defined directly as (0,0,0): x: The intersection of the beam vector and the dty translation axis vector y: The centre of the beam horizontally z: The centre of the beam vertically dtyi is a discretisation of the dty motor values.
Sample frame Origin is the rotation axis The rotation axis is translated by dty. The sample frame rotates with omega This translates with dty and rotates with omega, CW about the rotation axis (looking top down). This has the rotation axis at its origin. y0 is the true value of dty when the rotation axis intersects the beam.
Step space This is simply an integer discretisation of the sample frame.
Reconstruction space: units are (ystep), origin in corner (matches iradon output) when plotted with origin=”lower”, coords are (ri, rj)
Diagrams are below, S indicates the rotation axis
lab frame:
x
- <——- O (0, 0) centre of beam
y
sample frame (could be rotated about omega then translated along lab y by dty):
x
- <——- S (0, 0)
y
Step space:
+ve ^ |
- i |
- -ve <——– S (0, 0)——–> +ve
- j
v
-ve
Reconstruction space (iradon output when plotted with origin=”lower”):
- i | S
- (0, 0) ——->
j
- ImageD11.sinograms.geometry.dty_to_dtyi(dty, ystep, ymin)¶
We take continuous dty space and discretise it We do this by counting the number of ysteps away from ymin ymin should probably be ds.ymin This should be equivalent to determining the closest bin in ds.ybincens But this is neater as it accounts for values outside the ds.ybincens range
dtyi = (dty - ymin) / ystep
- ImageD11.sinograms.geometry.dty_values_grain_in_beam(sx, sy, y0, omega)¶
Calls dty_values_grain_in_beam_sincos after converting omega (degrees) into sinomega, cosomega
- ImageD11.sinograms.geometry.dty_values_grain_in_beam_sincos(sx, sy, y0, sinomega, cosomega)¶
Take a grain positioned at (sx, sy) in the sample reference frame Determine the dty values needed to bring the grain into the beam as you rotate by omega. Equivalently, solve the sample<->lab conversion where ly = 0 (grain is in-beam). From sample_to_lab_sincos:
sxr = sx * cosomega - sy * sinomega syr = sx * sinomega + sy * cosomega
lx = sxr ly = syr + dty - y0
Therefore: ly = sx * sinomega + sy * cosomega + dty - y0
Solving for ly = 0: 0 = sx * sinomega + sy * cosomega + dty - y0 dty = y0 - sx * sinomega - sy * cosomega
- ImageD11.sinograms.geometry.dtyi_to_dty(dtyi, ystep, ymin)¶
Simply: dty = (dtyi * ystep) + ymin
- ImageD11.sinograms.geometry.dtyimask_from_recon(ri, rj, omega, dtyi, y0, ystep, ymin, recon_shape)¶
Given a position in recon space (ri, rj) and arrays of (omega, dtyi) values Convert recon space (ri, rj) to sample space (sx, sy) Mask each (omega, dtyi) value if they put the position (sx, sy) into the beam
- ImageD11.sinograms.geometry.dtyimask_from_recon_sincos(ri, rj, sinomega, cosomega, dtyi, y0, ystep, ymin, recon_shape)¶
Given a position in recon space (ri, rj) and arrays of (sinomega, cosomega, dtyi) values Convert recon space (ri, rj) to sample space (sx, sy) Mask each (sinomega, cosomega, dtyi) value if they put the position (sx, sy) into the beam
- ImageD11.sinograms.geometry.dtyimask_from_sample(sx, sy, omega, dtyi, y0, ystep, ymin)¶
Given a position in the sample (sx, sy) and arrays of (omega, dtyi) values Mask each (omega, dtyi) value if they put the position (sx, sy) into the beam
- ImageD11.sinograms.geometry.dtyimask_from_sample_sincos(sx, sy, sinomega, cosomega, dtyi, y0, ystep, ymin)¶
Given a position in the sample (sx, sy) and arrays of (sinomega, cosomega, dtyi) values Mask each (sinomega, cosomega, dtyi) value if they put the position (sx, sy) into the beam
- ImageD11.sinograms.geometry.dtyimask_from_step(si, sj, omega, dtyi, y0, ystep, ymin)¶
Given a position in step space (si, sj) and arrays of (omega, dtyi) values Convert step space (si, sj) to sample space (sx, sy) Mask each (omega, dtyi) value if they put the position (sx, sy) into the beam
- ImageD11.sinograms.geometry.dtyimask_from_step_sincos(si, sj, sinomega, cosomega, dtyi, y0, ystep, ymin)¶
Given a position in step space (si, sj) and arrays of (sinomega, cosomega, dtyi) values Convert step space (si, sj) to sample space (sx, sy) Mask each (sinomega, cosomega, dtyi) value if they put the position (sx, sy) into the beam
- ImageD11.sinograms.geometry.fit_sample_position_from_recon(recon, ystep)¶
Fits grain position in sample space by doing a LoG search with skimage on the reconstruction image Useful if grain is very small (close to pointlike) Returns position in sample frame (unit matches ystep) Returns None if we couldn’t find any blobs
- ImageD11.sinograms.geometry.fit_sine_wave(omega, dty, initial_guess, weights=None)¶
Take a series of (omega, dty) values that originate from the same point in the sample. Determine the point in sample coordinates (sx, sy) by fitting a sine wave to the data. Includes a possible shift of the rotation axis in y (y0). In practice, we perform a curve_fit on dty_values_grain_in_beam to determine sx, sy, y0
- ImageD11.sinograms.geometry.lab_to_recon(lx, ly, y0, dty, omega, recon_shape, ystep)¶
Converts lab space (lx, ly) to recon space (ri, rj)
- ImageD11.sinograms.geometry.lab_to_sample(lx, ly, y0, dty, omega)¶
Calls lab_to_sample_sincos after converting omega (degrees) into sinomega, cosomega
- ImageD11.sinograms.geometry.lab_to_sample_sincos(lx, ly, y0, dty, sinomega, cosomega)¶
Converts position in lab frame (lx, ly) to position in lab frame (sx, sy). The units of sx, sy, y0, and dty must agree.
- Parameters:
lx ((float, np.ndarray)) – X-coordinate in lab reference frame
ly ((float, np.ndarray)) – Y-coordinate in lab reference frame
y0 (float) – the true value of dty when the rotation axis intersects the beam
dty ((float, np.ndarray)) – the dty motor underneath the rotation axis
sinomega ((float, np.ndarray)) – the sine of the omega value of the rotation axis
cosomega ((float, np.ndarray)) – the cosine of the omega value of the rotation axis
- Returns:
sx, su: the x and y coordinates in the sample reference frame
- Return type:
((float, np.ndarray), (float, np.ndarray))
- ImageD11.sinograms.geometry.lab_to_step(lx, ly, y0, dty, omega, ystep)¶
Converts lab space (lx, ly) to step space (si, sj)
- ImageD11.sinograms.geometry.recon_omega_to_dty(ri, rj, omega, y0, recon_shape, ystep)¶
Convert recon space (ri, rj) to step space (si, sj) Then get corresponding dty values which puts (si, sj) into the beam given omega
- ImageD11.sinograms.geometry.recon_omega_to_dtyi(ri, rj, omega, y0, recon_shape, ystep, ymin)¶
Convert recon space (ri, rj) to step space (si, sj) Then get corresponding dtyi values which puts (si, sj) into the beam given omega Then converts dty to dtyi
- ImageD11.sinograms.geometry.recon_to_lab(ri, rj, y0, dty, omega, recon_shape, ystep)¶
Converts recon space (ri, rj) to lab space (lx, ly)
- ImageD11.sinograms.geometry.recon_to_sample(ri, rj, recon_shape, ystep)¶
Converts reconstruction space (ri, rj) to sample space (sx, sy)
- ImageD11.sinograms.geometry.recon_to_step(ri, rj, recon_shape)¶
Converts reconstruction space (ri, rj) to step space (si, sj)
- ImageD11.sinograms.geometry.sample_to_lab(sx, sy, y0, dty, omega)¶
Calls sample_to_lab_sincos after converting omega (degrees) into sinomega, cosomega
- ImageD11.sinograms.geometry.sample_to_lab_sincos(sx, sy, y0, dty, sinomega, cosomega)¶
Converts position in sample frame (sx, sy) to position in lab frame (lx, ly). The units of sx, sy, y0, and dty must agree.
- Parameters:
sx ((float, np.ndarray)) – X-coordinate in sample reference frame
sy ((float, np.ndarray)) – Y-coordinate in sample reference frame
y0 (float) – the true value of dty when the rotation axis intersects the beam
dty ((float, np.ndarray)) – the dty motor underneath the rotation axis
sinomega ((float, np.ndarray)) – the sine of the omega value of the rotation axis
cosomega ((float, np.ndarray)) – the cosine of the omega value of the rotation axis
- Returns:
lx, ly: the x and y coordinates in the lab reference frame
- Return type:
((float, np.ndarray), (float, np.ndarray))
- ImageD11.sinograms.geometry.sample_to_recon(sx, sy, recon_shape, ystep)¶
Converts sample space (sx, sy) to reconstruction space (ri, rj)
- ImageD11.sinograms.geometry.sample_to_step(sx, sy, ystep)¶
Converts sample (sx, sy) position to step space (si, sj)
- ImageD11.sinograms.geometry.sino_shift_and_pad(y0, ny, ymin, ystep)¶
Determine the difference in sinogram pixels between the central dtyi value of the sinogram and the dtyi value of the rotation axis (from y0) To do this, we convert y0 into dtyi without rounding Also determine the minimum pad to get the whole sample in the frame Which should be double the shift
- ImageD11.sinograms.geometry.step_grid_from_ybincens(ybincens, step_size, gridstep, y0)¶
Produce a grid in (si, sj) step space to reconstruct on. Constructs a symmetric grid with the origin on y0 Therefore the step space is truly aligned to the rotation axis. The size of the grid is determined by the extremes of ybincens. The grid will always be symmetric such that (0, 0) is the centre of an image formed from the grid :param ybincens: An evenly sampled dty space :type ybincens: np.ndarray :param step_size: the step size of the grid (same units as ybincens and y0) :type step_size: float :param gridstep: the sampling resolution of the grid (e.g 2 = [0, 2, 4, 6, …]) :type gridstep: int :return: (si, sj) for si in ints for sj in ints :rtype: tuple(int, int)
- ImageD11.sinograms.geometry.step_omega_to_dty(si, sj, omega, y0, ystep)¶
Convert step space (si, sj) to sample space (sx, sy) Then get corresponding dty values which puts (sx, sy) into the beam given omega
- ImageD11.sinograms.geometry.step_omega_to_dtyi(si, sj, omega, y0, ystep, ymin)¶
Convert step space (si, sj) to sample space (sx, sy) Then get corresponding dty values which puts (sx, sy) into the beam given omega Then converts dty to dtyi
- ImageD11.sinograms.geometry.step_to_lab(si, sj, y0, dty, omega, ystep)¶
Converts step space (si, sj) to lab space (lx, ly)
- ImageD11.sinograms.geometry.step_to_recon(si, sj, recon_shape)¶
Converts step space (si, sj) to reconstruction space (ri, rj)
- ImageD11.sinograms.geometry.step_to_sample(si, sj, ystep)¶
Converts step space (si, sj) to sample position (sx, sy)
- ImageD11.sinograms.geometry.sx_sy_y0_from_dty_omega(dty, omega, weights=None)¶
Fits sine wave to dty vs omega plot, extracts sx, sy, y0
ImageD11.sinograms.lima_segmenter module¶
- class ImageD11.sinograms.lima_segmenter.SegmenterOptions(cut=1, howmany=100000, pixels_in_spot=3, maskfile='', bgfile='', cores_per_job=1, files_per_core=8)¶
Bases:
object- datasetnames = ('limapath', 'analysispath', 'datapath', 'imagefiles', 'sparsefiles')¶
- jobnames = ('cut', 'howmany', 'pixels_in_spot', 'maskfile', 'bgfile', 'cores_per_job', 'files_per_core')¶
- load(h5name, h5group)¶
- save(h5name, h5group)¶
- setup()¶
- ImageD11.sinograms.lima_segmenter.clean(nnz, row, col, val)¶
- class ImageD11.sinograms.lima_segmenter.frmtosparse(mask, dtype)¶
Bases:
object
- ImageD11.sinograms.lima_segmenter.initOptions(h5name, jobid)¶
- ImageD11.sinograms.lima_segmenter.main(h5name, jobid)¶
- ImageD11.sinograms.lima_segmenter.reader(frms, mask, cut, start=0)¶
iterator to read chunks or frames and segment them returns sparseframes
- ImageD11.sinograms.lima_segmenter.sbatchlocal(fname, cores=None)¶
Execute a grid batch job on the local machine Loops over the array submission for you
- ImageD11.sinograms.lima_segmenter.segment()¶
- ImageD11.sinograms.lima_segmenter.segment_lima(args)¶
Does segmentation on a single hdf5 srcname, destname, dataset
- ImageD11.sinograms.lima_segmenter.select(img, mask, row, col, val, cut)¶
- ImageD11.sinograms.lima_segmenter.setup(dsname, cut=None, howmany=100000, pixels_in_spot=3, maskfile='', bgfile='', cores_per_job=8, files_per_core=8, pythonpath=None)¶
Writes options into the dataset file cut=None is replaced by 1 for eiger, 25 otherwise pythonpath -> point to a non-default install
- ImageD11.sinograms.lima_segmenter.setup_slurm_array(dsname, dsgroup='/', pythonpath=None)¶
Send the tasks to slurm
- ImageD11.sinograms.lima_segmenter.top_pixels(nnz, row, col, val, howmany, thresholds)¶
selects the strongest pixels from a sparse collection - THRESHOLDS should be a sorted array of potential cutoff values to try that are higher than the original cutoff used to select data - howmany is the maximum number of pixels to return
ImageD11.sinograms.point_by_point module¶
- class ImageD11.sinograms.point_by_point.PBP(parfile, dset, hkl_tol=0.01, fpks=0.7, ds_tol=0.005, etacut=0.1, ifrac=None, gmax=5, cosine_tol=0.0017453283658982615, y0=0, symmetry='cubic', loglevel=3, foridx=None, forgen=None, uniqcut=0.75, phase_name=None)¶
Bases:
object- iplot(skip=1)¶
- point_by_point(grains_filename, icolf_filename=None, nprocs=None, gridstep=1, debugpoints=None, loglevel=3)¶
grains_filename = output file icolf_filename = hdf5file to write. Allows mmap to be used.
- setpeaks(colf, icolf_filename=None)¶
This is called on the main parent process
The peaks will be written to file
- class ImageD11.sinograms.point_by_point.PBPMap(*args, **kwargs)¶
Bases:
columnfileColumnfile for point-by-point indexing and refinement results. The results of point-by-point indexing and refinement can be multi-valued e.g there can be more than one UBI found at a given map pixel Therefore this class stores pixel results in the following way:
# i j ntotal nuniq ubi00 ubi01 ubi02 ubi10 ubi11 ubi12 ubi20 ubi21 ubi22
We have an extra method to get all the results at one pixel: self.get_pixel_mask() There’s another concept: selecting a single best UBI at each pixel This will fill in self.best_UBI, self.best_npks, self.best_nuniq
- property NI¶
- property NJ¶
- property NY¶
- property UBI¶
- choose_best(minpeaks=6)¶
- property eps¶
eps computed on-demand from reshaping eps columns shape is (3, 3, nrows) to match previous PBPMap definition
- get_pixel_mask(i, j)¶
Return mask to columnfile with those specified i and j values
- property i_shift¶
- property j_shift¶
- plot_best(minpeaks=6)¶
- plot_nuniq_hist()¶
- property ubi¶
ubi computed on-demand from reshaping ubi columns. shape is (3, 3, nrows) to match previous PBPMap definition
- class ImageD11.sinograms.point_by_point.PBPRefine(dset, phase_name, hkl_tol_origins=0.05, hkl_tol_refine=0.1, hkl_tol_refine_merged=0.05, ds_tol=0.005, etacut=0.1, ifrac=None, forref=None, y0=0.0, min_grain_npks=6)¶
Bases:
objectClass to manage point-by-point refinement. The maps in this class are set up on a grid that matches the PBPMap reference frame This is in step space in geometry.py
- classmethod from_h5(filename, h5group='PBPRefine')¶
- get_origins(guess_speed=True, guess_npks=10000, save_peaks_after=True)¶
- iplot(skip=1)¶
Same as PBP.iplot for now
- loadmap(filename=None, refined=False)¶
Load an existing input/refined PBPMap from h5. If you only have a .txt file, you want self.setmap()
- loadpeaks(icolf_filename=None)¶
Load icolf from disk
- run_refine(points_step_space=None, npoints=None, output_filename=None, use_cluster=False, pythonpath=None)¶
Call ImageD11.sinograms.point_by_point.refine_map to refine If you say use_cluster, will save the refinement object to disk Then submit a job to slurm to refine
- savemap(filename=None, refined=False)¶
Save self.pbpmap/self.refinedmap to an H5 file
- savepeaks(icolf_filename=None, del_existing=False)¶
- setmap(pbpmap)¶
Set an input PBPMap Python object to use
- setmask(manual_threshold=None, doplot=False, use_icolf=True)¶
Set a mask for choosing what to refine or not. You can choose whether to use self.colf (all peaks) or self.icolf (selected peaks) At the moment it does an iradon on the sinogram of all the 2D peaks in self.colf
- setpeaks(colf, icolf_filename=None, del_existing=True, prompt_del=True)¶
Similar to PBP.setpeaks for now
- setsingle(pbpmap, method='best', **method_args)¶
Function to go from a multi-valued PBPMap to a single-valued PBPMap
- to_h5(filename=None, h5group='PBPRefine')¶
- ImageD11.sinograms.point_by_point.compute_g_from_k(k, omega, wedge=0, chi=0)¶
Compute g-vectors with cached k-vectors
- ImageD11.sinograms.point_by_point.compute_g_vectors(tth, eta, omega, wvln, wedge=0.0, chi=0.0)¶
- Generates spot positions in reciprocal space from
twotheta, wavelength, omega and eta
Assumes single axis vertical … unless a wedge angle is specified
- ImageD11.sinograms.point_by_point.compute_grain_origins(omega, wedge, chi, t_x, t_y, t_z)¶
- ImageD11.sinograms.point_by_point.compute_gve(sc, fc, omega, xpos, distance, y_center, y_size, tilt_y, z_center, z_size, tilt_z, tilt_x, o11, o12, o21, o22, t_x, t_y, t_z, wedge, chi, wavelength)¶
- ImageD11.sinograms.point_by_point.compute_k_vectors(tth, eta, wvln)¶
generate k vectors - scattering vectors in laboratory frame
- ImageD11.sinograms.point_by_point.compute_origins(singlemap, sample_mask, gve, sinomega, cosomega, omega, dty, sx_grid, sy_grid, y0, ystep, hkl_tol, sorter)¶
Compute origins of diffraction for each peak For each dty, omega value, we cast a ray through singlemap Along the ray, we get the UBIs in singlemap If the UBI indexes the peak, we consider it For each peak, we then work out the weighted origin position in x Adapted from Axel codebase
- ImageD11.sinograms.point_by_point.compute_tth_eta(sc, fc, omega, y_center=0.0, y_size=0.0, tilt_y=0.0, z_center=0.0, z_size=0.0, tilt_z=0.0, tilt_x=0.0, distance=0.0, o11=1.0, o12=0.0, o21=0.0, o22=-1.0, t_x=0.0, t_y=0.0, t_z=0.0, wedge=0.0, chi=0.0)¶
- ImageD11.sinograms.point_by_point.compute_tth_eta_from_xyz(peaks_xyz, omega, t_x=0.0, t_y=0.0, t_z=0.0, wedge=0.0, chi=0.0)¶
- ImageD11.sinograms.point_by_point.compute_xyz_lab(sc, fc, y_center=0.0, y_size=0.0, tilt_y=0.0, z_center=0.0, z_size=0.0, tilt_z=0.0, tilt_x=0.0, distance=0.0, o11=1.0, o12=0.0, o21=0.0, o22=-1.0)¶
- ImageD11.sinograms.point_by_point.count_unique_peaks(hkl, etasign, dtyi)¶
- ImageD11.sinograms.point_by_point.count_unique_peaks_no_dtyi(hkl, etasign)¶
- ImageD11.sinograms.point_by_point.detector_rotation_matrix(tilt_x, tilt_y, tilt_z)¶
- ImageD11.sinograms.point_by_point.divide_where(arr1, arr2, out, wherearr)¶
Do arr1/arr2. In locations where wherearr == 0, return out instead
- ImageD11.sinograms.point_by_point.get_local_gv(si, sj, ystep, omega, sinomega, cosomega, xl, yl, zl)¶
Given a point (si, sj) in step space, compute the x values in the lab frame for each omega angle Then subtract them from xl to account for the change in the diffraction origin point. Then re-compute the g-vectors.
- ImageD11.sinograms.point_by_point.get_voxel_idx(y0, xi0, yi0, sinomega, cosomega, dty, ystep)¶
get peaks at xi0, yi0 basically just geometry.dty_values_grain_in_beam_sincos
- ImageD11.sinograms.point_by_point.gve_norm(gve)¶
- ImageD11.sinograms.point_by_point.hkluniq(ubi, gx, gy, gz, eta, m, tol, hmax)¶
count uniq peaks - move to cImageD11 in the future
- ImageD11.sinograms.point_by_point.idxpoint(si, sj, isel, omega, sinomega, cosomega, dtyi, xl, yl, zl, eta, ystep=2.0, y0=0.0, ymin=-2.0, minpks=1000, hkl_tol=0.1, ds_tol=0.005, cosine_tol=0.0017453283658982615, forgen=None, hmax=-1, uniqcut=0.75)¶
Indexing function called at one point in space. Selects peaks from the sinogram and attempts to index. More of this could be indexing.py I guess.
si, sj = position in step space (origin is rotation axis)
- Effectively a columnfile:
isel = column of rings to use sinomega = column of sinomega cosomega = column of cosomega dtyi = column of dty on integer bins gx/gy/gz/eta = peak co-ordinates
ystep, y0 = compute the dtyi bins to select peaks (dtymask function above)
forgen = the rings to use for INDEXING / orientation searching (a speedup effect)
minpks = number of peaks to find with rings hkl_tol = ImageD11 tolerance of indexed == | h-int(h) | < hkl_tol cosine_tol = ImageD11 tolerance for finding pairs of peaks
uniqcut = unique peaks cutoff (uniq> ucut * max are returned)
- returns a list of :
(npks, nuniq, ubi)
- ImageD11.sinograms.point_by_point.initializer(parfile, phase_name, symmetry, colfile, loglevel=3)¶
- ImageD11.sinograms.point_by_point.merge(hkl, etasign, dtyi, sum_intensity, sc, fc, omega, dty, xpos_refined, eta)¶
merge peaks with the same (h, k, l, etasign, dtyi) weighted by sum_intensity
- ImageD11.sinograms.point_by_point.nb_choose_best(i, j, u, n, NY, ubiar, minpeaks=6)¶
- ImageD11.sinograms.point_by_point.nb_inv(mats, imats)¶
- ImageD11.sinograms.point_by_point.nb_inv_3d(mats, imats)¶
- ImageD11.sinograms.point_by_point.prepare_refine_bash(pbp_object, id11_code_path, output_filename)¶
- ImageD11.sinograms.point_by_point.proxy(args)¶
Wrapper function for multiprocessing
- ImageD11.sinograms.point_by_point.refine_map(refine_points, all_pbpmap_ubis, ri_col, rj_col, sx_grid, sy_grid, mask, sc, fc, eta, sum_intensity, sinomega, cosomega, omega, dty, dtyi, xpos, ystep, y0, B0, distance, y_center, y_size, tilt_y, z_center, z_size, tilt_z, tilt_x, o11, o12, o21, o22, t_x, t_y, t_z, wedge, chi, wavelength, tol=0.1, merge_tol=0.05, min_grain_npks=6, gnoise_std=0.0001)¶
Refine UBIs in all_pbpmap_ubis Adapted from Axel codebase
refine_points: list or Nx2 array of points in reconstruction space (ri, rj) to refine at all_pbpmap_ubis: 3x3xM array of many-valued UBIs from point-by-point map ri_col, rj_col: length-M array of ri and rj coordinates (reconstruction space) for each UBI in all_pbpmap_ubis sx_grid, sy_grid: same as before (sample space sx, sy positions) a bunch of icolf columns ystep, y0: same as before B0: B matrix of dzero_cell then a bunch of pars from the parameter file then assignment tolerances: tol is the assignment hkl tolerance for non-merged peaks merge_tol is the assignment hkl tolerance for merged peaks
- ImageD11.sinograms.point_by_point.ubi_and_ucell_to_u(ubi, ucell)¶
- ImageD11.sinograms.point_by_point.ubi_to_unitcell(ubi)¶
- ImageD11.sinograms.point_by_point.unique_with_counts(a)¶
- ImageD11.sinograms.point_by_point.weighted_lstsq_ubi_fit(ydist, gve, hkl)¶
ImageD11.sinograms.polefigures module¶
WARNING: work in progress
- ImageD11.sinograms.polefigures.main(pars, dataset)¶
ImageD11.sinograms.pread module¶
WARNING: work in progress - look at mpi and/or uncompressed data instead?
- ImageD11.sinograms.pread.create(hname, dset)¶
- ImageD11.sinograms.pread.getse(shape, chunks, nproc)¶
- ImageD11.sinograms.pread.pread(tbl, hname, dset='pks2d', nproc=0)¶
- ImageD11.sinograms.pread.read2pipe(dest, hname, dset, selection)¶
- ImageD11.sinograms.pread.readN(hname, dset, NPROC=40)¶
- ImageD11.sinograms.pread.read_segment(args)¶
- ImageD11.sinograms.pread.readpartial(args)¶
ImageD11.sinograms.properties module¶
- ImageD11.sinograms.properties.compute_storage(peaks)¶
make the cumulative sums of peaks to figure out storage space holds the row, npks, nii, nij
- ImageD11.sinograms.properties.countse(se)¶
counts the points in a block of start/end
- ImageD11.sinograms.properties.find_ND_labels(i, j, npks, verbose=1)¶
- ImageD11.sinograms.properties.get_clean_labels(labels)¶
Given the labelling in l, put clean labels in the place.
l = integer array with value = label of lowest 2d peak in this ND group.
- ImageD11.sinograms.properties.get_start_end(n, p)¶
For splitting up the scan row over processes n = number of jobs p = number of processes
All processes must do at least two rows to get the overlaps between rows. The work sharing is based on these overlaps.
rows : 0 1 2 3 4 5 etc. overlap 01 12 23 34 45
- ImageD11.sinograms.properties.goforit(ds, sparsename, options)¶
- dsfilename = ImageD11.sinograms.dataset FILE
This is how processes all get omega data
sparsename = pixels to read options
- ImageD11.sinograms.properties.main(dsfilename, sparsefile=None, pksfile=None, options={})¶
dsname = ImageD11.sinograms.dataset file sparsename = File containing sparse pixels (None = use dsname.sparsefile) pkname = File to receive output peaks (None = use dsname.pksfile)
options : dictionary of options, to override
- ImageD11.sinograms.properties.n_pk2d(s1, sI, srI, scI, frm, omega, dty)¶
- ImageD11.sinograms.properties.numbalabelNd(i, j, pkid, flip=0)¶
i, j are the pairs of overlapping peaks pkid are the current labels of the peaks
- This scans all pairs and for each pair it makes
pkid[i] = pkid[j] = min(pkid[i], pkid[j])
Run this enough times and eventually all peaks point back to the first one they overlap.
Using parallel seems dodgy to me. Might be a race condition, but it seems like the code is legal so long as only these addresses are touched?
- ImageD11.sinograms.properties.numbapkmerge(labels, pks, omega, dty, out)¶
- ImageD11.sinograms.properties.pairrow(s, row)¶
s = SparseScan
- returns SparseScan which adds a dictionary of pairs:
sourceFrame destFrame
- [ idty, iomega, idty, iomega ]nedge, array( (nedge, 3) )
(src, dest, npixels)
- ImageD11.sinograms.properties.pairscans(s1, s2, omegatol=0.051)¶
- class ImageD11.sinograms.properties.pks_table(npk=None, ipk=None, pk_props=None, rc=None, rpk=None, glabel=None, nlabel=0, use_shm=False)¶
Bases:
object- create(npk)¶
- export()¶
- find_uniq(outputfile=None, use_scipy=False)¶
find the unique labels from the rc array
- classmethod fromSHM(dct)¶
- guesschunk(ar, m=2560)¶
- classmethod load(h5name, h5group='pks2d')¶
- pk2d(omega, dty)¶
- pk2dmerge(omega, dty)¶
creates a dictionary of the 3D peaks
- save(h5name, group='pks2d', rc=False)¶
puts the array into shared memory returns the shared copy
- ImageD11.sinograms.properties.pks_table_from_scan(sparsefilename, ds, row)¶
Labels one rotation scan to a peaks table
sparsefilename = sparse pixels file dataset = ImageD11.sinograms.dataset row = index for dataset.scan[ row ]
- returns a pks_table.
You might want to call one of “save” or “pk2d” or “pk2dmerge” on the result
This is probably not threadsafe
- ImageD11.sinograms.properties.process(qin, qshm, qout, hname, dsfilename, options)¶
- Worker process.
qin : gives a block of scans from qin to label (start, end) qshm : gives us shared memory to store/return results qout : numbers of overlaps hname = sparse pixels dsfilename = load omega options (passed through)
- ImageD11.sinograms.properties.props(scan, i, algorithm='lmlabel', wtmax=None)¶
scan = sparseframe.SparseScan object i = sinogram row id : used for tagging pairs algorithm = ‘lmlabel’ | ‘cplabel’
Labels the peaks with lmlabel Assumes a regular scan for labelling frames returns ( row, properties[(s1,sI,sRow,sCol,frame),:], pairs, scan )
- ImageD11.sinograms.properties.remove_shm_from_resource_tracker()¶
Monkey-patch multiprocessing.resource_tracker so SharedMemory won’t be tracked More details at: https://bugs.python.org/issue38119
Bases:
objectSee: https://bugs.python.org/issue38119 The multiprocessing pool must stick around until the process exits
- ImageD11.sinograms.properties.testit(NPROC)¶
sanity check
- class ImageD11.sinograms.properties.tictoc¶
Bases:
object
ImageD11.sinograms.roi_iradon module¶
This code came from skimage.transform and then was modified
Added mask ROI for back projection. Optimisation for small grains in big maps. Should allow threading (one thread per tile)
Added projection shifts (sinogram shaped array of dty shifts). Should work the same way for both forward and back projection. Probably only for small offsets
- ImageD11.sinograms.roi_iradon.apply_halfmask_to_sino(sino)¶
Applies halfmask correction to sinogram
- ImageD11.sinograms.roi_iradon.correct_recon_central_zingers(recon, radius=25)¶
- ImageD11.sinograms.roi_iradon.fxyrot(colrow, angle=0, center=0, projection_shifts=None)¶
- ImageD11.sinograms.roi_iradon.iradon(radon_image, theta, output_size=None, filter_name='ramp', interpolation='linear', projection_shifts=None, mask=None, workers=1)¶
Inverse radon transform. From skimage.transform. Simplified then ruined.
- allow projection offset/shifts to be used
1D = constant offset for this projection (why?) 2D = offset versus dty for this projection
allow a mask to be used for roi reconstruction
run over several threads (each one doing a different roi)
- ImageD11.sinograms.roi_iradon.mlem(sino, theta, startvalue=1, projection_shifts=None, output_size=None, mask=None, workers=1, niter=50, divtol=1e-05)¶
# Also called “MART” for Multiplicative ART # This keeps a positivity constraint for both the data and reconstruction # # This implementation was inspired from from: # https://www.youtube.com/watch?v=IhETD4nSJec # by Andrew Reader # # ToDo : implement a mask # ToDo : check about the corners / circle=False aspects #
An “MLEM” algorithm from XRDUA was used in this paper:
“Impurity precipitation in atomized particles evidenced by nano x-ray diffraction computed tomography” Anne Bonnin; Jonathan P. Wright; Rémi Tucoulou; Hervé Palancher Appl. Phys. Lett. 105, 084103 (2014) https://doi.org/10.1063/1.4894009
This python code implements something similar based on a youtube video (https://www.youtube.com/watch?v=IhETD4nSJec)
There are lots of papers from mathematicians in the literature about MART (multiplicative ART). The conversion of latex algebra back and forth into computer code seems to be a bit of a problem for me (Jon Wright - Nov 2023).
- ImageD11.sinograms.roi_iradon.radon(image, theta, output_size=None, projection_shifts=None, mask=None, workers=1)¶
From skimage.transform. Modified to have projection shifts and roi to match the masked iradon here. And spread theta over threads.
Calculates the radon transform of an image given specified projection angles.
Parameters¶
- imagearray_like
Input image. The rotation axis will be located in the pixel with indices
(image.shape[0] // 2, image.shape[1] // 2).- thetaarray_like
Projection angles (in degrees).
output_size : shape of the output sinogram. Matches [:, len(theta)]
Returns¶
- radon_imagendarray
Radon transform (sinogram). The tomography rotation axis will lie at the pixel index
radon_image.shape[0] // 2along the 0th dimension ofradon_image.
References¶
Notes¶
Based on code of Justin K. Romberg (https://www.clear.rice.edu/elec431/projects96/DSP/bpanalysis.html)
- ImageD11.sinograms.roi_iradon.recon_cens(omega, dty, ybins, imsize, wt, y0=0.0)¶
Back project the peak centers into a map
omega, dty = peak co-ordinates in the sinogram ybins = spatial binning imsize = probably len(ybins)+1 wt = intensity, probably ones()
- ImageD11.sinograms.roi_iradon.run_iradon(sino, angles, pad=20, shift=0, workers=1, mask=None, apply_halfmask=False, mask_central_zingers=False, central_mask_radius=25, filter_name='hamming')¶
Applies an iradon to a sinogram, with an optional pad Calculates scaled-up output size from pad value Applies projection shifts of shift Optionally mask the returned reconstruction with sample_mask Optionally apply halfmask to correct artifacts with half-scans (from -ny to 0 rather than -ny/2 to +ny/2 Optionally apply a circular median filter mask to the center of the reconstruction given a radius in central_mask_radius
- ImageD11.sinograms.roi_iradon.run_mlem(sino, angles, mask=None, pad=20, shift=0, workers=1, niter=20, apply_halfmask=False, mask_central_zingers=False, central_mask_radius=25)¶
Applies an MLEM reconstruction to a sinogram, with an optional pad Calculates scaled-up output size from pad value Applies projection shifts of shift Optionally mask the returned reconstruction with sample_mask Optionally apply halfmask to correct artifacts with half-scans (from -ny to 0 rather than -ny/2 to +ny/2 Optionally apply a circular median filter mask to the center of the reconstruction given a radius in central_mask_radius
ImageD11.sinograms.sinogram module¶
- class ImageD11.sinograms.sinogram.GrainSinogram(grain_obj, dataset)¶
Bases:
objectClass to build, hold and reconstruct sinograms of grains for Scanning 3DXRD data
- build_sinogram(columns=('omega',))¶
Computes sinogram for this grain using all peaks in self.cf_for_sino
- columns = list of columns to produce sinograms of intensity*value
for example: “ds”, “eta”, “omega”, etc
- correct_halfmask()¶
Applies halfmask correction to sinogram
- correct_ring_current(is_half_scan=False, min_ring_current_frac=0.5)¶
Corrects each row of the sinogram to the ring current of the corresponding scan
- classmethod from_h5py_group(group, ds, grain)¶
Creates a GrainSinogram object from an h5py group, dataset and grain object
- get_shape_mask(method='iradon', cutoff=None)¶
Gets a boolean mask representing the grain shape from the grain reconstruction. Performs a binary threshold of the reconstruction. Uses manual threshold value if cutoff value provided. Performs global Otsu threshold if no value provided.
- mask_central_zingers(method='iradon', radius=25)¶
- prepare_peaks_from_2d(cf_2d, grain_label, hkltol=0.25)¶
Prepare peaks used for sinograms from 2D peaks data Performs greedy assignment of all 2d peaks to each grain
- prepare_peaks_from_4d(cf_4d, gord, inds, grain_label, hkltol=0.25)¶
Prepares peaks used for sinograms from 4D peaks data. cf_4d should contain grain assignments grain_label should be the label for this grain
- recon(method='iradon', workers=1, projections=None, **extra_args)¶
Performs reconstruction given reconstruction method
method = “iradon”, “mlem”, “astra” workers = threads to use - passed to the method
- projections = which projections to use for reconstruction using a subset of data (twins)
iradon( self.sino[ :, projections ], theta = self.sinoangles[ projections ], … ) effectively a sinogram mask - perhaps this should move to iradon code.
extra_args = passed to the projection function
iradon -> ImageD11.sinograms.roi_iradon.run_iradon { pad=20, shift=0, workers=1, mask=None,
apply_halfmask=False, mask_central_zingers=False, central_mask_radius=25, filter_name=’hamming’}
- mlemImageD11.sinograms.roi_iradon.run_mlem
{ mask=None, pad=20, shift=0, workers=1, niter=20, apply_halfmask=False,
mask_central_zingers=False, central_mask_radius=25 }
- astrarun_astra in this file
{ shift=0, pad=0, mask=None, niter=100, astra_method=’SIRT_CUDA’, workers=None }
- to_h5py_group(parent_group, group_name)¶
Creates a H5Py group for this GrainSinogram. parent_group is the parent H5py Group group_name is the name of the H5py Group for this name Very useful for saving lists of GrainSinograms to an H5 file
- update_lab_position_from_peaks(cf_4d, grain_label)¶
Updates translation of self.grain using peaks in assigned 4D colfile. Also updates self.recon_y0 with centre
- update_lab_position_from_recon(method='iradon')¶
Updates translation of self.grain by finding centre-of-mass of reconstruction Only really valid for very small grains. Does not update translation if no fitting result found.
- update_recon_parameters(pad=None, shift=None, mask=None, niter=None, y0=None)¶
Update some or all of the reconstruction parameters in one go
- ImageD11.sinograms.sinogram.build_slice_arrays(grainsinos, cutoff_level=0.0, method='iradon', grain_labels=None)¶
Build grain maps from individual grain reonstructions Optionally provide a different list of grain labels to label the grains
- ImageD11.sinograms.sinogram.build_slice_arrays_clean(grainsinos, method='iradon', grain_labels=None)¶
Build grain maps from individual grain reonstructions Cleans and normalises reconstructions before building slice arrays Saves cleaned and normalised reconstruction to gs.recons[method_norm] Optionally provide a different list of grain labels to label the grains
- ImageD11.sinograms.sinogram.counting_sort(ary, maxval=None, minval=None)¶
Radix sort for integer array. Single threaded. O(n) Numpy should be doing this…
- ImageD11.sinograms.sinogram.filter_normalise_recon(recon)¶
Function to filter and normalise reconstructions
- ImageD11.sinograms.sinogram.find_grain_id(spot3d_id, grain_id, spot2d_label, grain_label, order, nthreads=20)¶
Assignment grain labels into the peaks 2d array spot3d_id = the 3d spot labels that are merged and indexed grain_id = the grains assigned to the 3D merged peaks spot2d_label = the 3d label for each 2d peak grain_label => output, which grain is this peak order = the order to traverse spot2d_label sorted
- ImageD11.sinograms.sinogram.get_2d_peaks_from_4d_peaks(p2d, cf)¶
inds is an array which tells you which 2D spots each grain owns the 2D spots are sorted by spot ID inds tells you for each grain were you can find its associated 2D spots
- ImageD11.sinograms.sinogram.norm(r)¶
- ImageD11.sinograms.sinogram.palloc(shape, dtype)¶
Allocate and fill an array with zeros in parallel
- ImageD11.sinograms.sinogram.pmax(ary)¶
Find the min/max of an array in parallel
- ImageD11.sinograms.sinogram.read_h5(filename, ds, group_name='grains')¶
Read list of GrainSinogram objects from H5Py file Will also create self.grain objects from the H5Py file Because GrainSinogram objects can’t exist without corresponding grain objects
- ImageD11.sinograms.sinogram.read_slice_recon(filename)¶
- ImageD11.sinograms.sinogram.run_astra(sino, angles, shift=0, pad=0, mask=None, niter=100, astra_method='SIRT_CUDA', workers=None)¶
- ImageD11.sinograms.sinogram.save_array(grp, name, ary)¶
- ImageD11.sinograms.sinogram.write_h5(filename, list_of_sinos, overwrite_grains=False, group_name='grains')¶
Write list of GrainSinogram objects to H5Py file If overwrite_grains is True, will replace grains in group_name
- ImageD11.sinograms.sinogram.write_pbp_strain(filename, pbp_strain_slice_arrays)¶
- ImageD11.sinograms.sinogram.write_slice_recon(filename, slice_arrays)¶
ImageD11.sinograms.sinogram2crysalis module¶
WARNING: work in in progress
- class ImageD11.sinograms.sinogram2crysalis.SinoScan(dataset, num=0)¶
Bases:
LimaImageInherit limaimage to be allowed by converter
- close()¶
- ImageD11.sinograms.sinogram2crysalis.accumulate(npixels, values, indices, dest, num)¶
- class ImageD11.sinograms.sinogram2crysalis.empty¶
Bases:
object
- ImageD11.sinograms.sinogram2crysalis.integrate_sino(ds, image_mask, sinomask=None, nomega=10)¶
ds = ImageD11.sinograms.dataset that describes scandata sinomask = which frames to use nomega = number of omegasteps to combine
- ImageD11.sinograms.sinogram2crysalis.makecmdline(wvln=0.2845715990727352, xbeam=1024, ybeam=1024, omegastart=90, step=0.1, distance=140, savepath='.', run=1)¶
- ImageD11.sinograms.sinogram2crysalis.name_decorator(method)¶
- ImageD11.sinograms.sinogram2crysalis.padd(values, destination)¶
- ImageD11.sinograms.sinogram2crysalis.sum_sinogram(dsname, output_name, nomega=10, nthreads=None)¶
ImageD11.sinograms.tensor_map module¶
- class ImageD11.sinograms.tensor_map.TensorMap(maps=None, phases=None, steps=None)¶
Bases:
objectThis is a class to store a contiguous voxel-based representation of a sample. At its core is the self.maps attribute, which is a dictionary of Numpy arrays. Each Numpy array should represent a 3D voxel grid of the sample. The dimensions of the array are aligned with the laboratory reference frame in the order (Z, Y, X, …) The shape of the first three axes should therefore be (NZ, NY, NX, …) The total number of dimensions can vary E.g a phase ID map might be (1, 15, 20) but a UBI map might be (1, 15, 20, 3, 3)
- property B¶
The B matrix via the unitcell
- property U¶
The U matrix - via UBI and B, the same way as in
ImageD11.grain
- property UB¶
The UB matrix
- property UBI¶
The UBI matrix
- add_map(name, array)¶
Required to clear caches if UBI is set
- check_shape()¶
Checks that all the maps in self.maps have equal shape for their first 3 dimensions
- clear_cache()¶
- property dzero_unitcell¶
The dzero unitcell for each voxel from the reference phase for that voxel.
- property eps_crystal¶
The per-voxel Biot strain tensor in the crystal reference frame, relative to the B0 of the unitcell of the reference phase for that voxel.
Equivalent to calling
ImageD11.grain.eps_sample_matrix(dzero_cell).Will compute from
eps_sampleby rotating the tensor if we have it. If not, will compute fromUBI.
- property eps_devia¶
The per-voxel deviatoric strain tensor
- property eps_hydro¶
The per-voxel hydrostatic strain tensor (frame invariant)
- property eps_sample¶
The per-voxel Biot strain tensor in the sample frame, relative to the B0 of the unitcell of the reference phase for that voxel.
Equivalent to calling
ImageD11.grain.eps_grain_matrix(dzero_cell).Will compute from
eps_crystalby rotating the tensor if we have it. If not, will compute fromUBI.
- property euler¶
The euler angles from the U matrix, the same way as in
xfab.tools
- classmethod from_combine_phases(tensormaps)¶
Combine multiple mono-phase TensorMaps with different phases into one TensorMap. For now, this handles grain label collisions by offsetting the grain labels of subsequent tensormaps before adding
- classmethod from_grainsinos(grainsinos, method='iradon', use_gids=True, cutoff_level=0.1, steps=None)¶
Build a TensorMap object from a list of GrainSinos. method is the recon that we look for inside each grainsino use_gids will look for grainsino.grain.gid inside each grainsino to use as the label if it can’t find it, it will use the increment
- classmethod from_h5(h5file, h5group='TensorMap')¶
Load TensorMap object from an HDF5 file
- classmethod from_pbpmap(pbpmap, steps=None, phases=None)¶
Create TensorMap from a pbpmap object
- classmethod from_stack(tensormaps, zstep=1.0)¶
Stack multiple TensorMaps together along Z. The order of tensormaps will determine the Z-order, lowest-index first. All Tensor Maps in tensormaps must have the same phase mapping (i.e phase 0 is always the same unitcell)
- classmethod from_ubis(ubi_array)¶
Make simplest possible TensorMap object from a UBI array in reconstuction space (X, -Y)
- get_ipf_maps()¶
Calculate all IPF maps and add them to self.maps
- get_meta_orix_orien(phase_id=0)¶
Get a meta orix orientation for all voxels of a given phase ID
- get_stress(stiffness_tensor, phase_id)¶
Convert Biot strain tensor (ImageD11 coordinate system) to Biot stress tensor (ImageD11 coordinate system). Does this for a given phase_id. Needs Voigt-format IEEE coordinate system stiffness tensor.
- Parameters:
stiffness_tensor (np.ndarray) – 6x6 stiffness tensor in GPa, Voigt notation, IEEE 1976 coordinate system
phase_id (int) – ID of phase you want to compute for (makes phase mask)
- keys()¶
allows you to use dictionary syntax
- static map_index_to_recon(mj, mk, yshape)¶
From a 3D array index (mi, mj, mk) and the Y shape of the map, determine the corresponding position in reconstruction space
- static map_order_to_recon_order(map_arr, z_layer=0)¶
Transform a 2D slice of a TensorMap to reconstruction space. The opposite of recon_order_to_map_order
- property mt¶
The metric tensor
- plot(map_name, z_layer=0)¶
- static recon_index_to_map(ri, rj, yshape)¶
From a 2D reconstruction space index (ri, rj) and the Y shape of the map, determine the corresponding position in TensorMap space
- static recon_order_to_map_order(recon_arr)¶
Transform a 2D array from reconstruction space (first axis X, second axis is -Y) to TensorMap space (Z, Y ,X) The input array must have the first two dimensions (X, -Y) as is the case for reconstructed grain shapes from sinogram or PBP methods
- property shape¶
The shape of the map (NZ, NY, NX)
- property sig_crystal¶
The per-voxel Biot stress tensor in the crystal reference frame
- property sig_devia¶
The per-voxel deviatoric stress tensor
- property sig_hydro¶
The per-voxel hydrostatic stress tensor (frame invariant)
- property sig_mises¶
The per-voxel von-Mises stress scalar (frame invariant)
- property sig_sample¶
The per-voxel Biot stress tensor in the sample reference frame
- to_ctf_mtex(ctf_path, z_index=0)¶
Export a Z slice to a CTF file for MTEX processing. The resulting ctf file can be loaded in MTEX with the command: ebsd = EBSD.load(ctf_path) Note that no Euler or spatial conversions are needed
- to_h5(h5file, h5group='TensorMap')¶
Write all maps to an HDF5 file (h5file) with a parent group h5group. Creates h5group if doesn’t already exist
- to_paraview(h5name, h5group='TensorMap')¶
Exports to H5, then writes an XDMF file that lets you read the data with ParaView
- to_pbpmap(z_layer=0, default_npks=20, default_nuniq=20)¶
Get a PBPMap object from this TensorMap object (good for refining strains)
- property unitcell¶
The unitcell - from metric tensor
Module contents¶
Instructions:
# create the dataset file
python3 -m ImageD11.sinograms.dataset /data/visitor/ma5415/id11/20221027 /data/visitor/ma5415/id11/20221027/analysis/test NSCOPE_SiMo1000_6 DT600nm_Z50 dstest_NSCOPE_SiMo1000_6_DT600nm_Z50.h5
# do some segmentation python3 -m ImageD11.sinograms.lima_segmenter setup dataset.h5 sbatch /data/visitor/ma5415/id11/20221027/analysis/test/NSCOPE_SiMo1000_6/NSCOPE_SiMo1000_6_DT600nm_Z50/slurm/lima_segmenter_slurm.sh
# next step(s) label the pixels (save that or not?)
cost = np.cumsum( dataset.nnz )
- save the peaks from each frame?
s_raw f_raw S_I float32, float32, float32 == 4 * 3 = 12 bytes (number of pixels?) sc fc 1 pixel is (uint16, uint16, uint16) = (2 * 3) = 6 bytes
determine dataset.npks_per_frame # keeping all? Keeping Some?
make the graph of all the p