API Reference

Input/output

Basic I/O for holography data.

We mostly want to support loading holograms from DM{3,4} files, and save results as numpy .npz files.

class libertem_holo.base.io.InputData(files: list[InputSource])[source]

Input data from one or more files, or from a LiberTEM DataSet.

property data: InputSlicer

Access slices of the input data.

Example:

>>> i = InputData.load_from_dm(path="something.dm4")  
>>> i.data[8]  # return the 8th slice of the input data  
array([...])
property dtype: dtype[Any]

The numpy dtype of the data.

property exposure_time: float

Exposure time, in seconds.

In case of a stack, this is the sum of all exposure times.

files: list[InputSource]

ordered list of input sources

classmethod from_array(data: ndarray, pixelsize: float | None = None, exposure_time: float | None = None, tags: dict[str, Any] | None = None) → InputData[source]

Create InputData from an array.

into_libertem_dataset(ctx: Context) → DataSet[source]

Turn this InputData into a LiberTEM dataset usable for running a UDF.

If this InputData wraps a LiberTEM DataSet, that DataSet is returned as-is. Other sources that were not loaded from disk (for example created using from_array()) are passed in as an in-memory dataset.

classmethod load_from_dm(path: str | Path) → InputData[source]

Load .dm3 or .dm4. Assumes a single 2D or 3D data set per file.

classmethod load_from_glob(*, base_path: str | Path, pattern: str, sort_files: bool = True) → InputData[source]

Load from a glob (for example stack_1/image_*.dm4).

Parameters:
  • base_path – path prefix where the data is stored

  • pattern – glob pattern to match against

  • sort_files – Whether the list of files should be sorted naturally (using natsort) - if disabled, files will be read in an undefined order.

Example

>>> InputData.load_from_glob(
...     base_path="/data/stack-1/",
...     pattern="*.dm4")  
classmethod load_from_libertem_dataset(dataset: DataSet, *, pixelsize: float | None = None, exposure_time: float | None = None, tags: dict[str, Any] | None = None) → InputData[source]

Wrap a LiberTEM DataSet.

The DataSet needs to be initialized, for example by loading it with libertem.api.Context.load(). Its navigation dimensions are flattened, so a 4D DataSet with nav shape (ny, nx) results in ny * nx slices.

Slices are read lazily, using a PickUDF running on an inline executor.

Metadata is not read from the DataSet, but can be given explicitly.

Example

>>> ds = ctx.load("dm", path="stack.dm4")  
>>> i = InputData.load_from_libertem_dataset(ds)  
>>> i.data[0]  
array([...])
classmethod load_from_list(paths: Sequence[str | pathlib.Path]) → InputData[source]

Load from an ordered list of .dm3 or .dm4 files.

Each file should contain a single 2D image.

property pixelsize: float | None

Pixel size in m.

property shape: tuple[int, int, int]

The 3D shape of the data.

tags_for_slice(z: int) → dict[str, Any] | None[source]

Raw dictionary of tags for slize z.

zslice(z: int) → ndarray[source]

From a 3D stack, load a single image/slice.

class libertem_holo.base.io.Results(complex_wave: np.ndarray[tuple[int, int], npd.Complex64DType | npd.Complex128DType], unwrapped_phase: np.ndarray[tuple[int, int], npd.Float16DType | npd.Float32DType | npd.Float64DType] | None = None, brightfield: np.ndarray[tuple[int, int], npd.Float16DType | npd.Float32DType | npd.Float64DType] | None = None, metadata: dict[str, Any] = <factory>)[source]

Reconstruction results.

Parameters:
  • complex_wave (np.ndarray[tuple[int, int], npd.Complex64DType | npd.Complex128DType]) – the (averaged) complex wave as 2D numpy array (dtype complex64 or complex128)

  • unwrapped_phase (np.ndarray[tuple[int, int], npd.Float16DType | npd.Float32DType | npd.Float64DType] | None) – 2D numpy array of unwrapped phase (dtype float32 or float64)

  • brightfield (np.ndarray[tuple[int, int], npd.Float16DType | npd.Float32DType | npd.Float64DType] | None) – 2D numpy array of a brightfield reconstruction from the centerband (dtype float32 or float64)

  • metadata (dict[str, Any]) – Dictionary of custom metadata. The values have to be json-serializable (roughly numbers, strings, lists or dicts of these)

classmethod load(path: str | pathlib.Path) → Results[source]

Load a result that was previously saved using the save method.

metadata_from_input(input_data: InputData, params: HoloParams | None = None) → None[source]

Update metadata from input_data.

The following keys will be set:
  • stack_shape

  • exposure_time

  • effective_pixelsize if params are given and input_data has a pixel size

  • acquisition_timestamp if available in the input data tags (formatted in ISO format)

Parameters:
  • input_data – The input hologram or hologram stack

  • params – The HoloParams used for the reconstruction

save(path: str | pathlib.Path) → None[source]

Save result data as npz file.

Parameters:

path – The path to the .npz file that will be created

Base holography functions

Reconstruction

Core reconstruction functions of LiberTEM-holo.

This includes both FFT-based and phase-shifting approaches.

class libertem_holo.base.reconstr.HologramFFT(frame: ~numpy.ndarray[tuple[int, int]], *, precision: bool = True, xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>)[source]

The half spectrum of a hologram, to share between multiple reconstruction calls.

The real-to-complex FFT is computed once, in the constructor. Instances can be passed to reconstruct_frame() and reconstruct_bf() in place of the hologram, which saves the FFT when reconstructing both the complex wave and the brightfield image from the same hologram. To also skip the parts of the spectrum that are not needed, use ReconstructionPlan directly.

Parameters:
  • frame – A numpy or cupy array containing the input hologram

  • precision – If True, the hologram is transformed in float64, resulting in complex128 results; if False in float32, resulting in complex64. See also reconstruct_frame().

  • xp – Pass in either the numpy or cupy module to select CPU or GPU processing

Examples

>>> from libertem_holo.base.generate import hologram_frame
>>> holo = hologram_frame(np.ones((64, 64)), np.zeros((64, 64)))
>>> params = HoloParams.from_hologram(holo, out_shape=(32, 32))
>>> holo_fft = HologramFFT(holo)
>>> wave = reconstruct_frame(
...     holo_fft,
...     sb_pos=params.sb_position,
...     aperture=params.aperture,
...     slice_fft=params.slice_fft,
... )
>>> bf = reconstruct_bf(
...     holo_fft,
...     aperture=params.aperture_bf,
...     slice_fft=params.slice_fft,
... )
>>> wave.shape, bf.shape
((32, 32), (32, 32))
as_partial() → PartialSpectrum[source]

Return the spectrum as a PartialSpectrum.

For use with ReconstructionPlan.

property half_spectrum: ndarray

Unnormalized, unshifted rfft2 of the hologram, (sy, sx//2 + 1).

shape

shape of the hologram (the half spectrum alone does not determine it)

libertem_holo.base.reconstr.display_fft_image(image: ndarray, sb_position: tuple[int, int], slice_fft: ndarray, mask: ndarray = 1, detail: bool = True) → None[source]

Display an fft image.

This function helps to show the steps of the reconstruction and to define the best length and width of line mask

Parameters:
  • image (array) – the input image

  • sb_position (tuple) – the sideband position (y, x), referred to the non-shifted FFT.

  • fft (slice) – contain minimum and maximum value in y and x axis.

  • mask (array) – contain the aperture and line mask

  • detail (bolean) –

libertem_holo.base.reconstr.estimate_omega(image: ndarray, sideband_position: tuple[float, float], *, flip: bool = False) → tuple[float, float][source]

Estimates the frequency carrier of the hologram.

Parameters:
  • image (array) – Holographic data array

  • sideband_position (tuple) – The sideband position (y, x), referred to the non-shifted FFT.

  • flip – ??? TODO

Returns:

omega – frequency carrier in y and x axis

Return type:

tuple

libertem_holo.base.reconstr.get_phase(hologram: ~numpy.ndarray, params: ~libertem_holo.base.utils.HoloParams, xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → ndarray[source]

Reconstruct hologram using HoloParams and extract and unwrap phase.

libertem_holo.base.reconstr.phase_offset_correction(aligned_stack: ~numpy.ndarray[tuple[int, int, int]], wtype: ~typing.Literal['weighted', 'unweighted'] = 'weighted', threshold: float = 1e-12, return_stack: bool = False, xp=<module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → tuple[ndarray, ndarray, ndarray | None][source]

Correct for phase offset in a stack of complex images.

This corrects for the phase drift in the holograms due to the biprism drift with time. Since we are dealing with the phase of the image which wraps from -pi to pi a simple scalar correction of the phase doesnt work as the phase wraps around the phase axis. So the options for a solution would be either iterative solution which is computationally heavy or an eigenvalue solution which is implemented here.

We start with a stack of holograms acquired using Holoworks or stack acquisition and this function returns a phase corrected complex image and optionally a stack of the phase corrected complex images before averaging.

Adapted from a function by oleh.melnyk: https://github.com/Ptychography-4-0/ptychography/blob/master/src/ptychography40/stitching/stitching.py for more details, see https://arxiv.org/pdf/2005.02032.pdf

Parameters:

aligned_stack

Array of shape (N, sy, sx) where N is the number of complex images; should have dtype complex64 or complex128.

threshold

Minimum absolute value to be considered in finding the phase match for stitching.

wtype

Selected type of weights to be used in the angular synchronization There are 2 possible choices: “unweighted” or “weighted”, depending on usage or not of the weights for angular synchronization (explained above)

return_stack

Also returns a stack shaped like the input stack, where the phase offset correction is applied.

xp

Either numpy or cupy for GPU support

libertem_holo.base.reconstr.reconstruct_bf(frame: ~numpy.ndarray[tuple[int, int]] | ~libertem_holo.base.reconstr.HologramFFT, aperture: ~numpy.ndarray, slice_fft: tuple[slice, slice], *, precision: bool = True, xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → ndarray[source]

Reconstruct a brightfield image from a hologram.

frame can be either a numpy or cupy array containing the hologram, or a HologramFFT of it. precision works as in reconstruct_frame(); the result is float64 or float32 accordingly.

Please use libertem_holo.base.filters.central_line_filter() to filter out fresnel fringes as appropriate.

aperture is in native layout (zero frequency at [0, 0]), like HoloParams.aperture_bf.

libertem_holo.base.reconstr.reconstruct_direct(stack: ndarray[tuple[int, int, int]], omega: tuple[float, float]) → ndarray[source]

Reconstruct a stack of phase shifted holograms.

This is using the direct reconstruction method.

Parameters:
  • stack (array_like) – Stack of holograms

  • omega (tuple) – frequency carrier in y and x axis

Returns:

phase final – the reconstructed phase image

Return type:

2D array

libertem_holo.base.reconstr.reconstruct_direct_euler(stack: ndarray[tuple[int, int, int]], omega: tuple[float, float]) → ndarray[tuple[int, int]][source]

Reconstruct a stack of phase shifted holograms.

This is using the direct reconstruction method by Ru et.al. 1994 (euler form)

Parameters:
  • stack – Holographic data array

  • omega – frequency carrier in y and x axis

Returns:

phase final – the reconstructed phase image

Return type:

2D array

libertem_holo.base.reconstr.reconstruct_double_resolution(frames: ~numpy.ndarray, sb_pos: tuple[float, float], aperture: ~numpy.ndarray, slice_fft: tuple[slice, slice], *, precision: bool = True, xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → ndarray[source]

Reconstruct a stack of phase shifted holography with double resolution method.

Parameters:
  • frames (array_like) – Two holograms taken at a phase offset of π; shape (2, height, width)

  • sb_pos – The sideband position in native (unshifted) FFT coordinates, for example as returned by estimate_sideband_position

  • aperture – A numpy or cupy array containing the aperture to apply in fourier space, in native layout (zero frequency at [0, 0]), like HoloParams.aperture

  • slice_fft – A slice to crop to the selected output shape in fourier space, as returned by get_slice_fft.

  • precision – Defines precision of the reconstruction, True for complex128 for the resulting complex wave, otherwise results will be complex64

  • xp – Pass in either the numpy or cupy module to select CPU or GPU processing

Returns:

wav – the reconstructed complex image

Return type:

complex array

libertem_holo.base.reconstr.reconstruct_frame(frame: ~numpy.ndarray[tuple[int, int]] | ~libertem_holo.base.reconstr.HologramFFT, sb_pos: tuple[float, float], aperture: ~numpy.ndarray, slice_fft: tuple[slice, slice], *, precision: bool = True, xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → ndarray[source]

Reconstruct a single hologram.

This is a convenience wrapper around ReconstructionPlan; when reconstructing many holograms with the same parameters, build the plan once and reuse it.

Parameters:
  • frame – A numpy or cupy array containing the input hologram, or a HologramFFT of it

  • sb_pos – The sideband position in native (unshifted) FFT coordinates, for example as returned by estimate_sideband_position

  • aperture – A numpy or cupy array containing the aperture to apply in fourier space, in native layout (zero frequency at [0, 0]), like HoloParams.aperture

  • slice_fft – A slice to crop to the selected output shape in fourier space, as returned by get_slice_fft.

  • precision – Defines precision of the reconstruction, True for float64/complex128 for the resulting complex wave, otherwise float32/complex64. Ignored if frame is a HologramFFT, which has the precision set at construction time.

  • xp – Pass in either the numpy or cupy module to select CPU or GPU processing

Hologram reconstruction with real-to-complex and pruned FFTs.

The per-frame reconstruction only ever uses an out_shape-sized window of the hologram’s spectrum, and the hologram is real. ReconstructionPlan precomputes, once per parameter set, which spectrum columns that window needs and then reconstructs each frame with

  • a real-to-complex FFT along the rows (half the spectrum is redundant for real input),

  • a complex FFT along the columns only for the columns that the sideband and central band windows need,

  • a gather of the window directly from the unshifted spectrum by a numba kernel (CPU) or CUDA kernel (cupy) that computes the spectrum index of each output element on the fly, conjugates the elements that are only stored as their mirror image, and applies the aperture, all in one pass, so there are no full-size roll, fftshift or scaling passes and no index arrays of the size of the output window (only the 1D column set for the pruned FFT),

  • reuse of the large intermediate buffer between frames (numpy only).

The results agree with the previous roll / fftshift / crop implementation up to floating point rounding, including its layout for odd sizes; see tests/base/test_plan.py.

class libertem_holo.base.plan.PartialSpectrum(kind: Literal['half', 'pruned'], data: Any, sig_shape: tuple[int, int])[source]

The part of a hologram’s spectrum that reconstruction needs.

Pass to ReconstructionPlan.wave() and ReconstructionPlan.bf() to share one FFT between the wave and the brightfield reconstruction.

kind is "half" for the complete half spectrum of a real frame (rfft2, shape (sy, sx // 2 + 1), see half_spectrum()), or "pruned" for the column block that ReconstructionPlan.spectrum() computes. sig_shape is the shape of the frame, which the half spectrum alone does not determine.

class libertem_holo.base.plan.ReconstructionPlan(*, sig_shape: tuple[int, int], out_shape: tuple[int, int], sb_pos: tuple[float, float], aperture: ~numpy.ndarray, aperture_bf: ~numpy.ndarray | None = None, precision: bool = True, xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>, reuse_buffers: bool = True)[source]

Precomputed column set and buffers to reconstruct holograms of one shape.

Parameters:
  • sig_shape – Shape of the input frames

  • out_shape – Shape of the reconstructed wave and brightfield image

  • sb_pos – Sideband position (y, x), referring to the unshifted FFT, as returned by libertem_holo.base.utils.estimate_sideband_position(). Truncated to integers, like the previous implementation.

  • aperture – Sideband aperture of shape out_shape, in unshifted layout (like libertem_holo.base.utils.HoloParams.aperture). A floating point aperture that is not wider than the computation’s precision is used as is, wider ones are cast down.

  • aperture_bf – Central band aperture for the brightfield image, same layout; optional

  • precision – True computes in float64/complex128, False in float32/complex64. Input frames are cast accordingly.

  • xp – numpy or cupy

  • reuse_buffers – Keep the large intermediate array between frames (numpy only). A plan with buffers must not be shared between threads.

Notes

out_shape must not exceed sig_shape along either axis. The column set is cached per sig_shape, out_shape, integer sideband position, presence of aperture_bf and xp (and GPU device), and shared read-only between plans, so building many plans for the same parameters is cheap and does not transfer anything to the GPU. The gather kernels are compiled by numba on first use (cached on disk).

Examples

>>> from libertem_holo.base.generate import hologram_frame
>>> from libertem_holo.base.utils import HoloParams
>>> holo = hologram_frame(np.ones((64, 64)), np.zeros((64, 64)))
>>> params = HoloParams.from_hologram(holo, out_shape=(32, 32))
>>> plan = ReconstructionPlan.from_params(params)
>>> wave, bf = plan.wave_and_bf(holo)
>>> wave.shape, wave.dtype, bf.shape, bf.dtype
((32, 32), dtype('complex128'), (32, 32), dtype('float64'))
bf(spec: PartialSpectrum) → ndarray[source]

Reconstruct the brightfield image from a PartialSpectrum.

classmethod from_params(params: HoloParams, *, precision: bool = True, xp: XPType | None = None, reuse_buffers: bool = True) → ReconstructionPlan[source]

Build a plan from libertem_holo.base.utils.HoloParams.

The frame shape is params.orig_shape; xp defaults to params.xp.

property n_columns: int

Number of spectrum columns that spectrum() transforms.

reconstruct(frame: ndarray) → ndarray[source]

Reconstruct the complex wave of one hologram.

reconstruct_bf(frame: ndarray) → ndarray[source]

Reconstruct the brightfield image of one hologram.

spectrum(frame: ndarray) → PartialSpectrum[source]

Transform frame as far as needed for wave() and bf().

A real-to-complex FFT along the rows, then a complex FFT along the columns, only for the columns in the sideband and central band windows.

wave(spec: PartialSpectrum) → ndarray[source]

Reconstruct the complex wave from a PartialSpectrum.

wave_and_bf(frame: ndarray) → tuple[ndarray, ndarray][source]

Reconstruct both the wave and the brightfield image of one hologram.

libertem_holo.base.plan.gather_idx_1d(n: int, o: int, s: int) → ndarray[source]

Spectrum indices of the output window along one axis.

For an unshifted spectrum of length n, output length o and an integer sideband shift s, element j of the output window (in unshifted order, as fed to the inverse FFT) is spectrum element gather_idx_1d(n, o, s)[j].

This replicates exactly what roll(+s), fftshift, the centered slice of libertem_holo.base.utils.get_slice_fft() and a final fftshift of the window do, including their behavior for odd sizes: for an even window in an odd spectrum the window is one bin off-centre, and for odd by odd the DC element lands at index o - 1 of the window instead of 0. Changing that is a separate, result-changing step.

_window_index_1d() is the same formula for one element, as used by the gather kernels.

libertem_holo.base.plan.half_spectrum(frame: ~numpy.ndarray, *, precision: bool = True, xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → PartialSpectrum[source]

Compute the unnormalized, unshifted half spectrum (rfft2) of a hologram.

Any ReconstructionPlan for the same frame shape can reconstruct from it, with any sideband position and output shape.

libertem_holo.base.plan.prepare_frame(frame: ~numpy.ndarray, *, sig_shape: tuple[int, int], precision: bool, xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → ndarray[source]

Check the shape of frame and cast it according to precision.

Returns the input unchanged if it already has the right dtype.

libertem_holo.base.plan.real_dtype(precision: bool) → dtype[source]

Return the floating point dtype that precision selects (float64 or float32).

Image filtering and aperture building

Useful image filtering helpers.

libertem_holo.base.filters.butterworth_disk(shape: tuple[int, int], radius: float, order: int = 12, xp=<module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>)[source]

Generate a filered disk-shaped aperture.

The edges are filtered with a butterworth filter of the given order.

The result is in fftshifted layout: the disk is centered at (shape[0] / 2, shape[1] / 2), which is the zero frequency of an fftshifted array for even sizes (and half a pixel past it for odd sizes).

Parameters:
  • shape – output shape of the aperture

  • radius – radius in pixels

  • order – order of the butterworth filter

  • xp – Either numpy or cupy

libertem_holo.base.filters.butterworth_line(shape: tuple[int, int], width: float, sb_position: tuple[float, float], length_ratio: float = 0.9, order: int = 12, xp=<module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>)[source]

Generate a line filter.

This is useful to remove fresnel fringes. The result is a mask that is one everywhere except for a line with butterworth-filtered edges, which is zero. The line starts close to the center of the array and points towards sb_position, extending up to the edge of the array.

Both sb_position and the result are in fftshifted layout (zero frequency at the center), like butterworth_disk(). To get the native layout used by HoloParams, crop with get_slice_fft() and apply numpy.fft.fftshift(), as in from_hologram().

Parameters:
  • shape – output shape of the aperture

  • width – width of the line in pixels

  • sb_position – Position (y, x) that the line points towards, in fftshifted coordinates of shape, i.e. an index into the result. For an aperture centered on the sideband, this is where the central band is (in from_hologram(), that is fft_shift_coords(sb_position, shape), with the native HoloParams.sb_position), and vice versa.

  • length_ratio – Length of the line from its start to sb_position, as a fraction of the distance from the center to sb_position. The part close to the center is left out.

  • order – order of the butterworth filter

  • xp – Either numpy or cupy

libertem_holo.base.filters.central_line_filter(sb_position: tuple[int, int], out_shape: tuple[int, int], orig_shape: tuple[int, int], length_ratio: float = 0.9, width: float = 10.0, crop_to_out_shape: bool = True, order: int = 2) → ndarray[int, int][source]

Return a line filter for the central band.

It can be applied by multiplying it with the aperture.

Two lines from close to the center towards both sidebands, made with butterworth_line().

Parameters:
  • sb_position – Position of the sideband in native (unshifted) FFT coordinates of orig_shape, as in HoloParams.sb_position. It is converted to fftshifted coordinates internally.

  • out_shape – Shape to crop to, if crop_to_out_shape is set.

  • orig_shape – Shape of the hologram.

  • length_ratio – See butterworth_line().

  • width – See butterworth_line().

  • order – See butterworth_line().

  • crop_to_out_shape – Crop the result to out_shape, around the center, with get_slice_fft().

Returns:

The filter in fftshifted layout, centered on the central band (zero frequency at the center). Apply numpy.fft.fftshift() after cropping to get the native layout used by HoloParams.aperture_bf.

Return type:

np.ndarray

libertem_holo.base.filters.clipped(img: ndarray, sigma: float = 6)[source]

Mask out outliers.

Return img, but with pixels deviating more than sigma from the mean masked out.

Useful for plotting:

>>> plt.imshow(img, vmax=np.max(clipped(img)))  
libertem_holo.base.filters.disk_aperture(out_shape: tuple[int, int], radius: float, xp=<module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → ndarray[source]

Generate a disk-shaped aperture

Parameters:
  • out_shape (interger) – Shape of the output array

  • radius (float) – Radius of the disk

  • xp – Either numpy or cupy

Returns:

2d array containing aperture

Return type:

aperture

libertem_holo.base.filters.exclusion_mask(img: ndarray, sigma: float = 6) → ndarray[source]

Generate outlier mask.

Return a mask with True entries for pixels deviating more than sigma from the mean.

libertem_holo.base.filters.highpass(img: ndarray, sigma: float = 2) → ndarray[source]

Return highpass by subtracting a gaussian lowpass filter.

libertem_holo.base.filters.line_filter(sb_position, out_shape, orig_shape, length_ratio=0.9, width=20, crop_to_out_shape=True)[source]

Return a line filter for the sideband.

It can be applied by multiplying it with the aperture.

sb_position is in native (unshifted) FFT coordinates of orig_shape, as in HoloParams.sb_position. The result is a boolean mask in fftshifted layout (zero frequency at the center), cropped to out_shape with get_slice_fft() if crop_to_out_shape is set.

Deprecated since version 1.1.0: Use butterworth_line() instead, which is what from_hologram() uses.

libertem_holo.base.filters.phase_unwrap(image)[source]

A phase_unwrap function that is unwrap the complex / wrapped phase image.

Parameters:

image (2d nd array) – Complex or Wrapped phase image

Return type:

2d nd array of the unwrapped phase image

libertem_holo.base.filters.remove_dead_pixels(img, sigma_lowpass=2.0, sigma_exclusion=6.0)[source]

Remove dead pixels.

Parameters:
  • img (np.array) – Input array

  • sigma_lowpass (float) – How much of the low frequencies should be removed before finding bad pixels

  • sigma_exclusion (float) – Pixels deviating more than this value from the mean will be removed

libertem_holo.base.filters.window_filter(input_array, window_type, window_shape)[source]

Apply window-based filter.

Return a filtered array with the same size of the input array

Parameters:
  • input_array (array) – Input array

  • window_type (string, float or tuple) – The type of window to be created. Any window type supported by scipy.signal.get_window is allowed here. See notes below for a current list, or the SciPy documentation for the version of SciPy on your machine.

  • window_shape (tuple of int or int) – The shape of the window. If an integer is provided, a 2D window is generated.

Notes

This function is based on scipy.signal.get_window and thus can access all of the window types available to that function (e.g., "hann", "boxcar"). Note that certain window types require parameters that have to be supplied with the window name as a tuple (e.g., ("tukey", 0.8)). If only a float is supplied, it is interpreted as the beta parameter of the Kaiser window. https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.windows.get_window.html

it is recommended to check the that after fft shift, the input array has value of 0 at the border.

Stack alignment

class libertem_holo.base.align.AmplitudeCorrelator(holoparams: ~libertem_holo.base.utils.HoloParams, upsample_factor: int = 1, normalization: ~typing.Literal['phase'] | None = 'phase', hanning: bool = False, xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>)[source]

Cross correlation on reconstructed amplitude.

class libertem_holo.base.align.BiprismDeletionCorrelator(mask: ~numpy.ndarray, upsample_factor: int = 1, normalization: ~typing.Literal['phase'] | None = 'phase', xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>)[source]

Cross correlation on low magnification while removing biprism.

classmethod get_masked(img, coords)[source]

Uses coordinates from plot_get_coords to create a mask of biprism.

classmethod plot_get_coords(img, coords_out)[source]

At low magnification, plot image of area with biprism visible. Click on edges of biprism to create the coordinates to mask it out, for cross correlation. First, click one edge of biprism from left side, then same edge, right side. Then, click other edge of biprism from left side, then right side. —–1——-2—– —–3——-4—–

class libertem_holo.base.align.BrightFieldCorrelator(holoparams: ~libertem_holo.base.utils.HoloParams, upsample_factor: int = 1, normalization: ~typing.Literal['phase'] | None = 'phase', hanning: bool = True, xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>)[source]

Cross correlation on bright field of hologram.

class libertem_holo.base.align.GradAngleCorrelator(holoparams: ~libertem_holo.base.utils.HoloParams, upsample_factor: int = 1, normalization: ~typing.Literal['phase'] | None = 'phase', xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>)[source]

Cross correlation on gradient angle of phase image.

class libertem_holo.base.align.GradXYCorrelator(holoparams: ~libertem_holo.base.utils.HoloParams, xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>)[source]

Cross correlation on gradient x and Y, correlation maps summed.

class libertem_holo.base.align.ImageCorrelator(upsample_factor: int = 1, normalization: ~typing.Literal['phase'] | None = 'phase', hanning: bool = True, binning: int = 1, xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>)[source]

Cross correlation based image registration with some pre-filtering. Assumes real-space images as input.

class libertem_holo.base.align.NoopCorrelator[source]

Do nothing, successfully.

class libertem_holo.base.align.PhaseImageCorrelator(holoparams: ~libertem_holo.base.utils.HoloParams, upsample_factor: int = 1, normalization: ~typing.Literal['phase'] | None = 'phase', hanning: bool = True, xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>)[source]

Cross correlation on reconstructed phase image.

class libertem_holo.base.align.RegResult(maximum, shift, corrmap)[source]
corrmap: ndarray

Alias for field number 2

maximum: tuple[float, float]

Alias for field number 0

shift: tuple[float, float]

Alias for field number 1

libertem_holo.base.align.align_stack(stack: ~numpy.ndarray, wave_stack: ~numpy.ndarray, static: ~numpy.ndarray | None = None, correlator: ~libertem_holo.base.align.Correlator | None = None, xp=<module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → tuple[ndarray, ndarray, ndarray, ndarray][source]

Align stacks of N holograms.

Parameters:
  • stack – Stack of images with shape (N, h, w) which is used for the alignment. It should be of dtype float32 or float64, so for holograms, you may want to align on the abs(wave). You can also slice the original data, if you want to align to a region of interest.

  • wave_stack – The (complex) result of the reconstruction. This should have shape (N, h’, w’), meaning it should have the same number of complex images as the stack argument, but the 2d items in the stack can have a different shape.

  • static – A reference image to align against. If this is not given, the first image of the stack will be taken.

  • correlator – A Correlator instance. By default, an ImageCorrelator is used, with reasonable default parameters. If you need control over these, you can construct your own Correlator and pass it in. A requirement is that it has to work on the value given as the stack parameter.

Returns:

  • aligned_stack – The aligned stack. Same shape and dtype as wave_stack

  • shifts – The shifts that were applied to the stack. Shape (N, 2)

  • reference – The pre-processed reference image, as used in the registration. Useful for debugging, for example if the correlator filters its input.

  • corrs – The correlation maps, as returned from the correlator. Useful for debugging.

libertem_holo.base.align.cross_correlate(src, target, plot: bool = False, plot_title: str = '', normalization: ~typing.Literal['phase'] | None = 'phase', upsample_factor=1, xp=<module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → tuple[ndarray, ndarray][source]

Rigid image registration by cross-correlation.

Supports optional phase normalization. Based on the phase_cross_correlation function of scikit-image, but with added GPU support via cupy, and some debugging facilities built in.

Parameters:
  • src – The static image, either a numpy or cupy array (if cupy, you should set xp=cp, too)

  • target – The moving image, either a numpy or cupy array (if cupy, you should set xp=cp, too)

  • normalization – ‘phase’ or None, same as for phase_cross_correlation

  • upsample_factor – Subpixel scaling factor, same as for phase_cross_correlation. Note that we test with a factor of up to 10; with larger values the results may not improve.

  • xp – numpy or cupy

libertem_holo.base.align.get_grad_angle(image, scale=3)[source]

From an image, get the angle of the gradient.

libertem_holo.base.align.get_grad_xy(image, scale=3)[source]

From an image, get the angle of the gradient.

libertem_holo.base.align.is_left(a: ndarray, b: ndarray, c: ndarray) → ndarray[source]

Points a and b are points on a line and result is an array of True or False if c is left or right of line resp.

libertem_holo.base.align.stack_alignment_quality(wave_stack: ndarray, shifts)[source]

Stack quality ,judged by standard deviation on the stacking axis.

This should be mostly noise, if not, there may be issues from the alignment.

Phase unwrapping

Various phase unwrapping tools and algorithms.

libertem_holo.base.unwrap.derivative_variance(array: ndarray[tuple[int, int]], k: int = 3) → ndarray[tuple[int, int]][source]

Calculate variance of the derivative of array.

Can be used as a quality map for libertem_holo.base.unwrap.quality_unwrap().

Parameters:

array

Input phase with a float dtype

k

Window size

libertem_holo.base.unwrap.phase_unwrap(image: ndarray[tuple[int, int], Float16DType | Float32DType | Float64DType | Complex64DType | Complex128DType], method: Literal['skimage', 'quality', 'laplacian'] = 'skimage') → ndarray[tuple[int, int]][source]

Unwrap phase from wrapped phase or complex wave.

You can choose different methods, which might perform better or worse depending on the input data. For tweaking the unwrapping, please call the specific unwrap methods directly.

Parameters:
  • image – Complex wave or wrapped phase image

  • method –

    The method to use for unwrapping the phase.
    • skimage: use the unwrap_phase function from scikit-image

    • quality: unwrap based on the variance of the derivative

    • laplacian: qualitative unwrapping based on

Return type:

2d nd array of the unwrapped phase image

libertem_holo.base.unwrap.prepare_laplacian_unwrap(shape: tuple[int, int], xp=<module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → LaplaceParams[source]

Prepare unwrap parameteres for a given shape.

Create the analytical discrete laplace operator and it’s inverse in the frequency domain.

You can use this if you plan to repeatedly unwrap phases of the same shape.

libertem_holo.base.unwrap.quality_unwrap(phase: ndarray[tuple[int, int]], quality: ndarray[tuple[int, int]]) → ndarray[tuple[int, int]][source]

Unwrap phase guided by a quality map.

Examples:

>>> import numpy as np
>>> from libertem_holo.base.unwrap import derivative_variance, quality_unwrap
>>> rng = np.random.default_rng()
>>> phase = rng.random(128*128).reshape(128, 128)
>>> dv = derivative_variance(phase)
>>> unwrapped = quality_unwrap(phase, dv)

Parameters:

phase

Input phase as a 2D ndarray

quality

Inverse score quality map for each pixel of the phase: lower values are higher quality

libertem_holo.base.unwrap.unwrap_phase_laplacian(wrapped_phase: ~numpy.ndarray[tuple[int, int]], params: ~libertem_holo.base.unwrap.laplace.LaplaceParams | None = None, xp=<module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → ndarray[tuple[int, int]][source]

2D Laplacian Phase Unwrapping.

Note that the result is qualitative and not guaranteed to be an integer multiple of 2π from the original phase. A potential use case is a quick phase preview, as this method is GPU-accelerated by passing in xp=cp. The result can also be used as a starting point for further processing.

Implements part of: Marvin A. Schofield and Yimei Zhu, “Fast phase unwrapping algorithm for interferometric applications,” Opt. Lett. 28, 1194-1196 (2003) https://doi.org/10.1364/OL.28.001194

Parameters:

wrapped_phase

The input phase, wrapped between -π and +π

params

Optional pre-computed parameters using prepare_laplacian_unwrap, useful if many phases of the same shape need to be unwrapped.

xp

numpy or cupy array module

Convenience functions

High-level helper functions for reconstruction and visualization.

Convenience functions for reconstruction and visualization.

libertem_holo.base.convenience.plot_mag_induction(phase: ndarray, axis: Axes, mask: ndarray | None = None, clip: float = 0.001, binning: int = 1, gain: float = 8, smooth: float = 5, cmap=None, **kwargs) → Axes[source]

Plot a magnetic induction map from a magnetic phase image.

This function combines a color-encoded visualization of the magnetic induction (obtained from the curl of the phase) with cosine contours of the smoothed phase image. The induction direction is encoded using colorvec(), while the cosine contours provide a visual representation of the phase. Optionally, a mask outline can be overlaid.

Parameters:
  • phase (ndarray) – Two-dimensional magnetic phase image.

  • axis (matplotlib.axes.Axes) – Axis on which to draw the visualization.

  • mask (ndarray, optional) – Binary mask whose boundary is overlaid as a white contour, by default None.

  • clip (float, optional) – Maximum induction magnitude to display. Larger values are clipped before color encoding, by default 1e-3.

  • binning (int, optional) – Spatial binning factor applied to the phase image and mask before processing, by default 1.

  • gain (float, optional) – Gain factor applied when computing the cosine contours, by default 8.

  • smooth (float, optional) – Standard deviation of the Gaussian filter applied to the phase image before computing the induction field, by default 5.

  • cmap (str or matplotlib.colors.Colormap, optional) – Colormap used for the induction map. By default, emp.vis.colors.cmaps.cyclic_cubehelix is used.

  • **kwargs – Additional keyword arguments passed to empyre.vis.colorvec() and empyre.vis.cosine_contours().

Returns:

The plotting axis.

Return type:

matplotlib.axes.Axes

Notes

The visualization consists of

  • a color-encoded induction map computed from the curl of the smoothed phase image,

  • cosine contours of the smoothed phase image,

  • a color wheel indicating the direction encoding,

  • an optional white contour showing the supplied mask.

libertem_holo.base.convenience.reconstruct_stack(stack: InputData, stack_ref: InputData | None = None, holoparams: HoloParams | None = None, correlator: Correlator | None = None, *, backend: Literal['cupy', 'libertem'] = 'cupy', ctx: Context | None = None, progress: bool = True, align_threads: int | None = None) → Results[source]

Reconstruct and align a stack of holograms.

Optionally use a reference stack for phase correction.

The processing happens in phases: first, all holograms are reconstructed into a stack of complex waves and brightfield images. Then, the waves are aligned against the first wave, using the brightfield images for registration. Finally, the aligned waves are averaged using phase offset correction, and optionally the (averaged) reference wave is divided out.

Parameters:
  • stack (InputData) – The input stack of holograms to reconstruct. Shape should be (N, H, W) or (H, W).

  • stack_ref (InputData, optional) – An optional reference stack of holograms for phase correction. Shape should be (N, H, W) or (H, W).

  • holoparams (HoloParams, optional) – Parameters for hologram reconstruction. If None, parameters will be estimated from the first hologram in the stack.

  • correlator (Correlator, optional) – Parameters for frame by frame alignment. If None, phase correlation will be used. Make sure the correlator works with the array module matching the backend (cupy for "cupy", numpy for "libertem").

  • backend ("cupy" or "libertem") – With "cupy", everything runs on the GPU in this process. With "libertem", the reconstruction runs as a HoloReconstructUDF on the given ctx, and alignment and averaging run on the CPU using numpy.

  • ctx (libertem.api.Context, optional) – The LiberTEM Context to run the reconstruction on; required for the "libertem" backend, and ignored by the "cupy" backend. It is not created here, as starting up a Context can take a long time, so it should be created once and re-used.

  • progress (bool) – Show progress bars

  • align_threads (int, optional) – Number of threads for registering and shifting the frames; all frames are aligned against the first one, so they are independent. Defaults to the number of CPUs for numpy, and to 1 for cupy.

Returns:

The results, packaged up in a Results instance

Return type:

results

Utility functions

Utility functions for working with holography data.

class libertem_holo.base.utils.HoloParams(sb_size: float, sb_position: tuple[float, float], aperture: np.ndarray[tuple[int, int]], aperture_bf: np.ndarray[tuple[int, int]], orig_shape: tuple[int, int], out_shape: tuple[int, int], scale_factor: float, xp: XPType)[source]

HoloParams class contians all parameters necessary for reconstruction.

Coordinate systems: sb_position is in native (unshifted) FFT coordinates of orig_shape, as returned by estimate_sideband_position() and used by reconstruct_frame(). aperture and aperture_bf have shape out_shape and are in native layout, too (zero frequency at [0, 0]), ready to be multiplied with the cropped FFT in reconstruct_frame() and reconstruct_bf().

aperture: ndarray[tuple[int, int]]

Alias for field number 2

aperture_bf: ndarray[tuple[int, int]]

Alias for field number 3

filter_aperture_gaussian(sigma: float) → HoloParams[source]

Apply gaussian filtering to sb aperture and return new parameters.

classmethod from_hologram(hologram: ~numpy.ndarray, *, central_band_mask_radius: float | None = None, out_shape: tuple[int, int] | None = None, sb_size: float | None = None, sb_position: tuple[float, float] | None = None, circle_filter_order: int = 20, line_filter_length: float = 0.9, line_filter_width: float | None = 3, line_filter_order: int = 2, sb: ~typing.Literal['lower', 'upper'] = 'upper', xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → HoloParams[source]

Determine reconstruction parameters from a hologram.

Automatically estimates sideband position and size, and returns the main parameters needed for holography reconstruction.

Parameters:
  • hologram – A single hologram, can be either a numpy or a cupy array

  • central_band_mask_radius – When estimating the sideband position, use a mask of this size to remove the central band

  • out_shape – The reconstruction shape, should be larger than the sideband size

  • sb_size – Override the sideband size; determined automatically if not given

  • sb_position – Override the sideband position; determined automatically if not given. In native (unshifted) FFT coordinates of the hologram, as returned by estimate_sideband_position().

  • circle_filter_order – Order of the butterworth filter applied to the circular part

  • line_filter_length – Length ratio of the line filter; as a fraction of the distance between the central band and the sideband

  • line_filter_width – Width of the line filter, in pixels. Passing in None will disable the line filter completely

  • line_filter_order – Order of the butterworth filter applied to the line part

  • sb – Chooses which sideband is taken. ‘lower’ or ‘upper’

  • xp – Pass in either the numpy or cupy module to select CPU or GPU processing

orig_shape: tuple[int, int]

Alias for field number 4

out_shape: tuple[int, int]

Alias for field number 5

sb_position: tuple[float, float]

Alias for field number 1

property sb_position_int: tuple[int, int]

Sideband position from float to int.

sb_size: float

Alias for field number 0

scale_factor: float

Alias for field number 6

xp: Any

Alias for field number 7

libertem_holo.base.utils.draw_lf_rect(dest: ndarray, orig_shape: tuple[int, int], sb_position_shifted: tuple[int, int], length_ratio: float, width: float) → None[source]

Draw a rectangular line filter into dest.

dest has shape orig_shape and is in fftshifted layout; sb_position_shifted is in fftshifted coordinates (zero frequency at the center).

Deprecated since version 1.1.0: Only used by libertem_holo.base.filters.line_filter(), which is deprecated.

libertem_holo.base.utils.estimate_sideband_position(holo_data: ~numpy.ndarray, holo_sampling: tuple[float, float], central_band_mask_radius: float | None = None, sb: ~typing.Literal['lower', 'upper'] = 'lower', xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → tuple[float, float][source]

Find the position of the sideband and return its position.

Parameters:
  • holo_data (ndarray) – The data of the hologram.

  • holo_sampling (tuple) – The sampling rate in both image directions.

  • central_band_mask_radius (float, optional) – The aperture radius used to mask out the centerband.

  • sb (str, optional) – Chooses which sideband is taken. ‘lower’ or ‘upper’

  • xp – Pass in either the numpy or cupy module to select CPU or GPU processing

Return type:

Tuple of the sideband position (y, x), referred to the unshifted FFT.

libertem_holo.base.utils.estimate_sideband_size(sb_position: tuple[float, float], holo_shape: tuple[int, int], sb_size_ratio: float = 0.5, xp: ~typing.Any = <module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → float[source]

Estimate the size of sideband filter.

Parameters:
  • holo_shape (array_like) – Holographic data array

  • sb_position (tuple) – The sideband position (y, x), referred to the non-shifted FFT.

  • sb_size_ratio (float, optional) – Size of sideband as a fraction of the distance to central band

  • xp – Pass in either the numpy or cupy module to select CPU or GPU processing

Returns:

sb_size – Size of sideband filter

Return type:

float

libertem_holo.base.utils.fft_shift_coords(pos, shape)[source]

Convert a position from native (unshifted) to fftshifted FFT coordinates.

For even sizes, this is where numpy.fft.fftshift() moves the value at pos, and the conversion is its own inverse. For odd sizes it is actually the numpy.fft.ifftshift() mapping, so the result is one pixel before where numpy.fft.fftshift() moves the value.

libertem_holo.base.utils.freq_array(shape: tuple[int, int], sampling: tuple[float, float] = (1.0, 1.0), xp=<module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>) → ndarray[source]

Generate a frequency array.

Parameters:
  • shape ((int, int)) – The shape of the array.

  • sampling ((float, float), optional, (Default: (1., 1.))) – The sampling rates of the array.

Return type:

Array of the frequencies.

libertem_holo.base.utils.get_slice_fft(out_shape: tuple[int, int], sig_shape: tuple[int, int]) → tuple[slice, slice][source]

Get a slice in fourier space to achieve the given output shape.

The slice is centered, so it has to be applied to an fftshifted array (zero frequency at the center); the cropped result is fftshifted, too.

libertem_holo.base.utils.line_filter_coords(length_ratio: float, sb_position_shifted: tuple[int, int], width: float, orig_shape: tuple[int, int]) → ndarray[source]

Corners of the rectangle drawn by draw_lf_rect().

sb_position_shifted and the result are in fftshifted coordinates of orig_shape (zero frequency at the center).

Deprecated since version 1.1.0: Only used by libertem_holo.base.filters.line_filter(), which is deprecated.

libertem_holo.base.utils.other_sb(sb_position, shape)[source]

Position of the other sideband.

Given the sb_position (as from estimate_sideband_position(), in native, unshifted FFT coordinates) and the shape of the hologram, calculate the position of the other sideband (also in native FFT coordinates).

libertem_holo.base.utils.remove_phase_ramp(img: np.ndarray, *, roi=None, method: Literal['gradient' | 'fit'] = 'gradient') → tuple[np.ndarray, np.ndarray, tuple[float, float]][source]

Remove a phase ramp from img.

Returns both the compensated image and the ramp that was removed.

Parameters:
  • img – The (phase) input image, has to be already unwrapped

  • roi – Either a slice (as returned by np.s_ for example), or an array of the region of interest in img. If not specified, the whole img is used. In any case, the ramp is subtraced from the whole image.

  • method –

    • ‘gradient’: the average gradient in the specified region of interest

    • ’fit’: a least-square fit of a linear gradient to the data in the region of interest

Returns:

  • corrected_img – The image with the ramp removed

  • ramp – The ramp that was found, as a 2D gradient

  • (ramp_y, ramp_x) – The ramp slopes

Simulation

libertem_holo.base.generate.hologram_frame(amp, phi, counts=1000.0, sampling=5.0, visibility=1.0, f_angle=30.0, gaussian_noise=None, poisson_noise=None, xp=<module 'numpy' from '/home/runner/work/LiberTEM-holo/LiberTEM-holo/.tox/docs-build-ci/lib/python3.11/site-packages/numpy/__init__.py'>)[source]

Generates holograms using phase and amplitude as an input

See Usage for detailed application example

New in version 0.3.0.

Notes

Theoretical basis for hologram simulations see in: Lichte, H., and M. Lehmann. Rep. Prog. Phys. 71 (2008): 016102. doi:10.1088/0034-4885/71/1/016102 [LL08]

Parameters:
  • amp (np.ndarray, 2d) – normalized amplitude and phase images of the same shape

  • phi (np.ndarray, 2d) – normalized amplitude and phase images of the same shape

  • counts (float, default: 1000.) – Number of electron counts in vacuum

  • sampling (float, default: 5.) – Hologram fringe sampling (number of pixels per fringe)

  • visibility (float, default: 1.) – Hologram fringe visibility (aka fringe contrast)

  • f_angle (float, default: 30.) – Angle in degrees of hologram fringes with respect to X-axis

  • gaussian_noise (float or int or None, default: None.) – Amount of Gaussian smoothing determined by sigma parameter applied to the hologram simulating effect of focus spread or PSF of the detector.

  • poisson_noise (float or int or None, default: None.) – Amount of Poisson applied to the hologram.

Returns:

holo – hologram image

Return type:

np.ndarray, 2d

Holography UDFs

class libertem_holo.udf.HoloReconstructUDF(*, out_shape: tuple[int, int], sb_position: tuple[float, float], aperture: ndarray, aperture_bf: ndarray | None = None, precision: bool = True)[source]

Reconstruct off-axis electron holograms using a Fourier-based method.

Running run_udf() on an instance of this class will reconstruct a complex electron wave. Use the wave key to access the raw data in the result.

See Usage for detailed application example

New in version 0.3.0.

Examples

>>> from libertem_holo.base.filters import butterworth_disk
>>> shape = tuple(dataset.shape.sig)
>>> # NOTE: in real use, one would use `HoloParams.from_hologram` to
>>> # directly estimate parameters from the data, instead of specifying manually
>>> sb_position = [2, 3]
>>> sb_size = 4.4
>>> aperture = butterworth_disk(shape=shape, radius=sb_size)
>>> holo_udf = HoloReconstructUDF(
...     out_shape=shape,
...     sb_position=sb_position,
...     aperture=np.fft.fftshift(aperture),
... )
>>> wave = ctx.run_udf(dataset=dataset, udf=holo_udf)['wave'].data