Reference

LiberTEM-blobfinder is structured into three parts:

  1. A “base” package with numerics functions that work independent of LiberTEM.

  2. A “common” package that uses other “common” aspects of LiberTEM for convenience, but can be used independent of LiberTEM core facilities.

  3. A “udf” package with classes and functions to use this functionality with full LiberTEM integration.

Basic numerics functions

These functions work independent of any LiberTEM infrastructure.

libertem_blobfinder.base.correlation.allocate_crop_bufs(crop_size, n_peaks, dtype, limit=524288)[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)[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.

Returns

corrs – Correlation of the correlation pattern and the peaks.

Return type

numpy.ndarray

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

int

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 height height that touches corrmap between r_min and r_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

float

libertem_blobfinder.base.correlation.process_frame_fast(template, crop_size, frame, peaks, out_centers, out_refineds, out_heights, out_elevations, crop_bufs)[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 should have size (2 * crop_size, 2 * crop_size). 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) – Aligned buffer for pyfftw. 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.

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
>>>
>>> frames, indices, peaks = libertem.utils.generate.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)[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 should have size (2 * crop_size, 2 * crop_size). 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) – Aligned buffer for FFT back-end, such as pyfftw. 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.

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
>>>
>>> frames, indices, peaks = libertem.utils.generate.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)

Common classes and functions

These functions and classes depend on other LiberTEM “common” packages, 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.

__init__(radius, search=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, 2x radius by default. Defining the size of the square correlation pattern.

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.

__init__(search)[source]
Parameters

search (float) – Range from the center point in px to include in the correlation, defining the size of the square correlation pattern. Will be ceiled to the next int for performing the correlation.

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.

__init__(radius, search=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, 2x radius by default. Defining the size of the square correlation pattern.

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.masks.polar_map().

Example

>>> import matplotlib.pyplot as plt
>>> (radius, phi) = libertem.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, search=None)[source]

User-defined template

__init__(template, 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 in libertem.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 and match_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 correlate sum_result with

libertem_blobfinder.common.correlation.get_peaks(sum_result, match_pattern: MatchPattern, num_peaks)[source]

Find peaks of the correlation between sum_result and match_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 with feature_vector().

Parameters
  • sum_result (numpy.ndarray) – 2D result frame as correlation input

  • match_pattern (MatchPattern) – Instance of MatchPattern to correlate sum_result with

  • num_peaks (int) – Number of peaks to find

Example

>>> frame, _, _ = libertem.utils.generate.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)[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)

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

>>> frames, indices, peaks = libertem.utils.generate.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)[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)

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

>>> frames, indices, peaks = libertem.utils.generate.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() and optimize() calculate a derived Match with a best fit of zero, a and b based on the points and the indices.

zero

Declared zero point (y, x) of the lattice

Type

numpy.ndarray

a

Declared “a” vector (y, x) of the lattice

Type

numpy.ndarray

b

Declared “b” vector (y, x) of the lattice

Type

numpy.ndarray

indices

List of indices (i, j) that are declared to express the matched points as linear combination of vectors a and b with reference to zero. The indices can be integers or floats, and they can be precise or approximate, depending on the matching method.

Type

numpy.ndarray

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

numpy.ndarray

Raises

ValueError – If the shape of indices is not as expected.

property calculated_refineds

Calculated peak positions based on lattice parameters and indices.

Type

numpy.ndarray

property error

Weighted average distance between calculated and given peak position. numpy.float(‘inf’) if match of length zero.

Type

float

classmethod invalid(correlation_result)[source]
Match

A Match instance with empty selector and all-‘nan’ attributes

optimize()[source]

Least square optimization of zero, a and b

Optimization to match the given points and indices.

Returns

A new Match instance with optimized zero, a and b

Return type

Match

Raises

np.linalg.LinAlgError – If the solver didn’t find a solution.

weighted_optimize()[source]

Weighted least square optimization of zero, a and b

Optimization to match the given points and indices using peak_elevation as weight.

Returns

A new Match instance with optimized zero, a and b

Return type

Match

Raises

np.linalg.LinAlgError – If the solver didn’t find a solution.

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
  • 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.

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

Match

Return type

Match

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

Match

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

numpy.ndarray

property centers

Integer centers (y, x) of correlation result masked with selector

Type

numpy.ndarray

property peak_elevations

Peak elevations of correlation result masked with selector

Type

numpy.ndarray

property peak_values

Peak heights of correlation result masked with selector

Type

numpy.ndarray

property refineds

Refined float centers (y, x) of correlation result masked with selector

Type

numpy.ndarray

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 matching

Include 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 the min_cluster_size parameter of HDBSCAN dynamically to the number of points to be matched. Set this to None to disable dynamic adjustment of min_cluster_size. If you like to set min_cluster_size to a constant value, you can set this to None and additionally set the clusterer 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 the min_samples parameter of HDBSCAN dynamically to the number of points to be matched. Set this to None to disable dynamic adjustment of min_samples. If you like to set min_samples to a constant value, you can set this to None and additionally set the clusterer 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
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 and max_delta to avoid calculating for unwanted higher order or random smaller vectors.

All calculated vectors have a positive or zero x direction.

exception libertem_blobfinder.common.fullmatch.NotFoundException[source]

Bases: Exception

libertem_blobfinder.common.fullmatch.angle_check(p1, p2, limit)[source]

Check if p1 and p2 have an angle difference of at least limit, both parallel or antiparallel

libertem_blobfinder.common.fullmatch.size_filter(polar, min_delta, max_delta)[source]

Accept a list of polar vectors Return a list of polar vectors with length between min_delta and max_delta

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.

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.

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.

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_result_buffers()[source]

This method adds the corr buffer to the result of CorrelationUDF.get_result_buffers(). See source code for the exact buffer declaration.

postprocess()[source]

The correlation results are evaluated during postprocessing since this implementation uses tiled processing where the correlations are incomplete in process_tile().

libertem_blobfinder.udf.correlation.run_blobfinder(ctx, dataset, match_pattern: MatchPattern, num_peaks, roi=None, progress=False)[source]

Wrapper function to find peaks in a dataset and refine their position using FastCorrelationUDF

Parameters
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, **kwargs)[source]

Wrapper function to construct and run a FastCorrelationUDF

Parameters
Returns

buffers – See CorrelationUDF.get_result_buffers() for details.

Return type

Dict[libertem.common.buffers.BufferWrapper]

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
class libertem_blobfinder.udf.refinement.FastmatchMixin(*args, **kwargs)[source]

Bases: RefinementMixin

Refinement using fastmatch()

__init__(*args, **kwargs)[source]
Parameters
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, **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 and libertem_blobfinder.RefinementMixin.

Changed in version 0.3.0: Support for FullFrameCorrelationUDF through parameter correlation = '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 matching

  • correlation ({'fast', 'sparse', 'fullframe'}, optional) – ‘fast’, ‘sparse’ or ‘fullframe’ to select FastCorrelationUDF, SparseCorrelationUDF or FullFrameCorrelationUDF

  • match ({'fast', 'affine'}, optional) – ‘fast’ or ‘affine’ to select FastmatchMixin or AffineMixin

  • 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 methods fast and fullframe.

  • kwargs (passed through to run_udf()) –

Returns

  • result (Dict[str, BufferWrapper]) – Result buffers of the UDF. See libertem_blobfinder.correlation.CorrelationUDF.get_result_buffers() and RefinementMixin.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

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)
>>> # Create an AuxBufferWrapper for the peaks
>>> centers = IntegrationUDF.aux_data(
...     data=peaks,
...     kind='nav',
...     dtype=int,
...     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)
get_result_buffers()[source]
integration:

Integrated intensity for each peak. Kind “nav”, extra_shape (num_peaks, )

get_task_data()[source]
process_frame(frame)[source]

Utilities

General utility functions.

libertem_blobfinder.udf.utils.visualize_frame(ctx, ds, result, indices, r, y, x, axes, colors=None, stretch=10)[source]

Visualize the refinement of a specific frame in matplotlib axes