rheedium.types

JAX PyTree data structures for crystallographic and RHEED simulation data.

Custom types and data structures for RHEED simulation.

Extended Summary

This module defines JAX-compatible data structures for representing crystal structures, RHEED patterns, and other simulation data. All types are PyTrees that support JAX transformations and automatic differentiation.

Routine Listings

CrystalStructure

JAX-compatible crystal structure with fractional and Cartesian coordinates.

DetectorGeometry

Configuration for RHEED detector geometry (tilt, curvature, offsets).

ElectronBeam

Complete specification of an electron beam for RHEED simulation.

EwaldData

Angle-independent Ewald sphere data for RHEED simulation.

KirklandParameters

Structured Kirkland coefficients for one element.

OrientationDistribution

Probability distribution over azimuthal domain orientations.

PotentialSlices

JAX-compatible data structure for representing multislice potential data.

RHEEDImage

Container for RHEED image data with pixel coordinates and intensity values.

RHEEDPattern

Container for RHEED diffraction pattern data with detector points and intensities.

SlicedCrystal

JAX-compatible crystal structure sliced for multislice simulation.

SizeDistribution

Probability distribution over coherent domain sizes.

SurfaceConfig

Configuration for surface atom identification method and parameters.

XYZData

A PyTree for XYZ file data with atomic positions and metadata.

create_crystal_structure()

Factory function to create CrystalStructure instances.

create_electron_beam()

Factory function to create ElectronBeam instances.

create_ewald_data()

Factory function to create EwaldData instances.

create_orientation_distribution()

Canonical factory for orientation distributions.

create_discrete_orientation()

Create a sharp rotational-variant distribution.

create_gaussian_orientation()

Create a Gaussian mosaic orientation distribution.

create_kirkland_parameters()

Factory function to create KirklandParameters instances.

create_lognormal_size()

Create a lognormal domain-size distribution.

create_mixed_orientation()

Create discrete orientation variants with mosaic broadening.

create_potential_slices()

Factory function to create PotentialSlices instances.

create_rheed_image()

Factory function to create RHEEDImage instances.

create_rheed_pattern()

Factory function to create RHEEDPattern instances.

create_sliced_crystal()

Factory function to create SlicedCrystal instances.

create_xyz_data()

Factory function to create XYZData instances.

discretize_orientation()

Convert an orientation distribution to quadrature samples.

discretize_orientation_static()

Python-branching orientation discretization for non-JIT use.

identify_surface_atoms()

Identify surface atoms using configurable methods.

integrate_over_orientation()

Simulate and incoherently average over orientation samples.

float_jax_image

Type alias for float-valued 2D JAX image arrays.

float_np_image

Type alias for float-valued 2D numpy image arrays.

int_jax_image

Type alias for integer-valued 2D JAX image arrays.

int_np_image

Type alias for integer-valued 2D numpy image arrays.

non_jax_number

Union type for non-JAX numeric values (int or float).

scalar_bool

Union type for scalar boolean values (bool or JAX scalar array).

scalar_float

Union type for scalar float values (float or JAX scalar array).

scalar_int

Union type for scalar integer values (int or JAX scalar array).

scalar_num

Union type for scalar numeric values (int, float, or JAX scalar array).

AMU_TO_KG

Atomic mass unit to kg conversion factor.

BOLTZMANN_CONSTANT_JK

Boltzmann constant in J/K.

ELECTRON_MASS_KG

Electron rest mass in kg.

ELEMENTARY_CHARGE_C

Elementary charge in C.

H_OVER_SQRT_2ME_ANG_VSQRT

Electron wavelength prefactor h / sqrt(2 m_e e) in Ang V^0.5.

HBAR_JS

Reduced Planck constant in J s.

M2_TO_ANG2

Square metres to square angstroms conversion factor.

PLANCK_CONSTANT_JS

Planck constant h in J s.

RELATIVISTIC_COEFF_PER_V

Relativistic correction coefficient e / (2 m_e c^2) in 1/V.

SPEED_OF_LIGHT_MS

Speed of light in vacuum in m/s.

Notes

Every PyTree has a corresponding factory function to create the instance. This is because beartype does not support type checking of dataclasses.

class rheedium.types.ElectronBeam(energy_kev: float | Float[Array, ''] = 20.0, energy_spread_ev: float | Float[Array, ''] = 0.5, angular_divergence_mrad: float | Float[Array, ''] = 0.5, coherence_length_transverse_angstrom: float | Float[Array, ''] = 500.0, coherence_length_longitudinal_angstrom: float | Float[Array, ''] = 1000.0, spot_size_um: Float[Array, '2'] = Array([100., 50.], dtype=float64))[source]

Bases: NamedTuple

Complete specification of an electron beam for RHEED simulation.

This PyTree captures all physical parameters of the electron source needed for instrument-broadened RHEED pattern simulation. Typical RHEED guns have angular divergence 0.1–1 mrad, energy spread 0.1–1 eV, and transverse coherence lengths 100–1000 Angstroms.

energy_kev

Nominal accelerating voltage in keV. Range: 5–100 keV. Default: 20.0

Type:

float

energy_spread_ev

1-sigma energy spread in eV. Typical: 0.1–1.0 eV. Controls longitudinal coherence and streak position variation. Default: 0.5

Type:

float

angular_divergence_mrad

1-sigma angular divergence in milliradians. Typical: 0.1–1.0 mrad. Controls transverse coherence and streak width. Default: 0.5

Type:

float

coherence_length_transverse_angstrom

Transverse coherence length in Angstroms. Typical: 100–1000. Limits the angular range over which diffraction is coherent. Default: 500.0

Type:

float

coherence_length_longitudinal_angstrom

Longitudinal coherence length in Angstroms. Related to energy spread by L_l = lambda^2 / delta_lambda. Default: 1000.0

Type:

float

spot_size_um

Beam footprint [width, height] on surface in micrometers. RHEED illuminates mm-scale areas; this sets the incoherent averaging domain. Default: [100.0, 50.0]

Type:

Float[Array, "2"]

Notes

This class is registered as a PyTree node, making it compatible with JAX transformations like jit, grad, and vmap. All continuous parameters (energy, spread, divergence, coherence lengths) are differentiable. The spot_size_um is also differentiable but rarely optimized in practice.

Examples

>>> import jax.numpy as jnp
>>> import rheedium as rh
>>>
>>> beam = rh.types.create_electron_beam(
...     energy_kev=15.0,
...     angular_divergence_mrad=0.3,
...     energy_spread_ev=0.2,
... )
energy_kev: float | Float[Array, '']

Alias for field number 0

energy_spread_ev: float | Float[Array, '']

Alias for field number 1

angular_divergence_mrad: float | Float[Array, '']

Alias for field number 2

coherence_length_transverse_angstrom: float | Float[Array, '']

Alias for field number 3

coherence_length_longitudinal_angstrom: float | Float[Array, '']

Alias for field number 4

spot_size_um: Float[Array, '2']

Alias for field number 5

rheedium.types.create_electron_beam(energy_kev: float | Float[Array, ''] = 20.0, energy_spread_ev: float | Float[Array, ''] = 0.5, angular_divergence_mrad: float | Float[Array, ''] = 0.5, coherence_length_transverse_angstrom: float | Float[Array, ''] = 500.0, coherence_length_longitudinal_angstrom: float | Float[Array, ''] = 1000.0, spot_size_um: Float[Array, '2'] = jnp.array([100.0, 50.0])) ElectronBeam[source]

Create an ElectronBeam instance with data validation.

Parameters:
  • energy_kev (Union[float, Float[Array, '']], default: 20.0) – Nominal accelerating voltage in keV. Must be in [5, 100]. Default: 20.0

  • energy_spread_ev (Union[float, Float[Array, '']], default: 0.5) – 1-sigma energy spread in eV. Must be non-negative. Default: 0.5

  • angular_divergence_mrad (Union[float, Float[Array, '']], default: 0.5) – 1-sigma angular divergence in milliradians. Must be non-negative. Default: 0.5

  • coherence_length_transverse_angstrom (Union[float, Float[Array, '']], default: 500.0) – Transverse coherence length in Angstroms. Must be positive. Default: 500.0

  • coherence_length_longitudinal_angstrom (Union[float, Float[Array, '']], default: 1000.0) – Longitudinal coherence length in Angstroms. Must be positive. Default: 1000.0

  • spot_size_um (Float[Array, '2'], default: jnp.array([100.0, 50.0])) – Beam footprint [width, height] in micrometers. Both components must be positive. Default: [100.0, 50.0]

Returns:

validated_beam – Validated ElectronBeam instance.

Return type:

ElectronBeam

Notes

  1. Cast all inputs to float64 JAX arrays.

  2. Validate energy_kev is in [5, 100] keV.

  3. Validate energy_spread_ev >= 0.

  4. Validate angular_divergence_mrad >= 0.

  5. Validate coherence lengths are positive.

  6. Validate spot_size_um components are positive.

  7. Return constructed ElectronBeam.

Examples

>>> import rheedium as rh
>>>
>>> beam = rh.types.create_electron_beam(energy_kev=15.0)
>>> beam.energy_kev
Array(15., dtype=float64)
class rheedium.types.CrystalStructure(frac_positions: Num[Array, 'N 4'], cart_positions: Num[Array, 'N 4'], cell_lengths: Num[Array, '3'], cell_angles: Num[Array, '3'])[source]

Bases: NamedTuple

JAX-compatible Pytree with fractional and Cartesian coordinates.

This PyTree represents a crystal structure containing atomic positions in both fractional and Cartesian coordinate systems, along with unit cell parameters. It’s designed for efficient crystal structure calculations and electron diffraction simulations.

frac_positions

Array of shape (n_atoms, 4) containing atomic positions in fractional coordinates. Each row contains [x, y, z, atomic_number] where x, y, z are fractional coordinates in the unit cell (range [0,1]) and atomic_number is the integer atomic number (Z) of the element.

Type:

Num[Array, "N 4"]

cart_positions

Array of shape (n_atoms, 4) containing atomic positions in Cartesian coordinates. Each row contains [x, y, z, atomic_number] where x, y, z are Cartesian coordinates in Ångstroms and atomic_number is the integer atomic number (Z).

Type:

Num[Array, "N 4"]

cell_lengths

Unit cell lengths [a, b, c] in Ångstroms.

Type:

Num[Array, "3"]

cell_angles

Unit cell angles [α, β, γ] in degrees, where α is the angle between b and c, β is the angle between a and c, and γ is the angle between a and b.

Type:

Num[Array, "3"]

This class is registered as a PyTree node, making it compatible with JAX
transformations like jit, grad, and vmap. All data is immutable and stored
in JAX arrays for efficient computation.

Examples

>>> import jax.numpy as jnp
>>> import rheedium as rh
>>>
>>> # Create crystal structure for simple cubic lattice
>>> frac_pos = jnp.array([[0.0, 0.0, 0.0, 6]])  # Carbon atom at origin
>>> cart_pos = jnp.array([[0.0, 0.0, 0.0, 6]])  # Same in Cartesian
>>> cell_lengths = jnp.array([3.57, 3.57, 3.57])  # Diamond lattice
>>> cell_angles = jnp.array([90.0, 90.0, 90.0])  # Cubic angles
>>> crystal = rh.types.create_crystal_structure(
...     frac_positions=frac_pos,
...     cart_positions=cart_pos,
...     cell_lengths=cell_lengths,
...     cell_angles=cell_angles,
... )
class rheedium.types.EwaldData(wavelength_ang: Float[Array, ''], k_magnitude: Float[Array, ''], sphere_radius: Float[Array, ''], recip_vectors: Float[Array, '3 3'], hkl_grid: Int[Array, 'N 3'], g_vectors: Float[Array, 'N 3'], g_magnitudes: Float[Array, 'N'], structure_factors: Complex[Array, 'N'], intensities: Float[Array, 'N'])[source]

Bases: NamedTuple

Angle-independent Ewald sphere data for RHEED simulation.

This PyTree contains pre-computed reciprocal lattice geometry and structure factors that depend only on crystal structure and beam voltage, not on beam orientation angles. This enables efficient reuse when scanning beam azimuth or incidence angle.

wavelength_ang

Relativistic electron wavelength in Ångstroms.

Type:

Float[Array, ""]

k_magnitude

Magnitude of electron wavevector \(|k| = 2\pi/\lambda\) in 1/Ångstroms.

Type:

Float[Array, ""]

sphere_radius

Ewald sphere radius in 1/Ångstroms (equals k_magnitude).

Type:

Float[Array, ""]

recip_vectors

Reciprocal lattice basis vectors [b₁, b₂, b₃] as rows.

Type:

Float[Array, "3 3"]

hkl_grid

Miller indices (h, k, l) for all reciprocal lattice points.

Type:

Int[Array, "N 3"]

g_vectors

Reciprocal lattice vectors G in 1/Ångstroms.

Type:

Float[Array, "N 3"]

g_magnitudes

Magnitudes \(|G|\) for each reciprocal lattice vector.

Type:

Float[Array, "N"]

structure_factors

Complex structure factors F(G) for each reciprocal lattice point.

Type:

Complex[Array, "N"]

intensities

Kinematic diffraction intensities \(I(G) = |F(G)|^2\).

Type:

Float[Array, "N"]

Notes

This class is registered as a PyTree node for JAX compatibility. The structure factors include Kirkland atomic form factors and Debye-Waller thermal damping.

Examples

>>> import rheedium as rh
>>> crystal = rh.inout.parse_cif("MgO.cif")
>>> ewald = rh.ucell.build_ewald_data(
...     crystal=crystal,
...     voltage_kv=15.0,
...     hmax=3,
...     kmax=3,
...     lmax=2,
... )
>>> print(f"Sphere radius: {ewald.sphere_radius:.2f} 1/Å")
class rheedium.types.KirklandParameters(lorentzian_amplitudes: Float[Array, '3'], lorentzian_scales: Float[Array, '3'], gaussian_amplitudes: Float[Array, '3'], gaussian_scales: Float[Array, '3'])[source]

Bases: NamedTuple

Structured Kirkland coefficients for one element.

This PyTree holds the three Lorentzian and three Gaussian amplitude/scale pairs from the Kirkland parameterization of electron scattering factors.

lorentzian_amplitudes

Lorentzian amplitude coefficients (a_1, a_2, a_3).

Type:

Float[Array, "3"]

lorentzian_scales

Lorentzian scale coefficients (b_1, b_2, b_3).

Type:

Float[Array, "3"]

gaussian_amplitudes

Gaussian amplitude coefficients (c_1, c_2, c_3).

Type:

Float[Array, "3"]

gaussian_scales

Gaussian scale coefficients (d_1, d_2, d_3).

Type:

Float[Array, "3"]

This class is registered as a PyTree node, making it compatible
with JAX transformations like jit, grad, and vmap. All fields are
JAX arrays and are stored as leaf nodes.
lorentzian_amplitudes: Float[Array, '3']

Alias for field number 0

lorentzian_scales: Float[Array, '3']

Alias for field number 1

gaussian_amplitudes: Float[Array, '3']

Alias for field number 2

gaussian_scales: Float[Array, '3']

Alias for field number 3

class rheedium.types.PotentialSlices(slices: Float[Array, 'n_slices height width'], slice_thickness: float | Float[Array, ''], x_calibration: float | Float[Array, ''], y_calibration: float | Float[Array, ''])[source]

Bases: NamedTuple

JAX-compatible multislice potential data for electron beam propagation.

This PyTree represents discretized potential data used in multislice electron diffraction calculations. It contains 3D potential slices with associated calibration information for accurate physical modeling.

slices

3D array containing projected-potential data for each slice. First dimension indexes slices, second and third dimensions are spatial coordinates. Units: Volt-Angstrom. These are projected slice potentials, not volumetric potentials.

Type:

Float[Array, "n_slices height width"]

slice_thickness

Thickness of each slice in Ångstroms. Determines the z-spacing between consecutive slices.

Type:

float

x_calibration

Real space calibration in the x-direction in Ångstroms per pixel. Converts pixel coordinates to physical distances.

Type:

float

y_calibration

Real space calibration in the y-direction in Ångstroms per pixel. Converts pixel coordinates to physical distances.

Type:

float

This class is registered as a PyTree node, making it compatible with JAX
transformations like jit, grad, and vmap. The calibration metadata is
preserved as auxiliary data while slice data can be efficiently processed.
All data is immutable for functional programming patterns.

Examples

>>> import jax.numpy as jnp
>>> import rheedium as rh
>>>
>>> # Create potential slices for multislice calculation
>>> slices_data = jnp.zeros((10, 64, 64))  # 10 slices, 64x64 each
>>> potential_slices = rh.types.create_potential_slices(
...     slices=slices_data,
...     slice_thickness=2.0,  # 2 Å per slice
...     x_calibration=0.1,  # 0.1 Å per pixel in x
...     y_calibration=0.1,  # 0.1 Å per pixel in y
... )
class rheedium.types.XYZData(positions: Float[Array, 'N 3'], atomic_numbers: Int[Array, 'N'], lattice: Float[Array, '3 3'] | None, stress: Float[Array, '3 3'] | None, energy: Float[Array, ''] | None, properties: list[dict[str, str | int]] | None, comment: str | None)[source]

Bases: NamedTuple

JAX-compatible representation of parsed XYZ file data.

This PyTree represents a complete XYZ file structure with atomic positions, optional lattice information, and metadata. It’s designed for geometry parsing, simulation preparation, and machine learning data processing.

positions

Cartesian atomic positions in Ångstroms. Shape (N, 3) where N is the number of atoms.

Type:

Float[Array, "N 3"]

atomic_numbers

Atomic numbers (Z) corresponding to each atom. Shape (N,) with integer values.

Type:

Int[Array, "N"]

lattice

Lattice vectors in Ångstroms if present in the XYZ file, otherwise None. Shape (3, 3) matrix where each row is a lattice vector.

Type:

Optional[Float[Array, "3 3"]]

stress

Symmetric stress tensor if present in the metadata, otherwise None. Shape (3, 3) matrix with stress components.

Type:

Optional[Float[Array, "3 3"]]

energy

Total energy in eV if present in the metadata, otherwise None. Scalar value.

Type:

Optional[scalar_float]

properties

List of per-atom properties described in the metadata, otherwise None.

Type:

Optional[List[Dict[str, Union[str, int]]]]

comment

The raw comment line from the XYZ file header, otherwise None.

Type:

Optional[str]

This class is registered as a PyTree node, making it compatible with JAX
transformations like jit, grad, and vmap. Numerical data is stored as
JAX arrays while metadata is preserved as auxiliary data. All data is
immutable for functional programming patterns.

Examples

>>> import jax.numpy as jnp
>>> import rheedium as rh
>>>
>>> # Create XYZ data for water molecule
>>> positions = jnp.array(
...     [
...         [0.0, 0.0, 0.0],
...         [0.76, 0.59, 0.0],
...         [-0.76, 0.59, 0.0],
...     ]
... )
>>> atomic_numbers = jnp.array([8, 1, 1])  # O, H, H
>>> xyz_data = rh.types.create_xyz_data(
...     positions=positions,
...     atomic_numbers=atomic_numbers,
...     comment="Water molecule",
... )
rheedium.types.create_crystal_structure(frac_positions: Num[Array, '... 4'], cart_positions: Num[Array, '... 4'], cell_lengths: Num[Array, '3'], cell_angles: Num[Array, '3']) CrystalStructure[source]

Create a CrystalStructure PyTree with data validation.

Parameters:
  • frac_positions ( 4']) – Array of shape (n_atoms, 4) containing atomic positions in fractional coordinates.

  • cart_positions ( 4']) – Array of shape (n_atoms, 4) containing atomic positions in Cartesian coordinates.

  • cell_lengths (Num[Array, '3']) – Unit cell lengths [a, b, c] in Ångstroms.

  • cell_angles (Num[Array, '3']) – Unit cell angles [α, β, γ] in degrees.

Returns:

validated_crystal_structure – A validated CrystalStructure instance.

Return type:

CrystalStructure

Notes

  • Convert all inputs to JAX arrays using jnp.asarray.

  • Validate shapes of frac_positions, cart_positions, cell_lengths, and cell_angles.

  • Verify number of atoms matches between frac and cart positions.

  • Verify atomic numbers match between frac and cart positions.

  • Ensure cell lengths are positive.

  • Ensure cell angles are between 0 and 180 degrees.

  • Create and return CrystalStructure instance with validated data.

rheedium.types.create_ewald_data(wavelength_ang: Float[Array, ''], k_magnitude: Float[Array, ''], sphere_radius: Float[Array, ''], recip_vectors: Float[Array, '3 3'], hkl_grid: Int[Array, 'N 3'], g_vectors: Float[Array, 'N 3'], g_magnitudes: Float[Array, 'N'], structure_factors: Complex[Array, 'N'], intensities: Float[Array, 'N']) EwaldData[source]

Create an EwaldData PyTree with validation.

Parameters:
  • wavelength_ang (Float[Array, '']) – Electron wavelength in Ångstroms.

  • k_magnitude (Float[Array, '']) – Wavevector magnitude \(|k| = 2\pi/\lambda\) in 1/Ångstroms.

  • sphere_radius (Float[Array, '']) – Ewald sphere radius in 1/Ångstroms.

  • recip_vectors (Float[Array, '3 3']) – Reciprocal lattice basis vectors as 3×3 matrix.

  • hkl_grid (Int[Array, 'N 3']) – Miller indices for N reciprocal lattice points.

  • g_vectors (Float[Array, 'N 3']) – Reciprocal lattice vectors for N points.

  • g_magnitudes (Float[Array, 'N']) – Magnitudes of N reciprocal vectors.

  • structure_factors (Complex[Array, 'N']) – Complex structure factors for N points.

  • intensities (Float[Array, 'N']) – Diffraction intensities for N points.

Returns:

ewald_data – Validated EwaldData PyTree instance.

Return type:

EwaldData

Notes

  1. Convert dtypes – float64 for real-valued fields, int32 for Miller indices, complex128 for structure factors.

  2. Validate scalars – Wavelength, k_magnitude, and sphere_radius must be positive.

  3. Validate shapes – recip_vectors is (3, 3); hkl_grid, g_vectors, g_magnitudes, structure_factors, and intensities share the same leading dimension N.

  4. Validate values – Intensities must be non-negative; all real-valued arrays must be finite.

  5. Create instance – Assemble validated arrays into EwaldData PyTree.

rheedium.types.create_kirkland_parameters(lorentzian_amplitudes: Float[Array, '3'], lorentzian_scales: Float[Array, '3'], gaussian_amplitudes: Float[Array, '3'], gaussian_scales: Float[Array, '3']) KirklandParameters[source]

Create a KirklandParameters PyTree with data validation.

Parameters:
  • lorentzian_amplitudes (Float[Array, '3']) – Lorentzian amplitude coefficients (a_1, a_2, a_3).

  • lorentzian_scales (Float[Array, '3']) – Lorentzian scale coefficients (b_1, b_2, b_3).

  • gaussian_amplitudes (Float[Array, '3']) – Gaussian amplitude coefficients (c_1, c_2, c_3).

  • gaussian_scales (Float[Array, '3']) – Gaussian scale coefficients (d_1, d_2, d_3).

Returns:

validated_kirkland_parameters – Validated KirklandParameters instance.

Return type:

KirklandParameters

Notes

  1. Convert inputs to JAX float64 arrays.

  2. Validate all arrays have exactly 3 elements.

  3. Ensure all values are finite.

  4. Create and return KirklandParameters instance.

rheedium.types.create_potential_slices(slices: Float[Array, 'n_slices height width'], slice_thickness: float | Float[Array, ''], x_calibration: float | Float[Array, ''], y_calibration: float | Float[Array, '']) PotentialSlices[source]

Create a PotentialSlices PyTree with data validation.

Parameters:
  • slices (Float[Array, 'n_slices height width']) – 3D array containing projected-potential data in Volt-Angstrom for each slice.

  • slice_thickness (Union[float, Float[Array, '']]) – Thickness of each slice in Ångstroms.

  • x_calibration (Union[float, Float[Array, '']]) – Real space calibration in x-direction in Ångstroms per pixel.

  • y_calibration (Union[float, Float[Array, '']]) – Real space calibration in y-direction in Ångstroms per pixel.

Returns:

validated_potential_slices – Validated PotentialSlices instance.

Return type:

PotentialSlices

Notes

  1. Convert inputs to JAX arrays with appropriate dtypes.

  2. Validate slice array is 3D.

  3. Ensure slice thickness is positive.

  4. Ensure calibrations are positive.

  5. Check that all slice data is finite.

  6. Create and return PotentialSlices instance.

rheedium.types.create_xyz_data(positions: Float[Array, 'N 3'], atomic_numbers: Int[Array, 'N'], lattice: Float[Array, '3 3'] | None = None, stress: Float[Array, '3 3'] | None = None, energy: float | Float[Array, ''] | None = None, properties: list[dict[str, str | int]] | None = None, comment: str | None = None) XYZData[source]

Create a XYZData PyTree with runtime validation.

Parameters:
  • positions (Float[Array, 'N 3']) – Cartesian positions in Ångstroms.

  • atomic_numbers (Int[Array, 'N']) – Atomic numbers (Z) for each atom.

  • lattice (Optional[Float[Array, '3 3']], default: None) – Lattice vectors (if any).

  • stress (Optional[Float[Array, '3 3']], default: None) – Stress tensor (if any).

  • energy (Union[float, Float[Array, ''], None], default: None) – Total energy (if any).

  • properties (Optional[list[dict[str, Union[str, int]]]], default: None) – Per-atom metadata.

  • comment (Optional[str], default: None) – Original XYZ comment line.

Returns:

validated_xyz_data – Validated PyTree structure for XYZ file contents.

Return type:

XYZData

Notes

  • Convert required inputs to JAX arrays with appropriate dtypes: positions to float64, atomic_numbers to int32, lattice/stress/energy to float64 if provided.

  • Execute shape validation checks: verify positions has shape (N, 3) and atomic_numbers has shape (N,).

  • Execute value validation checks: ensure all position values are finite and atomic numbers are non-negative.

  • Execute optional matrix validation checks: for lattice and stress tensors verify shape is (3, 3) and all values are finite.

  • If all validations pass, create and return XYZData instance.

  • If any validation fails, raise ValueError with descriptive error message.

rheedium.types.float_jax_image

alias of Float[Array, 'H W']

rheedium.types.float_np_image

alias of Float[ndarray, 'H W']

rheedium.types.int_jax_image

alias of Integer[Array, 'H W']

rheedium.types.int_np_image

alias of Integer[ndarray, 'H W']

class rheedium.types.OrientationDistribution(discrete_angles_deg: Float[Array, 'M'], discrete_weights: Float[Array, 'M'], mosaic_fwhm_deg: Float[Array, ''], distribution_id: str | None = None)[source]

Bases: NamedTuple

Probability distribution over domain azimuthal orientations.

Extended Summary

Models the statistical distribution of in-plane domain rotations on the illuminated surface. Supports discrete variants (e.g., rotational twins), continuous mosaic spread, or combinations.

The total intensity is computed as an incoherent sum:

\[\begin{split}I(G) = \\int P(\\theta) \\, |F(G, \\theta)|^2 \\, d\\theta\end{split}\]

For discrete variants this becomes:

\[\begin{split}I(G) = \\sum_i w_i \\, |F(G, \\theta_i)|^2\end{split}\]
discrete_angles_deg

Azimuthal rotation angles for discrete variants in degrees. For continuous-only distributions, use a single-element array with the center angle.

Type:

Float[Array, "M"]

discrete_weights

Probability weights for each discrete angle. Normalized internally to sum to 1.0. Must be non-negative.

Type:

Float[Array, "M"]

mosaic_fwhm_deg

Full-width at half-maximum of Gaussian mosaic spread around each discrete angle, in degrees. Set to 0.0 for sharp discrete variants with no mosaic broadening.

Type:

Float[Array, ""]

distribution_id

Optional identifier for the distribution (e.g., “sqrt13_R33.7”).

Type:

Optional[str]

Notes

The distribution is parameterized to handle three common cases:

  1. Discrete variants only (mosaic_fwhm_deg = 0): Sharp peaks at specified angles. Example: √13×√13 R±33.7° reconstruction with two domains.

  2. Continuous mosaic only (single angle, mosaic_fwhm_deg > 0): Gaussian spread around a central orientation. Models strain relaxation or polycrystalline texture.

  3. Mixed (multiple angles, mosaic_fwhm_deg > 0): Each discrete variant is broadened by the mosaic spread. Most realistic for real surfaces.

Examples

>>> # Two rotational variants at ±33.7°
>>> dist = OrientationDistribution(
...     discrete_angles_deg=jnp.array([33.7, -33.7]),
...     discrete_weights=jnp.array([0.5, 0.5]),
...     mosaic_fwhm_deg=jnp.array(0.0),
... )
>>> # Gaussian mosaic spread of 0.5° FWHM
>>> dist = OrientationDistribution(
...     discrete_angles_deg=jnp.array([0.0]),
...     discrete_weights=jnp.array([1.0]),
...     mosaic_fwhm_deg=jnp.array(0.5),
... )
discrete_angles_deg: Float[Array, 'M']

Alias for field number 0

discrete_weights: Float[Array, 'M']

Alias for field number 1

mosaic_fwhm_deg: Float[Array, '']

Alias for field number 2

distribution_id: str | None

Alias for field number 3

class rheedium.types.SizeDistribution(distribution_type: str, mean_ang: Float[Array, ''], sigma_ang: Float[Array, ''], min_size_ang: Float[Array, ''], max_size_ang: Float[Array, ''])[source]

Bases: NamedTuple

Probability distribution over coherent domain sizes.

Extended Summary

Models the statistical distribution of lateral coherent domain sizes on the illuminated surface. Domain size determines rod broadening via σ_rod = 2π / (L × √(2π)).

distribution_type

Type of distribution: “lognormal”, “gaussian”, “exponential”, “delta”. Lognormal is most physical for nucleation/coalescence.

Type:

str

mean_ang

Mean domain size in Ångstroms.

Type:

Float[Array, ""]

sigma_ang

Standard deviation in Ångstroms. For lognormal, this is the underlying normal distribution’s σ.

Type:

Float[Array, ""]

min_size_ang

Minimum size cutoff in Ångstroms. Avoids unphysical small domains. Typical: 5-20 Å.

Type:

Float[Array, ""]

max_size_ang

Maximum size cutoff in Ångstroms. Computational truncation. Typical: 500-2000 Å.

Type:

Float[Array, ""]

Notes

The distribution affects RHEED patterns through rod broadening: smaller domains → broader rods → more diffuse streaks.

For “delta” distribution, all domains have exactly mean_ang size.

distribution_type: str

Alias for field number 0

mean_ang: Float[Array, '']

Alias for field number 1

sigma_ang: Float[Array, '']

Alias for field number 2

min_size_ang: Float[Array, '']

Alias for field number 3

max_size_ang: Float[Array, '']

Alias for field number 4

rheedium.types.create_discrete_orientation(angles_deg: Float[Array, 'M'], weights: Float[Array, 'M'] | None = None, distribution_id: str | None = None) OrientationDistribution[source]

Create discrete orientation distribution for rotational variants.

Parameters:
  • angles_deg (Float[Array, 'M']) – Rotation angles for each variant in degrees.

  • weights (Optional[Float[Array, 'M']], default: None) – Probability weights. Default: equal weights (1/M each).

  • distribution_id (Optional[str], default: None) – Identifier for the distribution.

Returns:

dist – Discrete orientation distribution with no mosaic spread.

Return type:

OrientationDistribution

Examples

>>> # √13×√13 R±33.7° reconstruction
>>> dist = create_discrete_orientation(
...     angles_deg=jnp.array([33.7, -33.7]),
...     weights=jnp.array([0.5, 0.5]),
...     distribution_id="sqrt13_R33.7",
... )
>>> # 4-fold symmetric variants
>>> dist = create_discrete_orientation(
...     angles_deg=jnp.array([0.0, 90.0, 180.0, 270.0]),
... )
rheedium.types.create_gaussian_orientation(center_deg: float | Float[Array, ''] = 0.0, fwhm_deg: float | Float[Array, ''] = 0.5, distribution_id: str | None = None) OrientationDistribution[source]

Create Gaussian mosaic spread orientation distribution.

Parameters:
  • center_deg (Union[float, Float[Array, '']], default: 0.0) – Center of the distribution in degrees. Default: 0.0

  • fwhm_deg (Union[float, Float[Array, '']], default: 0.5) – Full-width at half-maximum in degrees. Default: 0.5

  • distribution_id (Optional[str], default: None) – Identifier for the distribution.

Returns:

dist – Continuous Gaussian orientation distribution.

Return type:

OrientationDistribution

Notes

FWHM relates to Gaussian σ by: FWHM = 2√(2 ln 2) × σ ≈ 2.355 σ

rheedium.types.create_lognormal_size(mean_ang: float | Float[Array, ''] = 100.0, sigma_ang: float | Float[Array, ''] = 30.0, min_size_ang: float | Float[Array, ''] = 10.0, max_size_ang: float | Float[Array, ''] = 500.0) SizeDistribution[source]

Create lognormal domain size distribution.

Parameters:
  • mean_ang (Union[float, Float[Array, '']], default: 100.0) – Mean domain size in Ångstroms. Default: 100.0

  • sigma_ang (Union[float, Float[Array, '']], default: 30.0) – Standard deviation in Ångstroms. Default: 30.0

  • min_size_ang (Union[float, Float[Array, '']], default: 10.0) – Minimum size cutoff. Default: 10.0 Å

  • max_size_ang (Union[float, Float[Array, '']], default: 500.0) – Maximum size cutoff. Default: 500.0 Å

Returns:

dist – Lognormal size distribution.

Return type:

SizeDistribution

Notes

Lognormal is most physical for domain sizes arising from nucleation and coalescence processes. The mode (peak) of the distribution is at exp(μ - σ²) where μ, σ are the underlying normal parameters.

rheedium.types.create_mixed_orientation(angles_deg: Float[Array, 'M'], weights: Float[Array, 'M'] | None = None, mosaic_fwhm_deg: float | Float[Array, ''] = 0.2, distribution_id: str | None = None) OrientationDistribution[source]

Create mixed distribution with discrete variants and mosaic spread.

Parameters:
  • angles_deg (Float[Array, 'M']) – Rotation angles for discrete variants in degrees.

  • weights (Optional[Float[Array, 'M']], default: None) – Probability weights for variants. Default: equal weights.

  • mosaic_fwhm_deg (Union[float, Float[Array, '']], default: 0.2) – Mosaic FWHM around each variant in degrees. Default: 0.2

  • distribution_id (Optional[str], default: None) – Identifier for the distribution.

Returns:

dist – Mixed discrete + continuous orientation distribution.

Return type:

OrientationDistribution

Notes

Each discrete variant peak is broadened by a Gaussian with the specified FWHM. This is the most realistic model for real surfaces.

rheedium.types.create_orientation_distribution(angles_deg: Float[Array, 'M'], weights: Float[Array, 'M'] | None = None, mosaic_fwhm_deg: float | Float[Array, ''] = 0.0, distribution_id: str | None = None) OrientationDistribution[source]

Create an OrientationDistribution with normalized JAX arrays.

Parameters:
  • angles_deg (Float[Array, 'M']) – Rotation angles for each supported orientation in degrees.

  • weights (Optional[Float[Array, 'M']], default: None) – Probability weights for each angle. Default: equal weights.

  • mosaic_fwhm_deg (Union[float, Float[Array, '']], default: 0.0) – Gaussian mosaic broadening FWHM in degrees. Negative values are clamped to 0.0. Default: 0.0

  • distribution_id (Optional[str], default: None) – Identifier for the distribution.

Returns:

dist – Orientation distribution with normalized weights and a non-negative mosaic width.

Return type:

OrientationDistribution

rheedium.types.discretize_orientation(dist: OrientationDistribution, n_mosaic_points: int | Integer[Array, ''] = 7, n_sigma_range: float | Float[Array, ''] = 3.0) tuple[Float[Array, 'N'], Float[Array, 'N']][source]

Convert OrientationDistribution to quadrature points and weights.

Description

Discretizes the orientation probability distribution into a set of angle samples and corresponding integration weights. Uses Gauss-Hermite quadrature around each discrete peak, with the spread controlled by mosaic_fwhm_deg.

param dist:

Orientation probability distribution.

type dist:

OrientationDistribution

param n_mosaic_points:

Number of Gauss-Hermite quadrature points per discrete peak for mosaic integration. Default: 7

type n_mosaic_points:

Union[int, Integer[Array, '']], default: 7

param n_sigma_range:

Number of sigma to extend mosaic sampling. Default: 3.0

type n_sigma_range:

Union[float, Float[Array, '']], default: 3.0

rtype:

tuple[Float[Array, 'N'], Float[Array, 'N']]

returns:
  • angles_deg (Float[Array, "N"]) – Quadrature angle samples in degrees. Shape: M × n_mosaic_points

  • weights (Float[Array, "N"]) – Integration weights (sum to 1.0).

Notes

When mosaic_fwhm_deg is very small (< 1e-6), the quadrature points collapse onto the discrete peaks, exactly reproducing delta-function behavior in the numerical quadrature.

The total number of output points is always M × n_mosaic_points.

rheedium.types.discretize_orientation_static(dist: OrientationDistribution, n_mosaic_points: int | Integer[Array, ''] = 7) tuple[Float[Array, 'N'], Float[Array, 'N']][source]

Static-dispatch version for use outside JIT when efficiency matters.

Description

When the distribution type is known at Python level (not traced), this version uses Python branching for efficiency: discrete-only distributions return M points instead of M × n_mosaic_points.

param dist:

Orientation probability distribution.

type dist:

OrientationDistribution

param n_mosaic_points:

Quadrature points per peak for mosaic. Default: 7

type n_mosaic_points:

Union[int, Integer[Array, '']], default: 7

rtype:

tuple[Float[Array, 'N'], Float[Array, 'N']]

returns:
  • angles_deg (Float[Array, "N"]) – Quadrature angle samples in degrees.

  • weights (Float[Array, "N"]) – Integration weights (sum to 1.0).

Notes

Use this version when calling outside of JIT for efficiency. Use discretize_orientation inside JIT-compiled functions.

rheedium.types.integrate_over_orientation(simulate_fn: Callable[[float | Float[Array, '']], Float[Array, 'H W']], orientation_dist: OrientationDistribution, n_mosaic_points: int | Integer[Array, ''] = 7) Float[Array, 'H W'][source]

Compute incoherent intensity sum over orientation distribution.

Description

Integrates RHEED intensity over the orientation probability distribution using numerical quadrature. Each orientation sample is simulated independently, then intensities are summed with distribution weights.

This implements the statistical ensemble averaging:

\[\begin{split}I_{total}(G) = \\int P(\\theta) \\, I(G, \\theta) \\, d\\theta \\approx \\sum_i w_i \\, I(G, \\theta_i)\end{split}\]
param simulate_fn:

Function mapping azimuthal angle (degrees) to RHEED intensity pattern. Must be vmappable. Signature: phi_deg → pattern.

type simulate_fn:

Callable[[Union[float, Float[Array, '']]], Float[Array, 'H W']]

param orientation_dist:

Probability distribution over orientations.

type orientation_dist:

OrientationDistribution

param n_mosaic_points:

Quadrature points for mosaic spread. Default: 7

type n_mosaic_points:

Union[int, Integer[Array, '']], default: 7

returns:

averaged_pattern – Incoherently averaged RHEED intensity pattern.

rtype:

Float[Array, 'H W']

Notes

The simulate_fn should capture all other parameters (crystal structure, beam energy, incidence angle, etc.) via closure. Only the azimuthal angle varies during integration.

For pure discrete distributions (no mosaic), this reduces to a weighted sum over the discrete variants.

Examples

>>> # Define simulation function (captures other params)
>>> def sim_at_phi(phi_deg):
...     return simulate_rheed(crystal, theta=2.0, phi=phi_deg, ...)
>>>
>>> # Create distribution
>>> dist = create_discrete_orientation(jnp.array([33.7, -33.7]))
>>>
>>> # Integrate
>>> pattern = integrate_over_orientation(sim_at_phi, dist)
class rheedium.types.DetectorGeometry(distance: float = 100.0, tilt_angle: float = 0.0, curvature_radius: float = inf, center_offset_h: float = 0.0, center_offset_v: float = 0.0, psf_sigma_pixels: float = 1.0)[source]

Bases: NamedTuple

Configuration for RHEED detector geometry.

This NamedTuple specifies the geometry of the detector screen for accurate projection of diffracted beams. Supports flat, tilted, and curved detector screens.

distance

Perpendicular distance from sample to detector center in mm. Default: 100.0

Type:

float

tilt_angle

Tilt angle of the detector about the horizontal axis in degrees. Positive tilt rotates the top of the screen away from the sample. Default: 0.0 (vertical screen)

Type:

float

curvature_radius

Radius of curvature of the detector screen in mm. Use jnp.inf for flat screen. Default: jnp.inf (flat)

Type:

float

center_offset_h

Horizontal offset of detector center from beam axis in mm. Positive values shift the detector right. Default: 0.0

Type:

float

center_offset_v

Vertical offset of detector center from beam axis in mm. Positive values shift the detector up. Default: 0.0

Type:

float

psf_sigma_pixels

Point spread function 1-sigma width in pixels. Models phosphor grain size, camera lens blur, and CCD pixel diffusion. Typical: 0.5–2.0 pixels. Use 0.0 to disable PSF convolution. Default: 1.0

Type:

float

Notes

For a standard RHEED setup: - The beam travels predominantly along +x (into the sample surface) - The detector is placed in the yz-plane at x = distance - Horizontal corresponds to y-direction, vertical to z-direction

The tilt angle accounts for common experimental setups where the phosphor screen is not perfectly perpendicular to the nominal beam direction.

For curved screens (e.g., cylindrical CCD detector arrays), the curvature_radius determines the cylinder radius. Points on the detector surface lie on this cylinder.

distance: float

Alias for field number 0

tilt_angle: float

Alias for field number 1

curvature_radius: float

Alias for field number 2

center_offset_h: float

Alias for field number 3

center_offset_v: float

Alias for field number 4

psf_sigma_pixels: float

Alias for field number 5

class rheedium.types.RHEEDImage(img_array: Float[Array, 'H W'], incoming_angle: float | Float[Array, ''], calibration: Float[Array, '2'] | float | Float[Array, ''], electron_wavelength: float | Float[Array, ''], detector_distance: int | float | Num[Array, ''])[source]

Bases: NamedTuple

JAX-compatible experimental RHEED image data structure.

This PyTree represents an experimental RHEED image with associated experimental parameters including beam geometry, detector calibration, and electron beam properties for quantitative RHEED analysis.

img_array

2D image array with shape (height, width) containing pixel intensity values. Non-negative finite values.

Type:

float_jax_image

incoming_angle

Angle of the incoming electron beam in degrees, typically between 0 and 90 degrees for grazing incidence geometry.

Type:

float

calibration

Calibration factor for converting pixels to physical units. Either a scalar (same calibration for both axes) or array of shape (2,) with separate [x, y] calibrations in appropriate units per pixel.

Type:

Union[Float[Array, "2"], scalar_float]

electron_wavelength

Wavelength of the electrons in Ångstroms. Determines the diffraction geometry and resolution.

Type:

float

detector_distance

Distance from the sample to the detector in mm. Affects the angular resolution and reciprocal space mapping.

Type:

float

Notes

This class is registered as a PyTree node, making it compatible with JAX transformations like jit, grad, and vmap. All data is immutable for functional programming patterns and efficient image processing.

Examples

>>> import jax.numpy as jnp
>>> import rheedium as rh
>>>
>>> # Create RHEED image with experimental parameters
>>> image = jnp.ones((256, 512))  # 256x512 pixel RHEED image
>>> rheed_img = rh.types.create_rheed_image(
...     img_array=image,
...     incoming_angle=2.0,  # 2 degree grazing angle
...     calibration=0.01,  # 0.01 units per pixel
...     electron_wavelength=0.037,  # 10 keV electrons
...     detector_distance=1000.0,  # 1000 Å to detector
... )
class rheedium.types.RHEEDPattern(G_indices: Int[Array, 'N'], k_out: Float[Array, 'M 3'], detector_points: Float[Array, 'M 2'], intensities: Float[Array, 'M'])[source]

Bases: NamedTuple

JAX-compatible RHEED diffraction pattern data structure.

This PyTree represents a RHEED diffraction pattern containing reflection data including reciprocal lattice indices, outgoing wavevectors, detector coordinates, and intensity values for electron diffraction analysis.

G_indices

Indices of reciprocal-lattice vectors that satisfy reflection conditions. Variable length array of integer indices.

Type:

Int[Array, "N"]

k_out

Outgoing wavevectors in 1/Å for reflections. Shape (M, 3) where M is the number of reflections and each row contains [kx, ky, kz] components.

Type:

Float[Array, "M 3"]

detector_points

Detector coordinates (Y, Z) on the detector plane in mm. Shape (M, 2) where each row contains [y, z] coordinates.

Type:

Float[Array, "M 2"]

intensities

Intensity values for each reflection. Shape (M,) with non-negative intensity values.

Type:

Float[Array, "M"]

This class is registered as a PyTree node, making it compatible with JAX
transformations like jit, grad, and vmap. All data is immutable and
stored in JAX arrays for efficient RHEED pattern analysis.

Examples

>>> import jax.numpy as jnp
>>> import rheedium as rh
>>>
>>> # Create RHEED pattern data
>>> G_indices = jnp.array([1, 2, 3])
>>> k_out = jnp.array([[1.0, 0.0, 0.5], [2.0, 0.0, 1.0], [3.0, 0.0, 1.5]])
>>> detector_points = jnp.array([[10.0, 5.0], [20.0, 10.0], [30.0, 15.0]])
>>> intensities = jnp.array([100.0, 80.0, 60.0])
>>> pattern = rh.types.create_rheed_pattern(
...     G_indices=G_indices,
...     k_out=k_out,
...     detector_points=detector_points,
...     intensities=intensities,
... )
class rheedium.types.SlicedCrystal(cart_positions: Float[Array, 'N 4'], cell_lengths: Float[Array, '3'], cell_angles: Float[Array, '3'], orientation: Int[Array, '3'], depth: float | Float[Array, ''], x_extent: float | Float[Array, ''], y_extent: float | Float[Array, ''])[source]

Bases: NamedTuple

JAX-compatible surface-oriented crystal structure for RHEED simulation.

This PyTree represents a crystal structure that has been sliced and oriented for RHEED simulations. The structure contains atoms from a surface region extended in x and y directions to cover a large area (>100 Å typically), with a specified depth perpendicular to the surface.

cart_positions

Cartesian coordinates of atoms in the slab with atomic numbers. Shape (N, 4) where each row is [x, y, z, atomic_number]. Coordinates are in Ångstroms.

Type:

Float[Array, "N 4"]

cell_lengths

Lengths of the supercell edges [a, b, c] in Ångstroms. These define the periodicity of the extended surface slab.

Type:

Float[Array, "3"]

cell_angles

Angles between supercell edges [alpha, beta, gamma] in degrees. Typically [90, 90, 90] for surface slabs.

Type:

Float[Array, "3"]

orientation

Miller indices [h, k, l] of the surface orientation. Example: [1, 1, 1] for a (111) surface, [0, 0, 1] for (001).

Type:

Int[Array, "3"]

depth

Depth of the slab perpendicular to the surface in Ångstroms. Atoms within this depth from the surface are included.

Type:

float

x_extent

Lateral extent of the slab in the x-direction in Ångstroms. Should be >100 Å for realistic RHEED simulation.

Type:

float

y_extent

Lateral extent of the slab in the y-direction in Ångstroms. Should be >100 Å for realistic RHEED simulation.

Type:

float

Notes

This class is registered as a PyTree node, making it compatible with JAX transformations. The structure is designed specifically for RHEED simulations where: - The z-direction is perpendicular to the surface (beam grazing angle) - The x-y plane is the surface plane - Large lateral extents (x_extent, y_extent) ensure realistic coherence - Limited depth models the surface sensitivity of RHEED

Examples

>>> import jax.numpy as jnp
>>> import rheedium as rh
>>>
>>> # Create a (111) surface slab
>>> cart_positions = jnp.array(
...     [
...         [0.0, 0.0, 0.0, 14.0],  # Si atom
...         [1.0, 1.0, 0.5, 14.0],
...     ]
... )  # Another Si
>>> sliced = rh.types.create_sliced_crystal(
...     cart_positions=cart_positions,
...     cell_lengths=jnp.array([150.0, 150.0, 20.0]),
...     cell_angles=jnp.array([90.0, 90.0, 90.0]),
...     orientation=jnp.array([1, 1, 1]),
...     depth=20.0,
...     x_extent=150.0,
...     y_extent=150.0,
... )
class rheedium.types.SurfaceConfig(method: str = 'height', height_fraction: float = 0.3, coordination_cutoff: float = 3.0, coordination_threshold: int = 8, n_layers: int = 1, layer_tolerance: float = 0.5, explicit_mask: Bool[Array, 'N'] | None = None)[source]

Bases: NamedTuple

Configuration for surface atom identification.

This NamedTuple specifies how to identify which atoms are considered surface atoms for enhanced Debye-Waller factors in RHEED simulations.

method

Surface identification method: - “height”: top fraction by z-coordinate (default) - “coordination”: atoms with fewer neighbors than bulk - “layers”: atoms in topmost N complete layers - “explicit”: user-provided surface mask

Type:

str

height_fraction

For “height” method: fraction of z-range considered surface. Default: 0.3 (top 30% of atoms by height)

Type:

float

coordination_cutoff

For “coordination” method: cutoff distance in Angstroms for counting neighbors. Default: 3.0

Type:

float

coordination_threshold

For “coordination” method: atoms with fewer than this many neighbors are considered surface. Default: 8 (typical for FCC)

Type:

int

n_layers

For “layers” method: number of topmost layers considered surface. Default: 1

Type:

int

layer_tolerance

For “layers” method: tolerance for grouping atoms into layers in Angstroms. Default: 0.5

Type:

float

explicit_mask

For “explicit” method: user-provided boolean mask. Must have same length as number of atoms. Default: None

Type:

Bool[Array, "N"] | None

method: str

Alias for field number 0

height_fraction: float

Alias for field number 1

coordination_cutoff: float

Alias for field number 2

coordination_threshold: int

Alias for field number 3

n_layers: int

Alias for field number 4

layer_tolerance: float

Alias for field number 5

explicit_mask: Bool[Array, 'N'] | None

Alias for field number 6

rheedium.types.create_rheed_image(img_array: Float[Array, 'H W'], incoming_angle: float | Float[Array, ''], calibration: Float[Array, '2'] | float | Float[Array, ''], electron_wavelength: float | Float[Array, ''], detector_distance: int | float | Num[Array, '']) RHEEDImage[source]

Create a RHEEDImage instance with data validation.

Parameters:
  • img_array (Float[Array, 'H W']) – The image in 2D array format.

  • incoming_angle (Union[float, Float[Array, '']]) – The angle of the incoming electron beam in degrees.

  • calibration (Union[Float[Array, '2'], float, Float[Array, '']]) – Calibration factor for the image, either as a 2D array or a scalar.

  • electron_wavelength (Union[float, Float[Array, '']]) – The wavelength of the electrons in Ångstroms.

  • detector_distance (Union[int, float, Num[Array, '']]) – The distance from the sample to the detector in mm.

Returns:

validated_rheed_image – Validated RHEED image instance.

Return type:

RHEEDImage

Notes

  1. Convert inputs to JAX arrays.

  2. Validate image array: check it is 2D, all values are finite and non-negative.

  3. Validate parameters: check incoming_angle is between 0 and 90 degrees, electron_wavelength is positive, and detector_distance is positive.

  4. Validate calibration: if scalar, ensure it is positive; if array, ensure shape is (2,) and all values are positive.

  5. Create and return RHEEDImage instance.

rheedium.types.create_rheed_pattern(g_indices: Int[Array, 'N'], k_out: Float[Array, 'M 3'], detector_points: Float[Array, 'M 2'], intensities: Float[Array, 'M']) RHEEDPattern[source]

Create a RHEEDPattern instance with data validation.

Parameters:
  • g_indices (Int[Array, 'N']) – Indices of reciprocal-lattice vectors that satisfy reflection.

  • k_out (Float[Array, 'M 3']) – Outgoing wavevectors (in 1/Å) for those reflections.

  • detector_points (Float[Array, 'M 2']) – (Y, Z) coordinates on the detector plane, in mm.

  • intensities (Float[Array, 'M']) – Intensities for each reflection.

Returns:

validated_rheed_pattern – Validated RHEED pattern instance.

Return type:

RHEEDPattern

Notes

  • Convert inputs to JAX arrays.

  • Validate array shapes: check k_out has shape (M, 3), detector_points has shape (M, 2), intensities has shape (M,), and g_indices has length M.

  • Validate data: ensure intensities are non-negative, k_out vectors are non-zero, and detector points are finite.

  • Create and return RHEEDPattern instance.

rheedium.types.create_sliced_crystal(cart_positions: Float[Array, 'N 4'], cell_lengths: Float[Array, '3'], cell_angles: Float[Array, '3'], orientation: Int[Array, '3'], depth: float | Float[Array, ''], x_extent: float | Float[Array, ''], y_extent: float | Float[Array, '']) SlicedCrystal[source]

Create a SlicedCrystal instance with data validation.

Parameters:
  • cart_positions (Float[Array, 'N 4']) – Cartesian atomic positions with atomic numbers [x, y, z, Z].

  • cell_lengths (Float[Array, '3']) – Supercell edge lengths [a, b, c] in Ångstroms.

  • cell_angles (Float[Array, '3']) – Supercell angles [alpha, beta, gamma] in degrees.

  • orientation (Int[Array, '3']) – Miller indices [h, k, l] of surface orientation.

  • depth (Union[float, Float[Array, '']]) – Slab depth perpendicular to surface in Ångstroms.

  • x_extent (Union[float, Float[Array, '']]) – Lateral extent in x-direction in Ångstroms.

  • y_extent (Union[float, Float[Array, '']]) – Lateral extent in y-direction in Ångstroms.

Returns:

validated_sliced_crystal – Validated SlicedCrystal instance.

Return type:

SlicedCrystal

Notes

  • Verify cart_positions shape is (N, 4) with N > 0.

  • Verify cell_lengths, cell_angles, orientation have correct shapes.

  • Ensure all positions are finite.

  • Ensure depth, x_extent, y_extent are positive.

  • Recommend x_extent and y_extent >= 100 Angstroms.

  • Validate atomic numbers (cart_positions[:, 3]) are in valid range [1, 118].

rheedium.types.identify_surface_atoms(atom_positions: Float[Array, 'N 3'], config: SurfaceConfig = _DEFAULT_SURFACE_CONFIG) Bool[Array, 'N'][source]

Identify surface atoms using the specified method.

Parameters:
  • atom_positions (Float[Array, 'N 3']) – Cartesian atomic positions in Angstroms, shape (N, 3).

  • config (SurfaceConfig, default: _DEFAULT_SURFACE_CONFIG) – Surface identification configuration. Default: SurfaceConfig() with height-based method at 30% fraction.

Returns:

is_surface – Boolean mask indicating which atoms are surface atoms.

Return type:

Bool[Array, 'N']

Notes

Available methods:

  • height: Uses z-coordinate threshold. Atoms in the top height_fraction of the z-range are marked as surface.

  • coordination: Uses neighbor counting. Atoms with fewer than coordination_threshold neighbors within coordination_cutoff distance are marked as surface. This is more physical for reconstructed or stepped surfaces.

  • layers: Identifies discrete atomic layers by z-coordinate and marks the topmost n_layers as surface. Uses layer_tolerance to group atoms into layers.

  • explicit: Uses user-provided mask directly from config.explicit_mask.

Examples

>>> import jax.numpy as jnp
>>> from rheedium.types import SurfaceConfig, identify_surface_atoms
>>> positions = jnp.array([[0, 0, 0], [0, 0, 1], [0, 0, 2]])
>>> # Height-based (default)
>>> mask = identify_surface_atoms(positions)
>>> # Coordination-based
>>> config = SurfaceConfig(method="coordination", coordination_cutoff=2.5)
>>> mask = identify_surface_atoms(positions, config)