Modules

This page contains auto-generated documentation for all QEM modules.

QEM - Quantitative Electron Microscopy Analysis Package

A comprehensive package for analyzing atomic-resolution electron microscopy images.

qem.image_fitting module

qem.model module

class qem.model.ImageModel(*args: Any, **kwargs: Any)[source]

Bases: Model

Base class for all image models.

__init__(dx: float = 1.0)[source]

Initialize the model.

Parameters:

dx (float, optional) – Pixel size. Defaults to 1.0.

set_grid(x_grid, y_grid)[source]
set_params(params)[source]
update_params(params)[source]

Update the model parameters (values only, not shapes).

build()[source]
get_params()[source]
call(inputs=None)[source]

Forward pass of the model.

abstract model_fn(x, y, pos_x, pos_y, height, width, *args)[source]

Core model function that defines the peak shape.

abstract volume(params: dict) numpy.ndarray[source]

Calculate the volume of each peak.

sum(local=True)[source]

Calculate sum of peaks using Keras.

Parameters:
  • x_grid (array) – x_grid coordinates mesh

  • y_grid (array) – y_grid coordinates mesh

  • local (bool, optional) – If True, calculate peaks locally within a fixed window. Defaults to False.

Returns:

array – Sum of all peaks plus background

class qem.model.GaussianModel(*args: Any, **kwargs: Any)[source]

Bases: ImageModel

Gaussian peak model.

volume(params: dict) numpy.ndarray[source]

Calculate the volume of each Gaussian peak.

For a 2D Gaussian, the volume is: height * 2π * width²

model_fn(x, y, pos_x, pos_y, height, width, *args)[source]

Core computation for Gaussian model using Keras.

class qem.model.LorentzianModel(*args: Any, **kwargs: Any)[source]

Bases: ImageModel

Lorentzian peak model.

volume(params: dict) numpy.ndarray[source]

Calculate the volume of each Lorentzian peak.

For a 2D Lorentzian, the volume is: height * π * width²

model_fn(x, y, pos_x, pos_y, height, width, *args)[source]

Core computation for Lorentzian model using Keras.

class qem.model.VoigtModel(*args: Any, **kwargs: Any)[source]

Bases: ImageModel

Voigt peak model.

__init__(dx: float = 1.0)[source]

Initialize the model.

Parameters:

dx (float, optional) – Pixel size. Defaults to 1.0.

set_params(params)[source]
build()[source]
get_params()[source]
volume(params: dict) numpy.ndarray[source]

Calculate the volume of each Voigt peak.

For a 2D Voigt profile, the volume is a weighted sum of Gaussian and Lorentzian volumes: V = ratio * (height * 2π * width²) + (1-ratio) * (height * π * width²)

model_fn(x, y, pos_x, pos_y, height, width, ratio)[source]

Core computation for Voigt model using Keras.

class qem.model.GaussianKernel[source]

Bases: object

Gaussian kernel implementation.

__init__()[source]

Initialize the kernel.

Parameters:

backend (str, optional) – Backend to use (‘tensorflow’, ‘pytorch’, or ‘jax’). Defaults to ‘jax’.

gaussian_kernel(sigma)[source]

Creates a 2D Gaussian kernel with the given sigma.

gaussian_filter(image, sigma)[source]

Applies Gaussian filter to a 2D image.

qem.model.gaussian_2d_single(xy, pos_x, pos_y, height, width, background)

2D Gaussian function for single atom.

qem.backend_utils module

Backend detection and configuration utilities.

qem.backend_utils.detect_available_backends()[source]

Detect which Keras backends are available in the current environment.

Returns:

list – List of available backend names in order of preference

qem.backend_utils.get_best_backend()[source]

Get the best available backend for the current environment.

Returns:

str – Name of the best available backend

Raises:

RuntimeError – If no backends are available

qem.backend_utils.configure_backend(backend_name=None, force=False)[source]

Configure Keras to use the specified backend.

Parameters:
  • backend_name (str, optional) – Backend to use. If None, auto-detect best.

  • force (bool) – Whether to force reconfiguration even if already set.

Returns:

str – Name of the configured backend

qem.backend_utils.setup_test_backend()[source]

Set up the best available backend for testing.

Returns:

str – Name of the configured backend

qem.backend_utils.backend_specific_config(backend_name)[source]

Apply backend-specific configurations.

Parameters:

backend_name (str) – Name of the backend to configure

qem.backend_utils.auto_configure()[source]

Auto-configure backend if none is set.

qem.utils module

qem.utils.plot_image(image, x_labels, y_labels, colormap='gray', colorbar=True)[source]

Plot an image. with x and y labels.

Parameters:
  • image (numpy.ndarray) – The image to plot.

  • x_labels (list) – The labels for the x-axis.

  • y_labels (list) – The labels for the y-axis.

  • colormap (str, optional) – The colormap to use.

  • colorbar (bool, optional) – Whether to show a colorbar.

Returns:

matplotlib.pyplot.figure – The figure containing the plot.

qem.utils.safe_ln(x)[source]

Natural logarithm function, avoiding division by zero warnings.

Parameters:

x (float) – The value to take the logarithm of.

Returns:

float – The natural logarithm of x.

qem.utils.fft2d(array)[source]

2D FFT of a numpy array.

Parameters:

array (numpy.ndarray) – The array to transform.

Returns:

numpy.ndarray – The transformed array.

qem.utils.ifft2d(array)[source]

2D inverse FFT of a numpy array.

Parameters:

array (numpy.ndarray) – The array to transform.

Returns:

numpy.ndarray – The transformed array.

qem.utils.remove_freq(image, low, high)[source]
qem.utils.apply_threshold(image, image_ref, threshold)[source]
qem.utils.make_mask_circle_centre(arr, radius)

Create a circular mask with same shape as arr

The circle is centered on the center of the array, with the circle having True values.

Similar to _make_circular_mask, but simpler and potentially faster.

Numba jit compatible.

Parameters:
  • arr (NumPy array) – Must be 2 dimensions

  • radius (scalar) – Radius of the circle

Returns:

mask (NumPy array) – Boolean array

Example

>>> import atomap.atom_finding_refining as afr
>>> arr = np.random.randint(100, size=(20, 20))
>>> mask = afr._make_mask_circle_centre(arr, 10)
qem.utils.find_duplicate_row_indices(array)[source]

Find the indices of duplicate rows in a NumPy array.

Parameters: - array: NumPy array to check for duplicate rows.

Returns: - idx_duplicates: NumPy array of indices of the duplicate rows.

qem.utils.find_row_indices(array1, array2)[source]

Efficiently find the indices of rows of array1 in array2.

Parameters:
  • array1 – A NumPy array of shape (M, N).

  • array2 – A NumPy array of shape (K, N).

Returns:

A NumPy array of indices indicating the position of each row of array1 in array2. If a row from array1 is not found in array2, the corresponding index is -1.

qem.utils.find_element_indices(array1, array2)[source]

Find indices of elements of array1 in array2.

Parameters:
  • array1 – A 1D NumPy array of elements to find.

  • array2 – A 1D NumPy array where to search for the elements.

Returns:

A list of indices indicating the position of each element of array1 in array2. If an element from array1 is not found in array2, the corresponding index is -1.

qem.utils.remove_close_coordinates(coordinates, threshold)[source]

Remove coordinates that are within a specified threshold distance of each other.

Parameters: - threshold: The distance below which coordinates are considered too close and should be removed.

qem.utils.export_params(params, filename)[source]

Export the parameters to a file.

Parameters: - params: Dictionary of parameters to export. - filename: Name of the file to export to.

qem.utils.get_random_indices_in_batches(total_examples, batch_size)[source]
qem.utils.is_point_in_polygon(point, polygon)[source]

Determine if a point is inside a polygon using the ray casting algorithm.

Parameters: - point: A 2D point as a tuple or numpy array (x, y). - polygon: A list of tuples or numpy arrays [(x1, y1), (x2, y2), …, (xn, yn)] representing the polygon vertices.

Returns: - Boolean indicating whether the point is inside the polygon.

qem.utils.find_peaks_in_rectangle(peaks, origin, a, b)[source]

Find all peaks that lie within the rectangle defined by origin, origin+a, origin+b, and origin+a+b.

Parameters: - peaks: A list of peak positions as tuples or numpy arrays (x, y). - origin: The origin point as a tuple or numpy array (x, y). - a: The vector a as a tuple or numpy array (x, y). - b: The vector b as a tuple or numpy array (x, y).

Returns: - A list of peaks within the defined rectangle.

qem.utils.rotate_vector(vector, axis, angle)[source]
qem.utils.q_space_array(pixels, gridsize, meshed=True)[source]

Return the appropriately scaled 2D reciprocal space coordinates.

Parameters:
  • pixels ((N,) array_like) – Pixels in each dimension of a ND array

  • gridsize ((N,) array_like) – Dimensions of the array in real space units

  • meshed (bool, optional) – Option to output dense meshed grid (True) or output unbroadcasted arrays (False)

  • pixels – Pixels in each dimension of a 2D array

  • gridsize – Dimensions of the array in real space units

qem.utils.broadcast_from_unmeshed(coords)[source]

For an unmeshed set of coordinates broadcast to a meshed ND array.

Examples

>>> broadcast_from_unmeshed([np.arange(5),np.arange(6)])
[array([[0, 0, 0, 0, 0, 0],
   [1, 1, 1, 1, 1, 1],
   [2, 2, 2, 2, 2, 2],
   [3, 3, 3, 3, 3, 3],
   [4, 4, 4, 4, 4, 4]]), array([[0, 1, 2, 3, 4, 5],
   [0, 1, 2, 3, 4, 5],
   [0, 1, 2, 3, 4, 5],
   [0, 1, 2, 3, 4, 5],
   [0, 1, 2, 3, 4, 5]])]
qem.utils.safe_convert_to_numpy(tensor)[source]

Safely convert a Keras tensor to numpy array, handling different backends.

Parameters:

tensor – Keras tensor or numpy array

Returns:

numpy.ndarray – The tensor converted to numpy array

qem.utils.safe_convert_to_tensor(array, dtype='float32')[source]

Safely convert a numpy array to Keras tensor.

Parameters:
  • array – numpy array or tensor

  • dtype – target dtype for the tensor

Returns:

Keras tensor

qem.utils.safe_deepcopy_params(params)[source]

Safely deep copy a parameter dictionary containing tensors.

Parameters:

params – Dictionary containing tensors and other values

Returns:

Dictionary with safely copied parameters

qem.io module

qem.io.read_legacyInputStatSTEM(filename)[source]

This function is used to read legacy StatSTEM input files in from .mat files.

StatSTEM Input class objects from matlab must be converted to struct objects in matlab first. (e.g. StatSTEM_Input = struct(StatSTEM_Input))) This is intended to be a temporary solution until the new pyStatSTEM classes are implemented. :param filename: path to .mat file containing StatSTEM input data :type filename: string

Returns:

dict – dictionary containing StatSTEM input data mirroring the legacy matlab class structure

Raises:

FileNotFoundError – Provided filename does not exist

Examples

>>> from pyStatSTEM.io import read_legacyInputStatSTEM
>>> legacyData = read_legacyInputStatSTEM('Examples/Example_PtIr.mat')
>>> inputStatSTEM = legacyData["input"]
>>> plt.imshow(inputStatSTEM['obs'])
qem.io.read_image(filename)[source]

This function is used to read images in common image file formats like .tif, .png etc.

Parameters:

filename (string) – path to image file

Returns:

array_like – image data as numpy array

Raises:

FileNotFoundError – Provided filename does not exist

Examples

>>> img = pyStatSTEM.io.read_image('Examples/det.tif')
>>> plt.imshow(img)
>>> plt.show()
qem.io.read_delimited_text(filename, delimiter=None)[source]

This function is used to read delimited text files.

Parameters:
  • filename (string) – path to delimited text file

  • delimiter (string) – delimiter used in file

Returns:

array_like – delimited text data as numpy array

Raises:

FileNotFoundError – Provided filename does not exist

Examples

>>> data = pyStatSTEM.io.read_delimited_text('Examples/det.txt')
>>> plt.imshow(img)
>>> plt.show()

qem.processing module

qem.processing.butterworth_window(shape, cutoff_radius_ftr, order)[source]

Generate a 2D Butterworth window.

Parameters: - shape: tuple of ints, the shape of the window (height, width). - cutoff_radius_ftr: float, the cutoff frequency as a fraction of the radius (0, 0.5]. - order: int, the order of the Butterworth filter.

Returns: - window: 2D numpy array, the Butterworth window.

qem.refine module

qem.refine.calculate_center_of_mass(arr)[source]

Find the center of mass of a NumPy array.

Find the center of mass of a single 2D array, or a list (or multidimensional array) of 2D arrays.

Parameters:

arr (Numpy 2D Array (or list/nd-array of such))

Returns:

cy, cx (array of floats (or nd-array of floats)) – Giving centre coordinates with sub-pixel accuracy

Examples

>>> import atomap.atom_finding_refining as afr
>>> arr = np.random.randint(100, size=(10, 10))
>>> data = afr.calculate_center_of_mass(arr)

Notes

This is a much simpler center of mass approach than the one from scipy. Gotten from stackoverflow: https://stackoverflow.com/questions/37519238/python-find-center-of-object-in-an-image

qem.refine.gauss2d(xy_meshgrid: numpy.ndarray, amplitude: float, x0: float, y0: float, sigma_x: float, sigma_y: float, theta: float, offset: float) numpy.ndarray

2D Gaussian function for fitting.

Parameters:
  • xy_meshgrid (tuple of np.ndarray) – Tuple containing the X and Y meshgrids

  • amplitude (float) – Peak amplitude

  • x0 (float) – Peak center coordinates

  • y0 (float) – Peak center coordinates

  • sigma_x (float) – Standard deviations in x and y directions

  • sigma_y (float) – Standard deviations in x and y directions

  • theta (float) – Rotation angle in radians

  • offset (float) – Background offset

Returns:

np.ndarray – 2D Gaussian evaluated on the meshgrid

qem.refine.fit_gaussian(x0, y0, sigma_x, sigma_y, theta, offset, data, plot=False, verbose=True)[source]

qem.voronoi module

qem.region module

class qem.region.Region(name: str = None, index: int = None, path: matplotlib.path.Path = None, image_shape: tuple[int, int] = None, analyzer: qem.crystal_analyzer.CrystalAnalyzer | None = None, columns: qem.atomic_column.AtomicColumns | None = None)[source]

Bases: object

name: str = None
index: int = None
path: Path = None
image_shape: tuple[int, int] = None
analyzer: CrystalAnalyzer | None = None
columns: AtomicColumns | None = None
view_3d()[source]
property lattice
__init__(name: str | None = None, index: int | None = None, path: Path | None = None, image_shape: tuple[int, int] | None = None, analyzer: CrystalAnalyzer | None = None, columns: AtomicColumns | None = None) None
class qem.region.Regions(image: numpy.ndarray)[source]

Bases: object

__init__(image: ndarray)[source]
image: ndarray = None
region_dict: dict[int, Region]
add_region(region: Region)[source]
remove_region(region: Region)[source]
get_region(idx: int) Region[source]
reset_regions()[source]
plot_regions()[source]
property region_map
plot()[source]
property keys
property values
property items
lattice(index: int | None = None)[source]
view_3d(index: int | None = None)[source]
property num_regions
draw_region(region_index: int = 0, invert_selection: bool = False)[source]

Draw a region with a polygonal selection and update the regions.

Parameters:
  • region_index (int, optional) – The region index. Defaults to 0.

  • invert_selection (bool, optional) – Whether to invert the selection. Defaults to False.

Returns:

np.ndarray – The region mask.

qem.stats module

qem.stats.add_poisson_noise(image, key_id: int = 0)[source]

Adds Poisson noise to an image.

Parameters: - image: 2D array of pixel values (representing intensities). - key: JAX random key for reproducibility.

Returns: - noisy_image: The image with Poisson noise applied.

qem.stats.compute_fim(model_func, params)[source]

Compute the Fisher Information Matrix (FIM) for a given model function with Poisson noise.

Parameters: - model_func: The model function, e.g., Gaussian, Lorentzian, etc. - params: Parameters of the model function as a JAX array. - obs: Observed image data. - x, y: Grid of points over the 2D image. - dose: Dose parameter that scales the intensity (affects Poisson noise).

Returns: - FIM: Fisher Information Matrix.

qem.stats.compute_crb(fim)[source]

Compute the Cramer-Rao Bound (CRB) given a Fisher Information Matrix (FIM).

Parameters: - fim: Fisher Information Matrix.

Returns: - crb: Cramer-Rao Bound for each parameter.

qem.stats.joint_probability_2d(observations, params, model_func)[source]

Compute the joint probability P(omega | theta) for a 2D image with Poisson-distributed data.

Parameters: - observations: The observed 2D image data (e.g., pixel values) as a JAX array. - params: Parameters of the model function as a JAX array. - model_func: The model function to compute lambda_k. - x, y: Grid of points over the 2D image (same shape as observations). - dose: Dose parameter that scales the intensity (affects Poisson noise).

Returns: - Joint probability P(omega | theta) for the entire 2D image.

qem.atomic_column module

class qem.atomic_column.AtomicColumns(lattice: ase.Atoms, lattice_ref: ase.Atoms, elements: ~typing.List[str] = <factory>, tol: float = 0, pixel_size: float = 0.1, reference: ~typing.Dict[str, numpy.ndarray] = <factory>)[source]

Bases: object

A class to represent atomic columns projected from a 3D atomic lattice onto a 2D plane.

Variables:
  • lattice (Atoms) – The 3D atomic lattice.

  • lattice_ref (Atoms) – The reference 3D atomic lattice.

  • elements (List[str]) – List of element symbols.

  • tol (float) – Tolerance for the projection.

  • pixel_size (float) – Size of each pixel.

  • projection_params (Dict[str, np.ndarray]) – Dictionary containing origin, vector_a, and vector_b for projection.

lattice: ase.Atoms
lattice_ref: ase.Atoms
elements: List[str]
tol: float = 0
pixel_size: float = 0.1
reference: Dict[str, numpy.ndarray]
get_columns()[source]

project the 3d atomic lattice onto the 2d plane in z direction and return the unique atomic columns

Parameters:

tol (float) – tolerance for the projection, within which the atoms are considered to be in the same column

Returns:

coords_2d (np.ndarray) – 2d coordinates of the atomic columns atomic_numbers (np.ndarray): atomic numbers of the atoms in the atomic columns

get_columns_ref()[source]

project the 3d atomic lattice onto the 2d plane in z direction and return the unique atomic columns

Parameters:

tol (float) – tolerance for the projection, within which the atoms are considered to be in the same column

Returns:

coords_2d (np.ndarray) – 2d coordinates of the atomic columns atomic_numbers (np.ndarray): atomic numbers of the atoms in the atomic columns

get_local_displacement(cutoff: float, units='pixel') numpy.ndarray[source]

Return an array of local displacements.

get_column_displacement(units='pixel') numpy.ndarray[source]

Return the displacement of the column.

property positions_pixel: numpy.ndarray

Return an array of positions.

property positions_pixel_ref: numpy.ndarray
property x: numpy.ndarray

Return an array of x coordinates.

property y: numpy.ndarray

Return an array of y coordinates.

property x_ref: numpy.ndarray

Return an array of x_ref coordinates.

property y_ref: numpy.ndarray

Return an array of y_ref coordinates.

property num_columns: int

Return the total number of AtomicColumns.

property atomic_numbers: numpy.ndarray

Return an array of atom types.

property column_elements: List[str]

Return a list of column elements.

property atom_types: numpy.ndarray

Return a numpy array of atom types.

get_strain_xy(cutoff: float = 0) numpy.ndarray[source]

Return the strain matrix.

get_strain(cutoff: float = 3.0) numpy.ndarray[source]

Return the strain tensor.

__init__(lattice: ase.Atoms, lattice_ref: ase.Atoms, elements: ~typing.List[str] = <factory>, tol: float = 0, pixel_size: float = 0.1, reference: ~typing.Dict[str, numpy.ndarray] = <factory>) None

qem.crystal_analyzer module

class qem.crystal_analyzer.CrystalAnalyzer(image: ndarray, dx: float, peak_positions: ndarray, atom_types: ndarray, elements: list[str], units: str = 'A', region_mask: ndarray | None = None)[source]

Bases: object

__init__(image: ndarray, dx: float, peak_positions: ndarray, atom_types: ndarray, elements: list[str], units: str = 'A', region_mask: ndarray | None = None)[source]
region_of_interest(sigma: float = 0.8)[source]
select_region(peak_positions: ndarray, atom_types: ndarray)[source]

Select a region of interest from the image.

Parameters:
  • peak_positions (np.ndarray) – Array of peak positions.

  • atom_types (np.ndarray) – Array of atom types.

Returns:

tuple – Tuple containing peak positions, atom types, and region mask.

read_cif(cif_file_path: str)[source]
get_unitcell_elements()[source]

Get the elements present in the unit cell.

Returns: - element_symbols: The symbols of the elements present in the unit cell.

static is_element_in_unit_cell(unitcell, element_symbol: str) list[source]

Checks if the given element is present in each site of the unit cell.

Args: - unitcell (Structure): The unit cell to check. - element_symbol (str): The symbol of the element to check for (e.g., “O” for oxygen).

Returns: - A list of booleans, where each boolean indicates whether the target element is present in the corresponding site of the unit cell.

get_atomic_columns(tol: float = 0, reciprocal: bool = True, sigma: float = 0.8)[source]
align_unit_cell_to_image(ref: tuple | None = None, plot: bool = True, mode: str = 'affine')[source]

Transforms unit cell coordinates to the image coordinate system, aligning them with detected atomic peak positions. Optionally visualizes the transformation, including the origin, lattice vectors, and positions of atoms within the unit cell.

Parameters: - plot: A boolean indicating whether to plot the mapping and unit cell visualization. - ref: A tuple containing the origin and lattice vectors of the reference unit cell. - mode: A string indicating the transformation mode. Either ‘affine’ or ‘perfect’. Affine means affine transformation is applied to the unit cell based on the lattice vectors selected on the image. In practice, ‘affine’ is more robust to match with atomic column on the image, because the unit cell and image can have different angle and its a and b lattice vectors may scale differently due to scanning distortion or simply a wrong pixel size. In contrast, ‘perfect’ means the transformation is based on the rotation of the angle between the lattice a-vector and the x-axis on the image and the pixel size from the image. You should use ‘perfect’ if you want the absolute mapping of the unit cell to the image if you have an ‘ideal’ microscope image with no distortion and correct pixel size.

Returns: - unitcell_transformed: The transformed coordinates of the unit cell.

get_lattice_3d(sigma: float = 0.8)[source]

Generate a supercell lattice based on the given lattice vectors and limits.

Parameters: - sigma: The sigma value around the intial peak positions to consider for the supercell lattice.

Returns: - supercell_lattice: The supercell lattice.

get_closest_peak(candidate_peaks: ndarray, target_peak: ndarray, min_distance: float = 1.5)[source]

Find the closest 2D peak to the given atom position.

get_origin_offset(mode: str = 'adaptive')[source]
get_strain(cut_off: float = 5.0)[source]

Get the strain of the atomic columns based on the given cut-off radius.

Args: - cut_off (int): The cut-off radius.

Returns: - The strain of the atomic columns.

select_lattice_vectors(tolerance: int = 10, reciprocal: bool = False)[source]

Choose the lattice vectors based on the given tolerance.

Args: - tolerance (int): The tolerance value.

Returns: - The selected origin, a, and b vectors.

plot()[source]
plot_unitcell(mode: str = 'affine')[source]
plot_displacement(mode: str = 'local', cut_off: float = 5.0, units: str = 'A')[source]
plot_strain(cut_off: float = 5.0, save: bool = False)[source]
measure_polarization(a_element: str, b_element: str, cutoff_radius: float = 5.0, num_neighbors: int = 2) dict[source]

Measure the polarization of B atoms relative to the center of surrounding A atoms.

Parameters:
  • a_element (str) – Element for A atoms (e.g., ‘Sr’)

  • b_element (str) – Element for B atoms (e.g., ‘Ti’)

  • cutoff_radius (float, optional) – Radius to search for surrounding A atoms. Defaults to 5.0, unit: Å.

  • num_neighbors (int, optional) – Number of surrounding A atoms to consider. Defaults to 2.

Returns:

dict

Dictionary containing:
  • ’positions’: Array of B atom positions

  • ’polarization’: Array of polarization vectors for each B atom

  • ’magnitude’: Array of polarization magnitudes

plot_polarization(a_element: str, b_element: str, cutoff_radius: float = 5.0, save: bool = False, exclude_border: bool = False, border_pixel: int = 10, vector_scale: float = 10.0)[source]

Plot the polarization vectors and magnitudes.

Parameters:
  • a_element (str) – Element for A atoms (e.g., ‘Sr’)

  • b_element (str) – Element for B atoms (e.g., ‘Ti’)

  • cutoff_radius (float, optional) – Radius to search for surrounding A atoms. Defaults to 5.0, unit: Å.

  • save (bool, optional) – Whether to save the plot. Defaults to False.

measure_oxygen_tilt(a_type: int, o_type: int, cutoff_radius: float = 5.0) dict[source]

Measure the tilt of oxygen atoms based on their coordinates and nearby A site atoms.

The tilt is calculated as the angle between two nearby oxygen atoms and the line formed by two A site atoms.

Parameters:
  • a_type (int) – Atom type label for A site atoms (e.g., 0)

  • o_type (int) – Atom type label for oxygen atoms (e.g., 2)

  • cutoff_radius (float, optional) – Radius to search for nearby atoms. Defaults to 5.0.

Returns:

dict

Dictionary containing:
  • ’positions’: Array of oxygen atom positions

  • ’tilt_angles’: Array of tilt angles in degrees for each oxygen atom

  • ’tilt_vectors’: Array of unit vectors representing the tilt direction

plot_oxygen_tilt(a_type: int, o_type: int, cutoff_radius: float = 5.0, save: bool = False)[source]

Plot the oxygen tilt angles and directions.

Parameters:
  • a_type (int) – Atom type label for A site atoms

  • o_type (int) – Atom type label for oxygen atoms

  • cutoff_radius (float, optional) – Radius to search for nearby atoms. Defaults to 5.0.

  • save (bool, optional) – Whether to save the plot. Defaults to False.

plot_lattice_parameter_unitcell(units='A', min_dist: float = 0.1, show_lattice: bool = False, boundary_thresh: int = 20, line_plot_direction: str | None = None, line_plot_averaging_window: float | None = None, line_plot_style: str = 'confidence_interval')[source]

Plot local lattice parameters using adaptive cell origins. The lattice parameter is defined as the distance between neighboring origins in a and b directions.

plot_lattice_parameter_nearest(units='A', show_lattice: bool = False, angle_thresh: float = 0.95, dist_min_a: float = 1, dist_min_b: float = 1, dist_max_a: float | None = None, dist_max_b: float | None = None, boundary_thresh: int = 5)[source]

Plot local lattice parameters using all nearest neighbors in the a and b directions within an angular and distance cutoff.

Parameters:
  • units (str, optional) – Unit of the lattice parameter. Defaults to ‘A’.

  • show_lattice (bool, optional) – Whether to show the lattice. Defaults to False.

  • angle_thresh (float, optional) – Angular cutoff. Defaults to 0.95.

  • dist_min_a (float, optional) – Minimum distance in a direction in A. Defaults to 1.

  • dist_min_b (float, optional) – Minimum distance in b direction in A. Defaults to 1.

  • dist_max_a (float, optional) – Maximum distance in a direction in A. Defaults to 3.

  • dist_max_b (float, optional) – Maximum distance in b direction in A. Defaults to 3.

  • boundary_thresh (int, optional) – Boundary threshold in pixels. Defaults to 20.

property nx
property ny
property min_distances
property scalebar

qem.probe module

Functions for emulating electron optics of a TEM.

class qem.probe.aberration(Krivanek, Haider, Description, amplitude, angle, n, m)[source]

Bases: object

A class describing electron lens aberrations.

__init__(Krivanek, Haider, Description, amplitude, angle, n, m)[source]

Intialize the lens aberration object.

Parameters:
  • Krivanek (str) – A string describing the aberration coefficient in Krivanek notation (C_mn)

  • Haider (str) – A string describing the aberration coefficient in Haider notation (ie. A1, A2, B2)

  • Description (str) – A string describing the colloqiual name of the aberration ie. 2-fold astig.

  • amplitude (float) – The amplitude of the aberration in Angstrom

  • angle (float) – The angle of the aberration in radians

  • n (int) – The principle aberration order

  • m (int) – The rotational order of the aberration.

qem.probe.depth_of_field(eV, alpha)[source]

Calculate the probe depth of field (z-resolution) for a probe.

Parameters:
  • eV (float) – Probe accelerating voltage in electron volts

  • alpha (float) – Probe forming semi-angle in mrad

Returns:

dof (float) – The probe full-width-at-half-maximum (FWHM) depth of field

qem.probe.aberration_starter_pack()[source]

Create the set of aberrations up to fifth order.

qem.probe.chi(q, qphi, lam, df=0.0, aberrations=None)[source]

Calculate the aberration function, chi.

Parameters:
  • q (float or array_like) – Reciprocal space extent (Inverse angstroms).

  • qphi (float or array_like) – Azimuth of grid in radians

  • lam (float) – Wavelength of electron (Inverse angstroms).

  • df (float, optional) – Defocus in Angstrom

  • aberrations (list, optional) – A list containing a set of the class aberration, pass an empty list for an unaberrated contrast transfer function.

Returns:

chi (float or array_like) – The aberration function, will be the same shape as q. This is used to calculate the probe wave function in reciprocal space.

qem.probe.make_contrast_transfer_function(pix_dim, real_dim, eV, app, optic_axis=None, aperture_shift=None, tilt_units='mrad', df=0, aberrations=None, q=None, app_units='mrad')[source]

Make an electron lens contrast transfer function.

Parameters:
  • pix_dim ((2,) int array_like) – The pixel size of the grid

  • real_dim ((2,) float array_like) – The size of the grid in Angstrom

  • eV (float) – The energy of the probe electrons in eV

  • app (float or None) – The aperture in units specified by app_units, pass app = None for no aperture

  • optic_axis ((2,) array_like, optional) – allows the user to specify a different optic axis in units specified by tilt_units

  • aperture_shift ((2,) array_like, optional) – Shift of the objective aperture relative to the center of the array

  • tilt_units (string) – Units of the optic_axis or aperture_shift values, default is mrad

  • df (float) – Probe defocus in A, a negative value indicate overfocus

  • aberrations (array_like of aberration objects) – List containing instances of class aberration

  • q – Precomputed reciprocal space array, allows the user to reduce computation time somewhat

  • app_units (string) – The units of app (A^-1 or mrad)

Returns:

ctf (array_like) – The lens contrast transfer function in reciprocal space

qem.probe.focused_probe(gridshape, rsize, eV, app, beam_tilt=None, aperture_shift=None, tilt_units='mrad', df=0, aberrations=None, q=None, app_units='mrad', qspace=False)[source]

Make a focused electron probe wave function.

Parameters:
  • gridshape ((2,) array_like) – The pixel size of the grid

  • rsize ((2,) array_like) – The size of the grid in Angstrom

  • eV (float) – The energy of the probe electrons in electron volts

  • app (float) – The probe-forming apperture in units specified by app_units, pass None if no probe forming aperture is to be used

  • beam_tilt (array_like, optional) – Allows the user to simulate a (small < 50 mrad) beam tilt. To maintain periodicity of the wave function at the boundaries this tilt is rounded to the nearest pixel value.

  • aperture_shift (array_like, optional) – Allows the user to simulate a (small < 50 mrad) aperture shift. To maintain periodicity of the wave function at the boundaries this tilt is rounded to the nearest pixel value.

  • tilt_units (string, optional) – Units of beam tilt and aperture shift, can be ‘mrad’,’pixels’ or ‘invA’

  • df (float, optional) – Probe defocus in A, a negative value indicate overfocus

  • aberrations (list, optional) – A list of of probe aberrations of class pyms.Probe.aberration, pass an empty list for an un-aberrated probe

  • app_units (string, optional) – The units of the aperture size (“invA”, “pixels” or “mrad”)

  • qspace (bool, optional) – If True return the probe in reciprocal space

Returns:

probe (complex (Y,X) np.ndarray) – The requested electron probe wave function

qem.probe.plane_wave_illumination(gridshape, gridsize, eV, tilt=None, tilt_units='mrad', qspace=False)[source]

Generate plane wave illumination for input to multislice.

The wave function will be normalized such that sum of intensity is unity in real space.

Parameters:
  • gridshape ((2,) array_like) – Pixel dimensions of the 2D grid

  • gridsize ((2,) array_like) – Size of the grid in real space

  • eV (float) – Probe energy in electron volts (irrelevant for untilted illumination)

  • tilt (array_like, optional) – Allows the user to simulate a (small < 50 mrad) beam tilt, To maintain periodicity of the wave function at the boundaries this tilt is rounded to the nearest pixel value.

  • tilt_units (string, optional) – Units of beam tilt, can be ‘mrad’,’pixels’ or ‘invA’

  • qspace (bool, optional) – Pass qspace = True to get the probe in momentum (q) space

Returns:

illum (np.ndarray (Y,X))

qem.probe.wavev(E)[source]

Evaluate the relativistically corrected wavenumber of an electron with energy E.

Energy E must be in electron-volts, see Eq. (2.5) in Kirkland’s Advanced Computing in electron microscopy

qem.probe.relativistic_mass_correction(E)[source]

Evaluate the relativistic mass correction for electron with energy E in eV.

See Eq. (2.2) in Kirkland’s Advanced Computing in electron microscopy.

qem.probe.simulation_result_with_Cc(func, Cc, deltaE, eV, args=None, kwargs=None, npoints=7, deltaEconv='1/e')[source]

Perform a simulation using function, taking into account chromatic aberration.

Pass in the function that simulates the multislice result, it is assumed that defocus is a variable named ‘df’ somewhere in the keyword argument list.

Parameters:
  • func (function) – Function that simulates the result of interest, ie. pyms.HRTEM. The defocus must be present in the keyword argument list as ‘df’

  • Cc (float) – Chromatic aberration coefficient in Angstroms

  • deltaE (float) – Energy spread in electron volts using 1/e measure of spread (to convert from FWHM divide by 1.655, and divide by sqrt(2) to convert from standard deviation )

  • eV (float) – (Mean) beam energy in electron volts

  • args (list, optional) – Arguments for the method function used to propagate probes to the exit surface

  • kwargs (Dict, optional) – Keyword arguments for the method function used to propagate probes to the exit surface

  • npoints (int,optional) – Number of integration points in the Cc numerical integration

Returns:

average (dict or array_like) – The simulation requested but averaged over the different defocus values to account for chromatic aberration.

qem.probe.Cc_integration_points(Cc, deltaE, eV, npoints=7, deltaEconv='1/e')[source]

Calculate the defocus integration points for simulating chromatic aberration.

The integration points are selected by dividing the assumed gaussian defocus spread into npoints regions of equal probability, then finding the mean defocus in each of those regions.

Parameters:
  • Cc (float) – Chromatic aberration coefficient in Angstroms

  • deltaE (float) – Energy spread in electron volts using 1/e measure of spread (to convert from FWHM divide by 1.655, and divide by sqrt(2) to convert from standard deviation )

  • eV (float) – (Mean) beam energy in electron volts

  • npoints (int,optional) – Number of integration points in the Cc numerical integration

  • deltaEconv (float,optional) – The convention for deltaE, the energy spread, acceptable inputs are ‘1/e’ the energy point that the probability density function drops to 1/e times its maximum value, ‘std’ for standard deviation and ‘FWHM’ for the full width at half maximum of the energy spread.

Returns:

defocii ((`npoints,) array_like`) – The defocus integration points

qem.probe.Cc_defocus_spread(df, Cc, deltaE, eV, deltaEconv)[source]

Calculate the defocus spread for chromatic aberration.

Evaluates the probability density function at defocus df for the defocus spread of a chromatic aberration (Cc) for (1/e) energy spread deltaE and beam energy eV in electron volts.

Parameters:
  • df (float or array_like) – defocus or defocii at which to evaluate the probability density function

  • Cc (float) – Chromatic aberration coefficient in Angstroms

  • deltaE (float) – Energy spread in electron volts using the measure given by deltaEconv (1/e measure of spread is default)

  • eV (float) – (Mean) beam energy in electron volts

  • deltaEconv (string,optional) – The convention for deltaE, the energy spread, acceptable inputs are ‘1/e’ the energy point that the probability density function drops to 1/e times its maximum value, ‘std’ for standard deviation and ‘FWHM’ for the full width at half maximum of the energy spread

Returns:

Cc_pdf (float or array_like) – the probability density function, will be the same size and shape as df

qem.probe.convert_deltaE(deltaE, deltaEconv)[source]

Convert the energy spread input to a 1/e spread.

Parameters:
  • deltaE (float) – Energy spread in electron volts using the measure given by deltaEconv

  • deltaEconv (string) – The convention for deltaE, the energy spread, acceptable inputs are ‘1/e’ the energy point that the probability density function drops to 1/e times its maximum value, ‘std’ for standard deviation and ‘FWHM’ for the full width at half maximum of the energy spread

qem.probe.convert_tilt_angles(tilt, tilt_units, rsize, eV, invA_out=False)[source]

Convert tilt to pixel or inverse Angstroms units regardless of input units.

Input units can be mrad, pixels or inverse Angstrom

Parameters:
  • tilt (array_like) – Tilt in units of mrad, pixels or inverse Angstrom

  • tilt_units (string) – Units of specimen and beam tilt, can be ‘mrad’,’pixels’ or ‘invA’

  • rsize ((2,) array_like) – The size of the grid in Angstrom

  • eV (float) – Probe energy in electron volts

  • invA_out (bool) – Pass True if inverse Angstrom units are desired.

qem.detector module

qem.abberration module

qem.abberration.aberration_function(aberrations, wavelength, kx, ky)[source]

Calculate the aberration phase shift for given aberrations and spatial frequencies.

Parameters: aberrations (dict): Dictionary of aberration coefficients (e.g. {‘A1’: 1e-9, ‘C3’: 1e-6}) kx, ky (ndarray): Spatial frequency coordinates in the x and y directions

Returns: phase_shift (ndarray): Aberration phase shift over the spatial frequency plane

qem.abberration.contrast_transfer_function(u, defocus, Cs, wavelength)[source]

Calculate the Contrast Transfer Function (CTF) for given parameters.

Parameters: u : array-like, spatial frequency defocus : defocus value (Delta f) Cs : spherical aberration coefficient wavelength: wavelength of the electron

Returns: CTF value for the given spatial frequencies.

qem.periodic_table module

qem.color module

qem.color.color_iter(name, n)[source]
qem.color.get_unique_colors()[source]

An iterator to generate unique colors by cycling through the HSV color space. The saturation and value components are fixed to ensure bright and vivid colors.

qem.zoom module

qem.zoom.zoom_on_pixel(input_array, coordinates, upsample_factor=1, output_shape=None, num_threads=1, use_numpy_fft=False, return_real=True, return_coordinates=False)[source]

Zoom in on a 1D or 2D array using Fourier upsampling.

Parameters:
  • (np.ndarray) (input_array)

  • floats) (coordinates (tuple of)

  • (int (num_threads)

  • optional) (If True, return the zoomed coordinates along with the zoomed array. Defaults to False.)

  • ints (output_shape (tuple of)

  • optional)

  • (int

  • optional)

  • (bool (return_coordinates)

  • optional)

  • (bool

  • optional)

  • (bool

  • optional)

Returns:

  • zoomed_array (np.ndarray) (The zoomed array upsampled by `upsampling_factor with size output_shape.`)

  • coordinates (np.ndarray, optional) (The coordinates of the zoomed region, if `return_coordinates is True.`)

qem.zoom.zoom_nd(input_array, offsets=(), center_convention=<class 'float'>, **kwargs)[source]

Zoom in on the center of a 1D or 2D array using Fourier upsampling.

Parameters:
  • (np.ndarray) (input_array)

  • floats (offsets (tuple of)

  • optional) (Function to determine the "center" of the array. Defaults to float.)

  • (function (center_convention)

  • optional)

  • **kwargs (Additional arguments passed to zoom_on_pixel.)

Returns:

  • zoomed_array (np.ndarray) (The zoomed array upsampled by `upsampling_factor with size output_shape.`)

  • coordinates (np.ndarray, optional) (The coordinates of the zoomed region, if `return_coordinates is True.`)

qem.zoom.fourier_interp2d(data, outinds, nthreads=1, use_numpy_fft=False, return_real=True)[source]

Use the fourier scaling theorem to interpolate (or extrapolate, without raising any exceptions) data.

Parameters:
  • data (ndarray) – The data values of the array to interpolate

  • outinds (ndarray) – The coordinate axis values along which the data should be interpolated CAN BE: ndim x [n,m,…] like np.indices OR (less memory intensive, more processor intensive) ([n],[m],…)

qem.gui_classes module

qem.gui_classes.get_atom_selection_from_verts(atom_positions, verts, invert_selection=False)[source]

Get a subset of atom positions within region spanned to verticies.

Parameters:
  • atom_positions (list or NumPy array) – In the form [[x0, y0]. [x1, y1], …]

  • verts (list of tuples) – List of positions, spanning an enclosed region. [(x0, y0), (x1, y1), …]. Need to have at least 3 positions.

  • invert_selection (bool, optional) – Get the atom positions outside the region, instead of the ones inside it. Default False.

Returns:

atom_positions_selected (NumPy array)

Examples

>>> from numpy.random import randint
>>> from atomap.tools import _get_atom_selection_from_verts
>>> atom_positions = randint(0, 200, size=(200, 2))
>>> verts = [(200, 400), (400, 600), (100, 100)]
>>> atom_positions_selected = _get_atom_selection_from_verts(
...        atom_positions=atom_positions, verts=verts)

Get atom positions inside the region

>>> atom_positions_selected = _get_atom_selection_from_verts(
...        atom_positions=atom_positions, verts=verts,
...        invert_selection=True)
qem.gui_classes.get_atom_type()[source]
class qem.gui_classes.GetRegionSelection(image, region_map, invert_selection=False)[source]

Bases: object

__init__(image, region_map, invert_selection=False)[source]
onselect(verts)[source]
get_region_mask()[source]
class qem.gui_classes.GetAtomSelection(image, atom_positions, invert_selection=False, size=1)[source]

Bases: object

__init__(image, atom_positions, invert_selection=False, size=1)[source]

Get a subset of atom positions using interactive tool.

Access the selected atom positions in the atom_positions_selected attribute.

Parameters:
  • image (2D HyperSpy signal or 2D NumPy array)

  • atom_positions (list of lists, NumPy array) – In the form [[x0, y0]. [x1, y1], …]

  • invert_selection (bool, optional) – Get the atom positions outside the region, instead of the ones inside it. Default False

Variables:

atom_positions_selected (NumPy array)

onselect(verts)[source]
get_mask_image(path, invert_selection=False)[source]
class qem.gui_classes.InteractivePlot(image: numpy.ndarray, peaks_locations: numpy.ndarray, atom_types: numpy.ndarray | None = None, tolerance: float = 10, dx: float = 1, units: str = 'A', dimension: str = 'si-length', zoom: float = 1)[source]

Bases: object

__init__(image: numpy.ndarray, peaks_locations: numpy.ndarray, atom_types: numpy.ndarray | None = None, tolerance: float = 10, dx: float = 1, units: str = 'A', dimension: str = 'si-length', zoom: float = 1)[source]
onclick_add_or_remove(event)[source]
on_key_press(event)[source]
property scalebar
update_plot(title)[source]
add_or_remove(tolerance: float = 10)[source]
onclick_select(event)[source]
select(tolerance: float = 10)[source]
onclick_select_vectors(event)[source]
draw_arrow(start, end, label)[source]
select_vectors(tolerance: float)[source]

qem.benchmark module

qem.add_coordinate module

Module for handling interactive coordinate addition and removal in matplotlib plots.

class qem.add_coordinate.AddCoordinate(line, init_coordinate, extra_line)[source]

Bases: object

A class to handle the addition and removal of coordinates in a matplotlib plot. This class is typically used for interactive plotting where the user can click on the plot to add or remove coordinates.

Variables:
  • line (matplotlib.lines.Line2D) – The line object which is updated upon user interaction.

  • init_coordinate (numpy.ndarray) – Initial coordinates.

  • extra_line (list) – List of additional line objects to be updated.

__call__(event)[source]

Method that handles mouse events; adds or removes coordinates based on user clicks.

__init__(line, init_coordinate, extra_line)[source]

Initializes the AddCoordinate object.

Parameters:
  • line (matplotlib.lines.Line2D) – The line object in the matplotlib plot.

  • init_coordinate (numpy.ndarray) – Initial set of coordinates.

  • extra_line (list) – Additional line objects that need to be updated along with the main line.

qem.dm module

Reading/writting dm3/dm4 files Pavel Potapov, temDM, 2022

can be used under GNU Lesser General Public License

qem.dm.dm_load(filename, index=0, prt=False) tuple[source]
qem.dm.dm_load_as_tags(filename, index=0) dict[source]
qem.dm.dm_store(filename, Image, dimensions: dict, dm_ext: str, calibration=None, meta=None, prt=False)[source]
qem.dm.dm_store_must_tags(Image, dimensions: dict, dm_ext: str, calibration=None, meta=None) dict[source]
qem.dm.set_endian(endian: str) str[source]
qem.dm.get_Specified_value(f, length: int, endian: str, Identifier: str)[source]
qem.dm.get_int8(f, endian: str) int[source]
qem.dm.get_uint8(f, endian: str) int[source]
qem.dm.get_int16(f, endian: str) int[source]
qem.dm.get_uint16(f, endian: str) int[source]
qem.dm.get_int32(f, endian: str) int[source]
qem.dm.get_uint32(f, endian: str) int[source]
qem.dm.get_int64(f, endian: str) int[source]
qem.dm.get_uint64(f, endian: str) int[source]
qem.dm.get_float32(f, endian: str) float[source]
qem.dm.get_float64(f, endian: str) float[source]
qem.dm.get_char(f, endian: str) str[source]
qem.dm.set_int8(value: int, endian: str)[source]
qem.dm.set_uint8(value: int, endian: str)[source]
qem.dm.set_int16(value: int, endian: str)[source]
qem.dm.set_uint16(value: int, endian: str)[source]
qem.dm.set_int32(value: int, endian: str)[source]
qem.dm.set_uint32(value: int, endian: str)[source]
qem.dm.set_int64(value: int, endian: str)[source]
qem.dm.set_uint64(value: int, endian: str)[source]
qem.dm.set_float32(value: float, endian: str)[source]
qem.dm.set_float64(value: float, endian: str)[source]
qem.dm.set_char(valueStr: float, endian: str)[source]
qem.dm.NP_number_types() tuple[source]
qem.dm.tag_counts() tuple[source]
class qem.dm.read_DM(f, prt)[source]

Bases: object

__init__(f, prt)[source]
init_dict()[source]

#reverse dictionary such as DM stream code is a key

read_file()[source]
file_header()[source]

Read dm format (extension) and endian 1:dm ext (dm3 or dm4) 2:length in bytes 3: endian, 0-big, 1-little (only for INSIDE tags)

read_DMvalue() int[source]

diferent formats for dm3 and dm4

group_header(group_name='', root=False) tuple[source]

Read header of TagGroup 1:length of the whole group (in dm4 only) 2:is group sorted (meaning unknown) 3:is group open 4:number of tags in group

name_header() tuple[source]

Read name of tag and its code 1:tag_code =21 if simple Tag, =20 if TagGroup branch 2:length of tag name 3:tag_name - names of Tag or TagGroup

check_delimiter(deviation: int)[source]
tag_header() tuple[source]

Read type of Tag and its length (in dm4 only) and length definition 1:length of tag (in dm4 only) 1:marker %%%% indicating the beginning of a tag 2:definition of length

parse_tags_to_dict(group_name: str, group_dict: dict, root=False)[source]

recursive funcion to scroll through DM file tags structure

make_image_list()[source]

remove thumnail item from dictionary

get_data_array(index: int) tuple[source]

read array associated with an image

read_data(dtype: int)[source]

elemental data piece

read_string(length: int) str[source]

1byte char (DM code 9) seems to be used for tag names only for the strings, array of 2byte symbols (DM code 4) mostly used

struct_types() tuple[source]

read the tuple with types of structure elements (type_0,type_1,…,type_n-1)

read_structure(types: tuple) tuple[source]

read a tuple with different (not necesarily same type) data pieces

read_array(size: int, eltype: int, inserted=None)[source]

read non-image array

get_matadata(index) dict[source]
class qem.dm.write_DM(im_type, im_size, dm_ext, prt)[source]

Bases: object

__init__(im_type, im_size, dm_ext, prt)[source]
init_dict()[source]
get_type(value) str[source]
set_DMvalue(value: int) int[source]

diferent int length for dm3 and dm4

must_tags(dim: int, dimensions: dict, calibration=None, metadata=None) dict[source]

according Bernhard Schaffer these Tags are obligatory for any dm file

write_to_buffer()[source]
break_buffer()[source]
finalize_buffer()[source]
file_header(f_size: int) bytes[source]
group_header(is_sorted: int, n_tags: int, root: bool)[source]
name_header(Ttype, Label)[source]
set_string(TxtLabel: str) bytes[source]

1byte char (DM code:9) for tag labels

tag_header(Ttype, item)[source]
image_tag_header()[source]
tag_end()[source]

this is needed to write the tag length

tag(Ttype: str, item)[source]
group_end(is_broken: bool)[source]
read_temdm_tag(group_dict: dict, name: str, par: bool) bool[source]

remove temdm special tags from dictionary, overwrite the default parameter if neccesary

write_dict(group_dict: dict, root=False)[source]

recursive function to write nested dictionary into binary

qem.gaussian_mixture_model module

qem.gaussian_mixture_model.safe_ln(x)[source]

Natural logarithm function, avoiding division by zero warnings.

Parameters:

x – The value to take the logarithm of.

Returns:

The natural logarithm of x.

class qem.gaussian_mixture_model.GaussianMixtureModel(cross_sections: numpy.ndarray, electron_dose: float | None = None)[source]

Bases: object

Gaussian Mixture Model for quantitative electron microscopy data analysis.

This class implements a GMM for fitting scattering cross-section data, with support for statistical atom counting and various initialization methods.

Variables:
  • cross_sections (np.ndarray) – The scattering cross-section data.

  • electron_dose (float) – The number of electrons per pixel.

  • fit_result (GmmResult) – The result of the GMM fitting.

  • selected_data (np.ndarray) – The selected cross-section data for fitting.

  • data_bounds (np.ndarray) – Min and max values of the selected data.

  • initial_means (np.ndarray) – Initial mean values for GMM components.

  • curve_function – The curve function used for 2D GMM fitting.

  • curve_parameters – Parameters of the curve function.

  • component_range (np.ndarray) – Range of component numbers to test.

__init__(cross_sections: numpy.ndarray, electron_dose: float | None = None)[source]

Initialize Gaussian Mixture Model.

Parameters:
  • cross_sections – Scattering cross-section data array

  • electron_dose – Number of electrons per pixel (for dose-dependent width)

initialize_fitting_conditions(num_components: list[int], data_channels, optimization_metric: str, scoring_methods: list[str], initialization_method: str, convergence_tolerance: float, max_iterations: int, initial_weights, initial_means, initial_widths, step_sizes, constraints: list[str])[source]

Initializes the conditions for the Gaussian Mixture Model.

Parameters:
  • n_component (int or list) – Number of components in the mixture model. If an integer is provided, the range of components will be from 1 to n_component. If a list is provided, the range will be from the first element to the last element of the list.

  • use_scs_channel (int or list) – The channel(s) to be used for the model. If an integer is provided, only that channel will be used. If a list is provided, the channels specified in the list will be used. If None is provided, the first channel will be used by default.

  • metric (str) – The metric to be used for the model.

  • score_method (list) – List of score methods to be used.Available methods: icl: Integrated Completed Likelihood, aic: Akaike Information Criterion, bic: Bayesian Information Criterion, gic: Generalized Information Criterion, clc: Consistent Likelihood Criterion, awe: Akaike’s Weighted Estimate, en: Entropy, nllh: Negative Log-Likelihood.

  • init_method (str) – The initialization method to be used.

  • lim_rate (float) – The rate of convergence for the model.

  • lim_ite (int) – The maximum number of iterations for the model.

  • given_weight (array-like) – The given weights for the model.

  • given_mean (array-like) – The given means for the model.

  • given_width (array-like) – The given widths for the model.

  • fit_step_size (float) – The step size for fitting the model.

  • constraint (str) – The constraint to be applied to the model.

Returns:

None

fit_gaussian_mixture_model(num_components, data_channels=None, optimization_metric='icl', scoring_methods=None, initialization_method='middle', convergence_tolerance=1e-05, max_iterations=100000.0, initial_weights=None, initial_means=None, initial_widths=None, step_sizes=None, constraints=None, use_first_local_minimum=True)[source]

Fits a Gaussian Mixture Model (GMM) to the data.

Parameters:
  • num_components – The number of components in the GMM.

  • data_channels – The channel to use for fitting the GMM.

  • optimization_metric (str) – The metric used for model selection. Default is “icl”.

  • scoring_methods (list) – The scoring method(s) used for model selection. Default is [“icl”].

  • initialization_method (str) – The initialization method for the GMM. Default is “middle”.

  • convergence_tolerance (float) – The convergence threshold for the optimization. Default is 1e-5.

  • max_iterations (float) – The maximum number of iterations for the optimization. Default is 1e5.

  • initial_weights – The initial weights of the GMM components. Default is None.

  • initial_means – The initial means of the GMM components. Default is None.

  • initial_widths – The initial widths of the GMM components. Default is None.

  • step_sizes (list) – The step sizes for fitting the GMM. Default is [1, [1, 1], [1, 1]].

  • constraints (list) – The constraints applied to the GMM. Default is [].

  • use_first_local_minimum (bool) – Whether to use first local minimum instead of global minimum.

Returns:

None

get_optimal_components(method='recommendation')[source]

Get the optimal number of components.

Parameters:

method – Method to determine optimal components - “recommendation”: Use the recommended value (first local minimum) - “global_min”: Use global minimum of scoring metric - “user”: Allow user to choose interactively

Returns:

int – Optimal number of components

import_coordinates(coordinate)[source]
plot_thickness(n_component, show_component=None)[source]
plot_criteria(criteria=None)[source]
plot_histogram(n_component: int, use_dim=None, bin=None)[source]
plot_interactive_gmm_selection(cross_sections, element_name='GMM', save_results=False, interactive_selection=True)[source]

Plot GMM fitting results with interactive component selection and colored areas.

Parameters:
  • cross_sections – Cross-section data used for fitting

  • element_name – Name of the element or dataset for labeling

  • save_results – Whether to save the plot

  • interactive_selection – Whether to allow interactive component selection

Returns:

int – Selected number of components

apply_parameter_constraints(weights, means, widths)[source]

Apply constraints to GMM parameters.

Parameters:
  • weights – Component weights

  • means – Component means

  • widths – Component widths/covariances

Returns:

tuple – (constrained_weights, constrained_means, constrained_widths)

class qem.gaussian_mixture_model.GmmResult(weight: list, mean: list, width: list, score: dict, ndim: int, val: numpy.ndarray, curve=None)[source]

Bases: object

__init__(weight: list, mean: list, width: list, score: dict, ndim: int, val: numpy.ndarray, curve=None)[source]

Initialize a GaussianMixtureModel result.

Parameters:
  • weight (list) – The weights of the Gaussian components.

  • mean (list) – The means of the Gaussian components.

  • width (list) – The widths of the Gaussian components.

  • score (dict) – A dictionary containing scores for each component.

  • ndim (int) – The number of dimensions of the data.

  • val (np.ndarray) – The input data values.

  • curve (Optional) – An optional curve parameter.

Returns:

None

idxComponentOfScs(id)[source]

Returns the index of the component in the Gaussian Mixture Model (GMM) that the given id corresponds to.

Parameters: id (int): The id of the scs (sub-component set).

Returns: int: The index of the component in the GMM.

idxScsOfComponent(id)[source]

Returns the indices of the scs belonging to a specific component.

Parameters: id (int): The component ID.

Returns: list: A list of indices representing the samples belonging to the specified component.

class qem.gaussian_mixture_model.GaussianComponents(weights, means, variances, data_values, electron_dose=None)[source]

Bases: object

Represents individual Gaussian components in a mixture model.

This class handles the expectation and maximization steps for individual Gaussian components during GMM fitting.

__init__(weights, means, variances, data_values, electron_dose=None)[source]

Initialize Gaussian components.

Parameters:
  • weights – Component weights

  • means – Component means

  • variances – Component variances

  • data_values – Observed data points

  • electron_dose – Electron dose for dose-dependent width modeling

property responsibilities

Get component responsibilities (tau values).

pre_maximization_step(step_sizes, constraints)[source]

Perform preliminary M-step operations.

Parameters:
  • step_sizes – Step sizes for parameter updates

  • constraints – List of constraint names to apply

maximization_step(step_sizes, constraints)[source]

Perform M-step: update all parameters.

Parameters:
  • step_sizes – Step sizes for parameter updates

  • constraints – List of constraint names to apply

static rectifier(val)[source]
static rev_rectifier(val)[source]