Reference
LiberTEM-blobfinder is structured into three parts:
A “base” package with numerics functions and utilities.
A “common” package providing user-facing funtcions to run Blobfinder without any dependency on LiberTEM itself.
A “udf” package with classes and functions to use this functionality with full LiberTEM integration.
Basic numerics functions
- libertem_blobfinder.base.correlation.allocate_crop_bufs(crop_size, n_peaks, dtype, limit=524288, xp=<module 'numpy' from '/home/runner/work/LiberTEM-blobfinder/LiberTEM-blobfinder/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>)[source]
Allocate buffer for stack of cropped peaks
The size is optimized to fit within
limit
. An aligned buffer for the FFT back-end is created if possible.- Parameters
crop_size (int) – The cropped parts will have size (2 * crop-size, 2 * crop_size)
n_peaks (int) – Number of peaks
dtype (numpy.dtype) – dtype of the buffer
limit (int, optional) – Upper limit, default 1/2 MB to be L3 cache friendly
- Returns
crop_bufs – Shape (n, 2*crop_size, 2*crop_size)
- Return type
np.ndarray
- libertem_blobfinder.base.correlation.do_correlations(template, crop_parts, with_specs: bool = False)[source]
Calculate the correlation of the pre-calculated template with a stack of cropped peaks using fast correlation.
- Parameters
template (numpy.ndarray) – Real Fourier transform of the correlation pattern. The source pattern should have the same size as the cropped parts. Please note that the real Fourier transform (fft.rfft2) of the source pattern has a different shape!
crop_parts (numpy.ndarray) – Stack of peaks cropped from the frame.
with_specs (bool, optional) – Whether to return the FFT correlation maps before inversion, used for FFT upsampling. By default, False.
- Returns
corrs (numpy.ndarray) – Correlation of the correlation pattern and the peaks.
corrspecs (numpy.ndarray) – The FFT correlation maps before inversion, returned only if with_specs is True.
- libertem_blobfinder.base.correlation.get_buf_count(crop_size, n_peaks, dtype, limit=524288)[source]
Calculate the optimal number of peaks in a stack to fit within the limit.
- Parameters
crop_size (int) – The cropped parts will have size (2 * crop-size, 2 * crop_size)
n_peaks (int) – Number of peaks
dtype (numpy.dtype) – dtype of the data for size calculation
limit (int, optional) – Upper limit, default 1/2 MB to be L3 cache friendly
- Return type
- libertem_blobfinder.base.correlation.peak_elevation(center, corrmap, height, r_min=1.5, r_max=inf)[source]
Return the slope of the tightest cone around
center
with heightheight
that touchescorrmap
betweenr_min
andr_max
.The correlation of two disks – mask and perfect diffraction spot – has the shape of a cone. The function’s return value correlates with the quality of a correlation. Higher slope means a strong peak and no side maxima, while weak signal or side maxima lead to a flatter slope.
- Parameters
center (numpy.ndarray) – (y, x) coordinates of the center within the
corrmap
corrmap (numpy.ndarray) – Correlation map
height (float) – The height is provided as a parameter since center can be float values from refinement and the height value is conveniently available from the calling function.
r_min (float, optional) – Masks out a small local plateau around the peak that would distort and dominate the calculation.
r_max (float, optional) – Mask out neighboring peaks if a large area with several legitimate peaks is correlated.
- Returns
elevation – Elevation of the tightest cone that fits the correlation map within the given parameter range.
- Return type
- libertem_blobfinder.base.correlation.process_frame_fast(template, crop_size, frame, peaks, out_centers, out_refineds, out_heights, out_elevations, crop_bufs, upsample: ~typing.Union[bool, int] = False, crop_function=CPUDispatcher(<function crop_disks_from_frame>))[source]
Find the parameters of peaks in a diffraction pattern by correlation with a template
This function is designed to be used in an optimized pipeline with a pre-calculated Fourier transform of the match pattern and optional pre-allocated buffers. It is the engine of the
libertem_blobfinder.udf.correlation.FastCorrelationUDF
for stand-alone use independent of LiberTEM.libertem_blobfinder.common.correlation.process_frames_fast()
offers a more convenient interface for batch processing.- Parameters
template (numpy.ndarray) – Real Fourier transform of the correlation pattern. The source pattern shape should match the shape[1:] of crop_bufs. Please note that the real Fourier transform (fft.rfft2) of the source pattern has a different shape!
crop_size (int) – Half the size of the correlation pattern. Given as a parameter since real Fourier transform changes the size.
frame (np.ndarray) – Frame data. Currently, only Real values are supported.
peaks (np.ndarray) – List of peaks of shape (n_peaks, 2)
out_centers (np.ndarray) – Output buffer for center positions of shape (n_peaks, 2) and integer dtype.
out_refineds (np.ndarray) – Output buffer for refined center positions of shape (n_peaks, 2) and float dtype.
out_heights (np.ndarray) – Output buffer for peak height in log scaled frame. Shape (n_peaks, ) and float dtype.
out_elevations (np.ndarray) – Output buffer for peak elevation in log scaled frame. Shape (n_peaks, ) and float dtype.
crop_bufs (np.ndarray) – Temporary buffers for cropping. Shape (n, 2 * crop_size, 2 * crop_size) and float dtype. n doesn’t have to match the number of peaks. Instead, it should be chosen for good L3 cache efficiency.
allocate_crop_bufs()
can be used to allocate this buffer.upsample (Union[bool, int], optional) – Whether to use upsampling DFT for refinement. False to deactivate (default) or a positive integer >1 to upsample by this factor when refining the correlation peak positions. Upsample True will choose a sensible upsampling factor.
- Returns
The values are placed in the provided output buffers.
- Return type
None
Example
>>> from libertem_blobfinder.common.patterns import RadialGradient >>> from libertem_blobfinder.base.correlation import allocate_crop_bufs >>> from libertem_blobfinder.base.utils import cbed_frame >>> >>> frames, indices, peaks = cbed_frame(radius=4) >>> pattern = RadialGradient(radius=4) >>> crop_size = pattern.get_crop_size() >>> template = pattern.get_template(sig_shape=(2 * crop_size, 2 * crop_size)) >>> >>> centers = np.zeros((len(frames), len(peaks), 2), dtype=np.uint16) >>> refineds = np.zeros((len(frames), len(peaks), 2), dtype=np.float32) >>> heights = np.zeros((len(frames), len(peaks)), dtype=np.float32) >>> elevations = np.zeros((len(frames), len(peaks)), dtype=np.float32) >>> >>> crop_bufs = allocate_crop_bufs(crop_size, len(peaks), frames.dtype) >>> >>> for i, f in enumerate(frames): ... process_frame_fast( ... template=template, crop_size=crop_size, ... frame=f, peaks=peaks.astype(np.int32), ... out_centers=centers[i], out_refineds=refineds[i], ... out_heights=heights[i], out_elevations=elevations[i], ... crop_bufs=crop_bufs ... ) >>> assert np.allclose(refineds[0], peaks, atol=0.1)
- libertem_blobfinder.base.correlation.process_frame_full(template, crop_size, frame, peaks, out_centers=None, out_refineds=None, out_heights=None, out_elevations=None, frame_buf=None, buf_count=None, upsample: ~typing.Union[bool, int] = False, crop_function=CPUDispatcher(<function crop_disks_from_frame>))[source]
Find the parameters of peaks in a diffraction pattern by correlation with a template
This function is designed to be used in an optimized pipeline with a pre-calculated Fourier transform of the match pattern and optional pre-allocated buffers. It is the engine of the
libertem_blobfinder.udf.correlation.FullFrameCorrelationUDF
for stand-alone use independent of LiberTEM.libertem_blobfinder.common.correlation.process_frames_full()
offers a more convenient interface for batch processing.- Parameters
template (numpy.ndarray) – Real Fourier transform of the correlation pattern. The source pattern shape should match the argument crop_size, either the supplied shape or (2 * crop_size, 2 * crop_size) if default. Please note that the real Fourier transform (fft.rfft2) of the source pattern has a different shape!
crop_size (int) – Half the size of the correlation pattern. Given as a parameter since real Fourier transform changes the size.
frame (np.ndarray) – Frame data. Currently, only real values are supported.
peaks (np.ndarray) – List of peaks of shape (n_peaks, 2)
out_centers (np.ndarray, optional) – Output buffer for center positions of shape (n_peaks, 2) and integer dtype. Will be allocated if needed.
out_refineds (np.ndarray, optional) – Output buffer for refined center positions of shape (n_peaks, 2) and float dtype. Will be allocated if needed.
out_heights (np.ndarray, optional) – Output buffer for peak height in log scaled frame. Shape (n_peaks, ) and float dtype. Will be allocated if needed.
out_elevations (np.ndarray, optional) – Output buffer for peak elevation in log scaled frame. Shape (n_peaks, ) and float dtype. Will be allocated if needed.
frame_buf (np.ndarray) – Temporary buffer for the FFT back-end. Shape of a frame and float dtype.
libertem_blobfinder.base.correlation.zero()
can be used.buf_count (int) – Number of peaks to process per outer loop iteration. This allows optimization of L3 cache efficiency.
upsample (Union[bool, int], optional) – Whether to use upsampling DFT for refinement. False to deactivate (default) or a positive integer >1 to upsample by this factor when refining the correlation peak positions. Upsample True will choose a sensible upsampling factor.
- Returns
The values are placed in the provided output buffers.
- Return type
None
Example
>>> from libertem_blobfinder.common.patterns import RadialGradient >>> from libertem_blobfinder.base.correlation import get_buf_count, zeros >>> from libertem_blobfinder.base.utils import cbed_frame >>> >>> frames, indices, peaks = cbed_frame() >>> pattern = RadialGradient(radius=4) >>> crop_size = pattern.get_crop_size() >>> template = pattern.get_template(sig_shape=frames[0].shape) >>> >>> centers = np.zeros((len(frames), len(peaks), 2), dtype=np.uint16) >>> refineds = np.zeros((len(frames), len(peaks), 2), dtype=np.float32) >>> heights = np.zeros((len(frames), len(peaks)), dtype=np.float32) >>> elevations = np.zeros((len(frames), len(peaks)), dtype=np.float32) >>> >>> frame_buf = zeros(frames[0].shape, dtype=np.float32) >>> buf_count = get_buf_count(crop_size, len(peaks), frame_buf.dtype) >>> >>> for i, f in enumerate(frames): ... process_frame_full( ... template=template, crop_size=crop_size, ... frame=f, peaks=peaks.astype(np.int32), ... out_centers=centers[i], out_refineds=refineds[i], ... out_heights=heights[i], out_elevations=elevations[i], ... frame_buf=frame_buf, buf_count=buf_count ... ) >>> assert np.allclose(refineds[0], peaks, atol=0.1)
- libertem_blobfinder.base.masks.balance(template)[source]
Accept a template with both positive and negative values and scale the negative part in such a way that the sum is zero.
This is useful to generate masks that return zero when applied to a uniform background or linear gradient.
- libertem_blobfinder.base.masks.bounding_radius(centerX, centerY, imageSizeX, imageSizeY)[source]
Calculate a radius around centerX, centerY that covers the whole frame
- libertem_blobfinder.base.masks.circular(centerX, centerY, imageSizeX, imageSizeY, radius, antialiased=False)[source]
Make a circular mask as a 2D array
- Parameters
- Returns
Array with the shape (imageSizeX, imageSizeY) with the mask.
- Return type
Numpy 2D Array
- libertem_blobfinder.base.masks.polar_map(centerX, centerY, imageSizeX, imageSizeY, stretchY=1.0, angle=0.0)[source]
Return a map of radius and angle.
The optional parameters stretchY and angle allow to stretch and rotate the coordinate system into an elliptical form. This is useful to generate modified input data for functions that generate a template as a function of radius and angle.
- Parameters
centerX (float) – Center of the coordinate system in pixel coordinates
centerY (float) – Center of the coordinate system in pixel coordinates
imageSizeX (int) – Size of the map to generate in px
imageSizeY (int) – Size of the map to generate in px
stretchY (float, optional) – Stretch the radius elliptically by amount
stretchY
in directionangle
in radians.angle = 0
means in Y direction.angle (float, optional) – Stretch the radius elliptically by amount
stretchY
in directionangle
in radians.angle = 0
means in Y direction.
- Returns
Map of radius and angle of shape
(imageSizeY, imageSizeX)
- Return type
Tuple[numpy.ndarray, numpy.ndarray]
- libertem_blobfinder.base.masks.radial_bins(centerX, centerY, imageSizeX, imageSizeY, radius=None, radius_inner=0, n_bins=None, normalize=False, use_sparse=None, dtype=None)[source]
Generate antialiased rings
- libertem_blobfinder.base.masks.radial_gradient(centerX, centerY, imageSizeX, imageSizeY, radius, antialiased=False)[source]
Generate a linear radial gradient from 0 to 1 within radius
- libertem_blobfinder.base.masks.radial_gradient_background_subtraction(r, r0, r_outer, delta=1)[source]
Generate a template with a linear radial gradient from 0 to 1 inside r0, linear transition region for antialiasing between [r0 - delta/2, r0 + delta/2[, and a negative ring with value -1 in [r0 + delta/2, r_outer].
The function accepts the radius for each pixel as a parameter so that a distorted version can be generated with the stretchY and angle parameters of
polar_map()
.- Parameters
r (numpy.ndarray) – Map of radius for each pixel, typically 2D. This allows to work in distorted coordinate systems by assigning arbitrary radius values to each pixel.
polar_map()
can generate elliptical maps as an example.r0 (float) – Inner radius to fill with a linear gradient in units of r
r_outer (float) – Outer radius of ring from r0 to fill with -1 in units of r
delta (float, optional) – Width of transition region between inner and outer in units of r with linear gradient for antialiasing or smoothening. Defaults to 1.
- Returns
NumPy numpy.ndarray with the same shape and type of r with mask values assigned as described in the description.
- Return type
- libertem_blobfinder.base.masks.rectangular(X, Y, Width, Height, imageSizeX, imageSizeY)[source]
Make a rectangular mask as a 2D array of bool. :param X: Centre point of the mask. :type X: Corner coordinates :param Y: Centre point of the mask. :type Y: Corner coordinates :param imageSizeX: Size of the image to be masked. :type imageSizeX: int :param imageSizeY: Size of the image to be masked. :type imageSizeY: int :param Width: :type Width: Width and Height of the rectangle :param Height: :type Height: Width and Height of the rectangle
- Returns
Array with the shape (imageSizeX, imageSizeY) with the mask.
- Return type
Numpy 2D Array
Common classes and functions
These functions and classes provide Blobfinder’s funtcionality, but can be used without the LiberTEM core infrastructure.
- class libertem_blobfinder.common.patterns.BackgroundSubtraction(radius, search=None, radius_outer=None)[source]
Solid circular disk surrounded with a balancing negative area
This pattern rejects background and avoids false positives at positions between peaks
- __init__(radius, search=None, radius_outer=None)[source]
- Parameters
radius (float) – Radius of the circular pattern in px
search (float, optional) – Range from the center point in px to include in the correlation.
max(2*radius, radius_outer)
by default. Defining the size of the square correlation pattern.radius_outer (float, optional) – Radius of the negative region in px. 1.5x radius by default.
- class libertem_blobfinder.common.patterns.Circular(radius, search=None)[source]
Circular pattern with radius
radius
.This pattern is useful for constructing feature vectors using
feature_vector()
.New in version 0.3.0.
- class libertem_blobfinder.common.patterns.MatchPattern(search)[source]
Abstract base class for correlation patterns.
This class provides an API to provide a template for fast correlation-based peak finding.
- class libertem_blobfinder.common.patterns.RadialGradient(radius, search=None)[source]
Radial gradient from zero in the center to one at
radius
.This pattern rejects the influence of internal intensity variations of the CBED disk.
- class libertem_blobfinder.common.patterns.RadialGradientBackgroundSubtraction(radius, search=None, radius_outer=None, delta=1, radial_map=None)[source]
Combination of radial gradient with background subtraction
- __init__(radius, search=None, radius_outer=None, delta=1, radial_map=None)[source]
See
radial_gradient_background_subtraction()
for details.- Parameters
radius (float) – Radius of the circular pattern in px
search (float, optional) – Range from the center point in px to include in the correlation.
max(2*radius, radius_outer)
by default Defining the size of the square correlation pattern.radius_outer (float, optional) – Radius of the negative region in px. 1.5x radius by default.
delta (float, optional) – Width of the transition region between positive and negative in px
radial_map (numpy.ndarray, optional) – Radius value of each pixel in px. This can be used to distort the shape as needed or work in physical coordinates instead of pixels. A suitable map can be generated with
libertem_blobfinder.base.masks.polar_map()
.
Example
>>> import matplotlib.pyplot as plt
>>> (radius, phi) = libertem_blobfinder.base.masks.polar_map( ... centerX=64, centerY=64, ... imageSizeX=128, imageSizeY=128, ... stretchY=2., angle=np.pi/4 ... )
>>> template = RadialGradientBackgroundSubtraction( ... radius=30, radial_map=radius)
>>> # This shows an elliptical template that is stretched >>> # along the 45 ° bottom-left top-right diagonal >>> plt.imshow(template.get_mask(sig_shape=(128, 128))) <matplotlib.image.AxesImage object at ...> >>> plt.show()
- class libertem_blobfinder.common.patterns.UserTemplate(template: ndarray, search=None)[source]
User-defined template
- __init__(template: ndarray, search=None)[source]
- Parameters
template (numpy.ndarray) – Correlation template as 2D numpy.ndarray
search (float, optional) – Range from the center point in px to include in the correlation. Half diagonal of the template by default. Defining the size of the square correlation pattern.
- libertem_blobfinder.common.patterns.feature_vector(imageSizeX, imageSizeY, peaks, match_pattern: MatchPattern)[source]
This function generates a sparse mask stack to extract a feature vector.
A match template based on the parameters in
parameters
is placed at each peak position in an individual mask layer. This mask stack can then be used inlibertem.udf.masks.ApplyMasksUDF
to generate a feature vector for each frame.Summing up the mask stack along the first axis generates a mask that can be used for virtual darkfield imaging of all peaks together.
- Parameters
imageSizeX (int) – Frame size in px
imageSizeY (int) – Frame size in px
peaks (numpy.ndarray) – Peak positions in px as numpy.ndarray of shape (n, 2) with integer type
match_pattern (MatchPattern) – Instance of
MatchPattern
- libertem_blobfinder.common.correlation.get_correlation(sum_result, match_pattern: MatchPattern)[source]
Calculate the correlation between
sum_result
andmatch_pattern
.New in version 0.4.0.dev0.
- Parameters
sum_result (numpy.ndarray) – 2D result frame as correlation input
match_pattern (MatchPattern) – Instance of
MatchPattern
to correlatesum_result
with
- libertem_blobfinder.common.correlation.get_peaks(sum_result, match_pattern: MatchPattern, num_peaks)[source]
Find peaks of the correlation between
sum_result
andmatch_pattern
.The result can then be used as input to
full_match()
to extract grid parameters,run_fastcorrelation()
to find the position in each frame or to construct a mask to extract feature vectors withfeature_vector()
.- Parameters
sum_result (numpy.ndarray) – 2D result frame as correlation input
match_pattern (MatchPattern) – Instance of
MatchPattern
to correlatesum_result
withnum_peaks (int) – Number of peaks to find
Example
>>> from libertem_blobfinder.base.utils import cbed_frame >>> >>> frame, _, _ = cbed_frame(radius=4) >>> pattern = libertem_blobfinder.common.patterns.RadialGradient(radius=4) >>> peaks = get_peaks(frame[0], pattern, 7) >>> print(peaks) [[64 64] [64 80] [80 80] [80 64] [48 80] [48 64] [64 96]]
- libertem_blobfinder.common.correlation.process_frames_fast(pattern: MatchPattern, frames, peaks, upsample: Union[bool, int] = False)[source]
Find the parameters of peaks in a diffraction pattern by correlation with a match pattern.
This method crops regions of interest around the peaks from the frames before correlation, which is usually fastest for a moderate amount of moderately sized peaks per frame.
Note
FastCorrelationUDF
is a parallelized, distributed version for large-scale data.- Parameters
pattern (MatchPattern) – Pattern to correlate with.
frames (np.ndarray) – Frame data. Currently, only Real values are supported.
peaks (np.ndarray) – List of peaks of shape (n_peaks, 2)
upsample (Union[bool, int], optional) – Use DFT upsampling for the refinement step, by default False. Supplying True will choose a reasonable default upsampling factor, while any positive integer > 1 will upsample the correlation peak by this factor. DFT upsampling can provide more accurate center values, especially when peak shifts are small, but does require more computation time.
- Returns
centers (np.ndarray) – Center positions of shape (n_peaks, 2) and integer dtype.
refineds (np.ndarray) – Refined center positions of shape (n_peaks, 2) and float dtype.
heights (np.ndarray) – Peak height in log scaled frame. Shape (n_peaks, ) and float dtype.
elevations (np.ndarray) – Peak elevation in log scaled frame. Shape (n_peaks, ) and float dtype
Example
>>> from libertem_blobfinder.base.utils import cbed_frame >>> >>> frames, indices, peaks = cbed_frame() >>> pattern = libertem_blobfinder.common.patterns.RadialGradient(radius=4) >>> (centers, refineds, heights, elevations) = process_frames_fast( ... pattern=pattern, ... frames=frames, ... peaks=peaks.astype(np.int32), ... ) >>> assert np.allclose(refineds[0], peaks, atol=0.1)
- libertem_blobfinder.common.correlation.process_frames_full(pattern: MatchPattern, frames, peaks, upsample: Union[bool, int] = False)[source]
Find the parameters of peaks in a diffraction pattern by correlation with a match pattern.
This method crops regions of interest around the peaks after correlation, which can be faster for many peaks on smaller frames.
Note
FullFrameCorrelationUDF
is a parallelized, distributed version for large-scale data.- Parameters
pattern (MatchPattern) – Pattern to correlate with.
frame (np.ndarray) – Frame data. Currently, only real values are supported.
peaks (np.ndarray) – List of peaks of shape (n_peaks, 2)
upsample (Union[bool, int], optional) – Use DFT upsampling for the refinement step, by default False. Supplying True will choose a reasonable default upsampling factor, while any positive integer > 1 will upsample the correlation peak by this factor. DFT upsampling can provide more accurate center values, especially when peak shifts are small, but does require more computation time.
- Returns
centers (np.ndarray) – Center positions of shape (n_peaks, 2) and integer dtype.
refineds (np.ndarray) – Refined center positions of shape (n_peaks, 2) and float dtype.
heights (np.ndarray) – Peak height in log scaled frame. Shape (n_peaks, ) and float dtype.
elevations (np.ndarray) – Peak elevation in log scaled frame. Shape (n_peaks, ) and float dtype
Example
>>> from libertem_blobfinder.base.utils import cbed_frame >>> >>> frames, indices, peaks = cbed_frame(radius=4) >>> pattern = libertem_blobfinder.common.patterns.RadialGradient(radius=4) >>> (centers, refineds, heights, elevations) = process_frames_full( ... pattern=pattern, ... frames=frames, ... peaks=peaks.astype(np.int32) ... ) >>> assert np.allclose(refineds[0], peaks, atol=0.1)
Matching
These modules contain classes and helper functions that extract and manipulate lattices from correlation results.
Gridmatching
Code to match parallelogram grids to point clouds. This can connect diffraction spots to a lattice.
- class libertem_blobfinder.common.gridmatching.CorrelationResult(centers, refineds=None, peak_values=None, peak_elevations=None)[source]
Bases:
object
Container class for the result of correlation-based refinement of peak positions within a frame.
- class libertem_blobfinder.common.gridmatching.Match(correlation_result: CorrelationResult, selector, zero, a, b, indices)[source]
Bases:
PointSelection
Class that represents a lattice match to a subset of a correlation result
The attributes are not guaranteed to be correct or sensible for the given lattice. The methods
weighted_optimize()
andoptimize()
calculate a derivedMatch
with a best fit ofzero
,a
andb
based on the points and the indices.- zero
Declared zero point (y, x) of the lattice
- Type
- a
Declared “a” vector (y, x) of the lattice
- Type
- b
Declared “b” vector (y, x) of the lattice
- Type
- indices
List of indices (i, j) that are declared to express the matched points as linear combination of vectors
a
andb
with reference tozero
. The indices can be integers or floats, and they can be precise or approximate, depending on the matching method.- Type
- calc_coords(indices=None, drop_zero=False, frame_shape=None, r=0)[source]
Shorthand to calculate peak coordinates.
- Parameters
indices (numpy.ndarray) – Indices to calculate coordinates for. Both an array of (y, x) pairs and the output of np.mgrid are supported.
drop_zero (bool) – Drop the zero order peak. This is important for virtual darkfield imaging.
frame_shape (Tuple[int, int]) – If set, the peaks are filtered with
within_frame()
r (float) – Radius for
within_frame()
- Returns
A list of (y, x) coordinate pairs for peaks
- Return type
- Raises
ValueError – If the shape of
indices
is not as expected.
- property calculated_refineds
Calculated peak positions based on lattice parameters and indices.
- Type
- property error
Weighted average distance between calculated and given peak position. numpy.float(‘inf’) if match of length zero.
- Type
- classmethod invalid(correlation_result)[source]
- Match
A
Match
instance with empty selector and all-‘nan’ attributes
- optimize()[source]
Least square optimization of
zero
,a
andb
Optimization to match the given points and indices.
- class libertem_blobfinder.common.gridmatching.Matcher(tolerance=3, min_weight=0.1, min_match=3)[source]
Bases:
object
The main job of the Matcher object is managing the matching parameters and making them available for the various matching routines.
- Parameters
- affinematch(centers, indices, refineds=None, peak_values=None, peak_elevations=None)[source]
This function creates a Match object from correlation_result and indices for all points. The indices can be non-integer and relative to any base vectors zero, a, b, including virtual ones like zero=(0, 0), a=(1, 0), b=(0, 1).
Refined values for zero, a and b that match the correlated peaks are then derived.
This match method is very fast, can be robust against a distorted field of view and works without determining a lattice. It matches the full CorrelationResult and does not reject random points or other outliers.
It is mathematically equivalent to calculating an affine transformation, as inspired by Giulio Guzzinati https://arxiv.org/abs/1902.06979
- Parameters
centers (numpy.ndarray) – numpy.ndarray of shape (n, 2) with integer centers (y, x) of peaks
refineds (numpy.ndarray) – numpy.ndarray of shape (n, 2) with float centers (y, x) of peaks (subpixel refinement)
peak_values (numpy.ndarray) – numpy.ndarray of shape (n,) with float maxima of correlation map of peaks
peak_values – numpy.ndarray of shape (n,) with float elevation of correlation map of peaks. See
libertem_blobfinder.base.correlation.peak_elevation()
for details.indices (numpy.ndarray) – The indices assigned to each point of the CorrelationResult.
- Returns
- Return type
- fastmatch(centers, zero, a, b, refineds=None, peak_values=None, peak_elevations=None)[source]
This function creates a Match object from correlation_result and approximates for zero point and lattice vectors a and b. This function is much, much faster than the full match. It works well to match a large number of point sets that share the same lattice vectors, for example from a larger grain or monocrystalline material. It rejects random points or other lattices in the CorrelationResult, provided they are not on near-integer positions of zero, a, b.
- Parameters
centers (numpy.ndarray) – numpy.ndarray of shape (n, 2) with integer centers (y, x) of peaks
refineds (numpy.ndarray) – numpy.ndarray of shape (n, 2) with float centers (y, x) of peaks (subpixel refinement)
peak_values (numpy.ndarray) – numpy.ndarray of shape (n,) with float maxima of correlation map of peaks
peak_elevations (numpy.ndarray) – numpy.ndarray of shape (n,) with float elevation of correlation map of peaks. See
libertem_blobfinder.base.correlation.peak_elevation()
for details.zero (numpy.ndarray) – The near approximate zero point as numpy array (y, x).
a (numpy.ndarray) – The near approximate vectors a, b to match the grid as numpy arrays (y, x).
b (numpy.ndarray) – The near approximate vectors a, b to match the grid as numpy arrays (y, x).
- Returns
Match
object with the optimized matching result.- Return type
- class libertem_blobfinder.common.gridmatching.PointSelection(correlation_result: CorrelationResult, selector=None)[source]
Bases:
object
Class that represents a subset of a correlation result.
- selector
Boolean mask for all points in the correlation result,
True
indicating selected points.- Type
- libertem_blobfinder.common.gridmatching.get_indices(points, zero, a, b)[source]
Find indices to express each point as sum of lattice vectors from zero point
This could solve for arbitrarily many points, i.e. frame stacks instead of frame by frame With that the algorithm could actually match entire frame collections at once.
- libertem_blobfinder.common.gridmatching.get_transformation(ref, peaks, center=None, weighs=None)[source]
Inspired by Giulio Guzzinati https://arxiv.org/abs/1902.06979
Fullmatch
Code to extract parallelogram grids from point clouds. This can guess lattices from a set of diffraction spots using clustering.
- class libertem_blobfinder.common.fullmatch.FullMatcher(tolerance=3, min_weight=0.1, min_match=3, min_angle=0.3141592653589793, min_points=10, min_delta=0, max_delta=inf, min_candidates=3, max_candidates=7, clusterer=None, min_cluster_size_fraction=4, min_samples_fraction=20)[source]
Bases:
Matcher
Extension of
Matcher
will full matchingInclude the ability to guess grid parameters from a point cloud. This is separated from the other code since it currently only works with
HDBSCAN
, which can be problematic to install on some platforms. For that reason it is an optional dependency.- Parameters
tolerance (float) – Position tolerance in px for peaks to be considered matches
min_weight (float) – Minimum peak elevation of a peak to be considered for matching
min_match (int) – Minimum number of matching peaks to be considered a match.
min_angle (float) – Minimum angle in radians between two vectors to be considered candidates
min_points (int) – Minimum points to try clustering matching. Otherwise match directly
min_delta (float) – Minimum length of a potential grid vector
max_delta (float) – Maximum length of a potential grid vector
min_candidates (int) – Minimum number of candidates to consider clustering matching successful. If not enough are found, the algorithm uses a brute-force search with all pairwise vectors between points
max_candidates (int) – Maximum number of candidates to return from clustering matching
clusterer – Instance of sklearn.cluster compatible clusterer. Default is
HDBSCAN
.min_cluster_size_fraction (float) – Tuning parameter for clustering matching with
HDBSCAN
. Larger values allow smaller or fuzzier clusters. This is used to adapt themin_cluster_size
parameter ofHDBSCAN
dynamically to the number of points to be matched. Set this toNone
to disable dynamic adjustment ofmin_cluster_size
. If you like to setmin_cluster_size
to a constant value, you can set this toNone
and additionally set theclusterer
parameter with your own clusterer object to have direct control over all parameters.min_samples_fraction (float) – Tuning parameter for clustering matching with
HDBSCAN
. Larger values allow smaller or fuzzier clusters. This is used to adapt themin_samples
parameter ofHDBSCAN
dynamically to the number of points to be matched. Set this toNone
to disable dynamic adjustment ofmin_samples
. If you like to setmin_samples
to a constant value, you can set this toNone
and additionally set theclusterer
parameter with your own clusterer object to have direct control over all parameters.
- full_match(centers, zero=None, cand=None, refineds=None, peak_values=None, peak_elevations=None)[source]
This function extracts a list of Match objects as well two PointSelection objects for unmatched and weak points from correlation_result and zero point. The zero point is included in each of the matches because it is shared between all grids.
- Parameters
centers (numpy.ndarray) – numpy.ndarray of shape (n, 2) with integer centers (y, x) of peaks. This would typically be extracted with
libertem_blobfinder.common.correlation.get_peaks()
zero (numpy.ndarray) – Zero point as numpy array (y, x).
cand (list or numpy.ndarray) – Optional list of candidate vectors (y, x) to use in a first matching round before guessing.
refineds (numpy.ndarray) – numpy.ndarray of shape (n, 2) with float centers (y, x) of peaks (subpixel refinement)
peak_values (numpy.ndarray) – numpy.ndarray of shape (n,) with float maxima of correlation map of peaks
peak_elevations (numpy.ndarray) – numpy.ndarray of shape (n,) with float elevation of correlation map of peaks. See
libertem_blobfinder.base.correlation.peak_elevation()
for details.
- Returns
matches: list of
Match
instances,unmatched: instance of
PointSelection
,weak: instance of
PointSelection
- Return type
Tuple[List[libertem_blobfinder.common.gridmatching.Match, …], libertem_blobfinder.common.gridmatching.PointSelection, libertem_blobfinder.common.gridmatching.PointSelection]
Example
>>> peaks = np.array([ ... # First peak is zero if not specified otherwise ... # Base lattice vectors (32, 0) and (0, 32) ... (64, 64), ... (32, 32), (32, 64), (32, 96), ... (64, 32), (64, 96), ... (96, 32), (96, 64), (96, 96), ... ]) >>> matcher = FullMatcher() >>> (matches, unmatched, weak) = matcher.full_match(peaks) >>> m = matches[0] >>> assert np.allclose(m.zero, (64, 64)) >>> assert np.allclose(m.a, (32, 0)) >>> assert np.allclose(m.b, (0, 32))
- make_polar_vectors(coords)[source]
Calculate all unique pairwise connecting polar vectors between points in coords.
The pairwise connecting vectors are converted to polar coordinates and filtered with parameters
min_delta
andmax_delta
to avoid calculating for unwanted higher order or random smaller vectors.All calculated vectors have a positive or zero x direction.
User-defined functions
These functions and classes depend on LiberTEM core infrastructure.
Correlation
UDFs and utility functions to find peaks and refine their positions by using correlation.
- class libertem_blobfinder.udf.correlation.CorrelationUDF(peaks, zero_shift=None, *args, **kwargs)[source]
Bases:
UDF
Base class for peak correlation implementations
- __init__(peaks, zero_shift=None, *args, **kwargs)[source]
- Parameters
peaks (numpy.ndarray) – Numpy array of (y, x) coordinates with peak positions in px to correlate
zero_shift (Union[AUXBufferWrapper, numpy.ndarray, None], optional) – Zero shift, for example descan error. Can be
None
,numpy.array((y, x))
or AUX data with(y, x)
for each frame.
- get_result_buffers()[source]
The common buffers for all correlation methods.
centers
:(y, x) integer positions. NOTE: the returned positions can be out-of-frame and the user should perform bounds checking if directly indexing into the frame array.
refineds
:(y, x) positions with subpixel refinement.
peak_values
:Peak height in the log scaled frame.
peak_elevations
:Peak quality (result of
peak_elevation()
).
See source code for details of the buffer declaration.
- output_buffers()[source]
This function allows abstraction of the result buffers from the default implementation in
get_result_buffers()
.Override this function if you wish to redirect the results to different buffers, for example ragged arrays or binned processing.
- class libertem_blobfinder.udf.correlation.FastCorrelationUDF(peaks, match_pattern, zero_shift=None, *args, **kwargs)[source]
Bases:
CorrelationUDF
Fourier-based fast correlation-based refinement of peak positions within a search frame for each peak.
- __init__(peaks, match_pattern, zero_shift=None, *args, **kwargs)[source]
- Parameters
peaks (numpy.ndarray) – Numpy array of (y, x) coordinates with peak positions in px to correlate
match_pattern (MatchPattern) – Instance of
MatchPattern
zero_shift (Union[AUXBufferWrapper, numpy.ndarray, None], optional) – Zero shift, for example descan error. Can be
None
,numpy.array((y, x))
or AUX data with(y, x)
for each frame.upsample (Union[bool, int], optional) – Use DFT upsampling for the refinement step, by default False. Supplying True will choose a reasonable default upsampling factor, while any positive integer > 1 will upsample the correlation peak by this factor. DFT upsampling can provide more accurate center values, especially when peak shifts are small, but does require more computation time.
- get_backends()[source]
Signal which computation back-ends the UDF can use.
Allowed are values in
libertem.udf.base.UDF.BACKEND_ALL
.(UDF.BACKEND_NUMPY, )
is returned by default for CPU-based computation.New in version 0.6.0.
Changed in version 0.11.0: Extended from just NumPy vs. CuPy to include more generic specification of backends, including sparse arrays. See Sparse arrays for details! The backend specifications are backwards-compatible with the previously supported values.
- Returns
A single value or iterable containing values from the supported backends in
libertem.udf.base.UDF.BACKEND_ALL
- Return type
backends
- class libertem_blobfinder.udf.correlation.FullFrameCorrelationUDF(peaks, match_pattern, zero_shift=None, *args, **kwargs)[source]
Bases:
CorrelationUDF
Fourier-based correlation-based refinement of peak positions within a search frame for each peak using a single correlation step. This can be faster for correlating a large number of peaks in small frames in comparison to
FastCorrelationUDF
. However, it is more sensitive to interference from strong peaks next to the peak of interest.New in version 0.3.0.
- __init__(peaks, match_pattern, zero_shift=None, *args, **kwargs)[source]
- Parameters
peaks (numpy.ndarray) – Numpy array of (y, x) coordinates with peak positions in px to correlate
match_pattern (MatchPattern) – Instance of
MatchPattern
zero_shift (Union[AUXBufferWrapper, numpy.ndarray, None], optional) – Zero shift, for example descan error. Can be
None
,numpy.array((y, x))
or AUX data with(y, x)
for each frame.upsample (Union[bool, int], optional) – Use DFT upsampling for the refinement step, by default False. Supplying True will choose a reasonable default upsampling factor, while any positive integer > 1 will upsample the correlation peak by this factor. DFT upsampling can provide more accurate center values, especially when peak shifts are small, but does require more computation time.
- get_backends()[source]
Signal which computation back-ends the UDF can use.
Allowed are values in
libertem.udf.base.UDF.BACKEND_ALL
.(UDF.BACKEND_NUMPY, )
is returned by default for CPU-based computation.New in version 0.6.0.
Changed in version 0.11.0: Extended from just NumPy vs. CuPy to include more generic specification of backends, including sparse arrays. See Sparse arrays for details! The backend specifications are backwards-compatible with the previously supported values.
- Returns
A single value or iterable containing values from the supported backends in
libertem.udf.base.UDF.BACKEND_ALL
- Return type
backends
- class libertem_blobfinder.udf.correlation.SparseCorrelationUDF(peaks, match_pattern, steps, *args, **kwargs)[source]
Bases:
CorrelationUDF
Direct correlation using sparse matrices
This method allows to adjust the number of correlation steps independent of the template size.
- __init__(peaks, match_pattern, steps, *args, **kwargs)[source]
- Parameters
peaks (numpy.ndarray) – Numpy array of (y, x) coordinates with peak positions in px to correlate
match_pattern (MatchPattern) – Instance of
MatchPattern
steps (int) – The template is correlated with 2 * steps + 1 symmetrically around the peak position in x and y direction. This defines the maximum shift that can be detected. The number of calculations grows with the square of this value, that means keeping this as small as the data allows speeds up the calculation.
- get_backends()[source]
Signal which computation back-ends the UDF can use.
Allowed are values in
libertem.udf.base.UDF.BACKEND_ALL
.(UDF.BACKEND_NUMPY, )
is returned by default for CPU-based computation.New in version 0.6.0.
Changed in version 0.11.0: Extended from just NumPy vs. CuPy to include more generic specification of backends, including sparse arrays. See Sparse arrays for details! The backend specifications are backwards-compatible with the previously supported values.
- Returns
A single value or iterable containing values from the supported backends in
libertem.udf.base.UDF.BACKEND_ALL
- Return type
backends
- get_result_buffers()[source]
This method adds the
corr
buffer to the result ofCorrelationUDF.get_result_buffers()
. See source code for the exact buffer declaration.
- libertem_blobfinder.udf.correlation.run_blobfinder(ctx, dataset, match_pattern: MatchPattern, num_peaks, roi=None, upsample=False, progress=False)[source]
Wrapper function to find peaks in a dataset and refine their position using
FastCorrelationUDF
- Parameters
ctx (libertem.api.Context) –
dataset (libertem.io.dataset.base.DataSet) –
match_pattern (libertem_blobfinder.patterns.MatchPattern) –
num_peaks (int) – Number of peaks to look for
roi (numpy.ndarray, optional) – Boolean mask of the navigation dimension to select region of interest (ROI)
upsample (Union[bool, int], optional) – Whether to use upsampling DFT for refinement. False to deactivate (default) or a positive integer >1 to upsample by this factor when refining the correlation peak positions. Upsample True will choose a sensible upsampling factor.
progress (bool, optional) – Show progress bar
- Returns
sum_result (numpy.ndarray) – Log-scaled sum frame of the dataset/ROI
centers, refineds, peak_values, peak_elevations (libertem.common.buffers.BufferWrapper) – See
CorrelationUDF.get_result_buffers()
for details.peaks (numpy.ndarray) – List of found peaks with (y, x) coordinates
- libertem_blobfinder.udf.correlation.run_fastcorrelation(ctx, dataset, peaks, match_pattern: MatchPattern, zero_shift=None, upsample=False, **kwargs)[source]
Wrapper function to construct and run a
FastCorrelationUDF
- Parameters
ctx (libertem.api.Context) –
dataset (libertem.io.dataset.base.DataSet) –
peaks (numpy.ndarray) – List of peaks with (y, x) coordinates
match_pattern (libertem_blobfinder.patterns.MatchPattern) –
zero_shift (Union[AUXBufferWrapper, numpy.ndarray, None], optional) – Zero shift, for example descan error. Can be
None
,numpy.array((y, x))
or AUX data with(y, x)
for each frame.upsample (Union[bool, int], optional) – Whether to use upsampling DFT for refinement. False to deactivate (default) or a positive integer >1 to upsample by this factor when refining the correlation peak positions. Upsample True will choose a sensible upsampling factor.
kwargs (passed through to
run_udf()
) –
- Returns
buffers – See
CorrelationUDF.get_result_buffers()
for details.- Return type
Refinement
UDFs and utility functions to refine grid parameters from peak positions.
- class libertem_blobfinder.udf.refinement.AffineMixin(*args, **kwargs)[source]
Bases:
RefinementMixin
Refinement using
affinematch()
- __init__(*args, **kwargs)[source]
- Parameters
matcher (libertem_blobfinder.common.gridmatching.Matcher) – Instance of
Matcher
indices (numpy.ndarray) – List of indices [(h1, k1), (h2, k2), …] of all peaks. The indices can be non-integer and relative to any base vectors, including virtual ones like (1, 0); (0, 1). See documentation of
affinematch()
for details.
- class libertem_blobfinder.udf.refinement.FastmatchMixin(*args, **kwargs)[source]
Bases:
RefinementMixin
Refinement using
fastmatch()
- __init__(*args, **kwargs)[source]
- Parameters
matcher (libertem_blobfinder.common.gridmatching.Matcher) – Instance of
Matcher
start_zero (numpy.ndarray) – Approximate value (y, x) in px for “zero” point (origin, zero order peak)
start_a (numpy.ndarray) – Approximate value (y, x) in px for “a” vector.
start_b (numpy.ndarray) – Approximate value (y, x) in px for “b” vector.
- class libertem_blobfinder.udf.refinement.RefinementMixin[source]
Bases:
object
To be combined with a
libertem_blobfinder.CorrelationUDF
using multiple inheritance.The mixin must come before the UDF in the inheritance list.
The subclasses implement a
postprocess
method that calculates a refinement of start_zero, start_a and start_b based on the correlation result and populates the appropriate result buffers with this refinement result.This allows combining arbitrary implementations of correlation-based matching with arbitrary implementations of the refinement by declaring an ad-hoc class that inherits from one subclass of RefinementMixin and one subclass of CorrelationUDF.
- apply_match(index, match)[source]
Override this method to change how a match is saved in the result buffers, for example to support binned processing or ragged result arrays.
- get_result_buffers()[source]
This adds
zero
,a
,b
,selector
,error
to the superclass result buffer declaration.zero
,a
,b
:Grid refinement parameters for each frame.
selector
:Boolean mask of the peaks that were used in the fit.
error
:Residual of the fit.
See source code for the exact buffer declaration.
- libertem_blobfinder.udf.refinement.run_refine(ctx, dataset, zero, a, b, match_pattern: MatchPattern, matcher: Matcher, correlation='fast', match='fast', indices=None, steps=5, zero_shift=None, upsample=False, **kwargs)[source]
Wrapper function to refine the given lattice for each frame by calculating approximate peak positions and refining them for each frame using a combination of
libertem_blobfinder.CorrelationUDF
andlibertem_blobfinder.RefinementMixin
.Changed in version 0.3.0: Support for
FullFrameCorrelationUDF
through parametercorrelation = 'fullframe'
- Parameters
ctx (libertem.api.Context) – Instance of a LiberTEM
Context
dataset (libertem.io.dataset.base.DataSet) – Instance of a
DataSet
zero (numpy.ndarray) – Approximate value for “zero” point (y, x) in px (origin, zero order peak)
a (numpy.ndarray) – Approximate value for “a” vector (y, x) in px.
b (numpy.ndarray) – Approximate value for “b” vector (y, x) in px.
match_pattern (MatchPattern) – Instance of
MatchPattern
matcher (libertem_blobfinder.common.gridmatching.Matcher) – Instance of
Matcher
to perform the matchingcorrelation ({'fast', 'sparse', 'fullframe'}, optional) – ‘fast’, ‘sparse’ or ‘fullframe’ to select
FastCorrelationUDF
,SparseCorrelationUDF
orFullFrameCorrelationUDF
match ({'fast', 'affine'}, optional) – ‘fast’ or ‘affine’ to select
FastmatchMixin
orAffineMixin
indices (numpy.ndarray, optional) – Indices to refine. This is trimmed down to positions within the frame. As a convenience, for the indices parameter this function accepts both shape (n, 2) and (2, n, m) so that numpy.mgrid[h:k, i:j] works directly to specify indices. This saves boilerplate code when using this function. Default: numpy.mgrid[-10:10, -10:10].
steps (int, optional) – Only for correlation == ‘sparse’: Correlation steps. See
__init__()
for details.zero_shift (Union[AUXBufferWrapper, numpy.ndarray, None], optional) – Zero shift, for example descan error. Can be
None
,numpy.array((y, x))
or AUX data with(y, x)
for each frame. Only supported for correlation methodsfast
and fullframe.upsample (Union[bool, int], optional) – Use DFT upsampling for the refinement step, by default False. Supplying True will choose a reasonable default upsampling factor, while any positive integer > 1 will upsample the correlation peak by this factor. DFT upsampling can provide more accurate center values, especially when peak shifts are small, but does require more computation time.
kwargs (passed through to
run_udf()
) –
- Returns
result (Dict[str, BufferWrapper]) – Result buffers of the UDF. See
libertem_blobfinder.correlation.CorrelationUDF.get_result_buffers()
andRefinementMixin.get_result_buffers()
for details on the available buffers.used_indices (numpy.ndarray) – The peak indices that were within the frame.
Examples
>>> dataset = ctx.load( ... filetype="memory", ... data=np.zeros(shape=(2, 2, 128, 128), dtype=np.float32) ... ) >>> (result, used_indices) = run_refine( ... ctx, dataset, ... zero=(64, 64), a=(1, 0), b=(0, 1), ... match_pattern=libertem_blobfinder.common.patterns.RadialGradient(radius=4), ... matcher=grm.Matcher() ... ) >>> result['centers'].data array(...)
Integration
UDFs to integrate peak intensity with positions specified per frame. If the peak
positions are sufficiently similar for all frames, you can use
libertem_blobfinder.common.patterns.feature_vector()
together with
libertem.udf.masks.ApplyMasksUDF
instead.
- class libertem_blobfinder.udf.integration.IntegrationUDF(centers, pattern)[source]
Bases:
UDF
- __init__(centers, pattern)[source]
Integrate peak intensity at positions that are specified for each frame.
- Parameters
centers (AUXBufferWrapper) – Peak positions (y, x) as AUX buffer wrapper of kind “nav”, extra_shape (num_peaks, 2) and integer dtype.
pattern (libertem_blobfinder.common.patterns.MatchPattern) – Match pattern with the weight for each pixels.
libertem_blobfinder.common.patterns.BackgroundSubtraction
orlibertem_blobfinder.common.patterns.Circular
can be good choices.
Example
>>> from libertem_blobfinder.udf.integration import IntegrationUDF >>> from libertem_blobfinder.common.patterns import BackgroundSubtraction
>>> nav_shape = tuple(dataset.shape.nav) >>> sig_shape = tuple(dataset.shape.sig) >>> extra_shape = (3, 2) # three peaks with coordinates (y, x) >>> peaks_shape = nav_shape + extra_shape
>>> # Generate some random positions as an example >>> peaks = np.random.randint( ... low=0, high=np.min(sig_shape), size=peaks_shape, dtype=np.int64 ... )
>>> # Create an AuxBufferWrapper for the peaks >>> centers = IntegrationUDF.aux_data( ... data=peaks, ... kind='nav', ... dtype=np.int64, ... extra_shape=extra_shape ... )
>>> udf = IntegrationUDF( ... centers=centers, ... pattern=BackgroundSubtraction(radius=5, radius_outer=6) ... )
>>> res = ctx.run_udf(udf=udf, dataset=dataset)
>>> nav_shape (16, 16) >>> # Integration result for each frame and peak >>> res['integration'].data.shape (16, 16, 3)
Utilities
General utility functions.