abtem.inelastic.core_loss

Contents

abtem.inelastic.core_loss#

Module Contents#

Classes#

Functions#

calculate_bound_radial_wavefunction

calculate_continuum_radial_wavefunction

check_valid_quantum_number

Validate that the quantum numbers (n, l) correspond to an occupied subshell for element with atomic number Z. Raises RuntimeError if invalid.

config_str_to_config_tuples

Parse an electron configuration string (e.g. “1s2 2s2 2p6”) into a list of (n, l, occupancy) tuples.

config_tuples_to_config_str

Convert a list of (n, l, occupancy) tuples back to an electron configuration string (e.g. “1s2 2s2 2p6”).

fast_roll

Batched 2D circular roll: out[i] == xp.roll(array, shifts[i], axis=(0, 1)).

numerov

Given precomputed function f(x), solves for x(t), which satisfies: x’’(t) = f(t) x(t)

prism_transition_potential_scan

PRISM-EELS driver following Brown et al. (Phys. Rev. Research 1, 033186, 2019).

prism_transition_potential_scan_beam_basis

PRISM-EELS beam-basis reduction (Brown et al. Sec. IV B / Eq. dropped in supplementary; PRISM_double_channeling_nanoparticle.m) — the accuracy-oriented alternative to prism_transition_potential_scan().

radial_schroedinger_equation

remove_electron_from_config_str

Remove one electron from the (n, l) subshell in the given configuration string and return the updated configuration string.

Data#

API#

class abtem.inelastic.core_loss.AtomicWaveFunction(...)[source]#

Initialization

property bound#
property energy#
property l#
property ml#
property n#
property quantum_numbers#
property radial_grid#
class abtem.inelastic.core_loss.BaseTransitionCollection(...)[source]#

Initialization

property Z#
abstract get_transition_potential()[source]#
class abtem.inelastic.core_loss.BaseTransitionPotential(...)[source]#

Bases: abtem.core.energy.HasAcceleratorMixin, abtem.core.grid.HasGrid2DMixin, abtem.core.utils.CopyMixin

property Z: int#
property double_channel: bool#
abstract property metadata: dict#
class abtem.inelastic.core_loss.RadialWavefunction(...)[source]#

Initialization

property bound#
property energy#
property l#
property n#
property radial_grid#
show(...)[source]#
to_lineprofiles(...)[source]#
class abtem.inelastic.core_loss.SubshellTransitions(...)[source]#

Bases: abtem.inelastic.core_loss.BaseTransitionCollection

Initialization

property bound_configuration#
property epsilon#
property excited_configuration#
get_bound_wave_function()[source]#
get_excited_wave_functions()[source]#
get_transition_potentials(...)[source]#
get_transition_quantum_numbers()[source]#
get_transitions()[source]#
property l#
property lprimes#
property min_contrast#
property n#
property order#
property xc#
class abtem.inelastic.core_loss.TransitionPotential(...)[source]#

Bases: abtem.inelastic.core_loss.BaseTransitionPotential

property Z: int#
build() TransitionPotentialArray[source]#
property double_channel: bool#
property ensemble_axes_metadata: list[AxisMetadata]#
property ensemble_shape: tuple[int]#
filter_by_intensity(...) TransitionPotential[source]#
integrated_intensities()[source]#
property metadata: dict#
property orbital_filling_factor: bool#
scatter(...) Waves[source]#
show(...)[source]#
property transition_quantum_numbers#
property transitions#
class abtem.inelastic.core_loss.TransitionPotentialArray(...)[source]#

Bases: abtem.array.ArrayObject, abtem.inelastic.core_loss.BaseTransitionPotential

absolute_threshold(...)[source]#
filter_by_intensity(...) TransitionPotential[source]#
filter_sites(...)[source]#
abstract from_array_and_metadata(...)[source]#
generate_scattered_waves(...)[source]#
integrated_intensities(...)[source]#
local_potential(...)[source]#
Parameters:
  • max_angle (float) – Maximum angle (in degrees) for the local potential calculation.

  • space (str, optional) – Specifies the coordinate space in which the potential is calculated. Default is “reciprocal”. Possible values are “reciprocal” and “real”.

Returns:

array – The calculated local potential.

Return type:

ndarray

scatter(...) Waves[source]#
set_threshold(...)[source]#
show(...)[source]#
to_images()[source]#
validate_sites(...) ndarray[source]#
abtem.inelastic.core_loss.azimuthal_letter#

None

abtem.inelastic.core_loss.azimuthal_number#

None

abtem.inelastic.core_loss.calculate_bound_radial_wavefunction(...)[source]#
abtem.inelastic.core_loss.calculate_continuum_radial_wavefunction(...)[source]#
abtem.inelastic.core_loss.check_valid_quantum_number(...)[source]#

Validate that the quantum numbers (n, l) correspond to an occupied subshell for element with atomic number Z. Raises RuntimeError if invalid.

abtem.inelastic.core_loss.config_str_to_config_tuples(...)[source]#

Parse an electron configuration string (e.g. “1s2 2s2 2p6”) into a list of (n, l, occupancy) tuples.

abtem.inelastic.core_loss.config_tuples_to_config_str(...)[source]#

Convert a list of (n, l, occupancy) tuples back to an electron configuration string (e.g. “1s2 2s2 2p6”).

abtem.inelastic.core_loss.fast_roll(...)[source]#

Batched 2D circular roll: out[i] == xp.roll(array, shifts[i], axis=(0, 1)).

On CPU the per-site quadrant-copy loop is already very fast — each slice is a memmove — and beats both xp.roll in a loop and a full advanced-indexing gather. On GPU the advanced-indexing form wins because the per-site loop serialises kernel launches; we dispatch on the backend.

Shifts are first reduced modulo H / W so negative and out-of-range values are handled correctly (the previous version raised RuntimeError on negative shifts).

abtem.inelastic.core_loss.numerov(...)[source]#

Given precomputed function f(x), solves for x(t), which satisfies: x’’(t) = f(t) x(t)

abtem.inelastic.core_loss.prism_transition_potential_scan(...)[source]#

PRISM-EELS driver following Brown et al. (Phys. Rev. Research 1, 033186, 2019).

Supports any interpolation factor, downsample setting, and both single- and double-channel modes. The scatter and (optionally) double-channel propagation operate on a cropped grid at full resolution centered at each scattering site (Sec. IV B); when downsample is enabled the scattered result is Fourier-cropped to the downsampled resolution before per-position reduction.

At interpolation=(1,1) with downsample=False the output is bit-equivalent (to float32 noise) to Probe.transition_potential_scan at the matching double_channel setting.

double_channel=True propagates the scattered state through the remaining potential slices to the exit before reducing per-position; double_channel=False (default) detects immediately at the scatter slice — Brown’s single-channel approximation.

Frozen-phonon ensemble averaging is handled at the SMatrix level (see SMatrix.transition_potential_scan); Dask lazy evaluation is supported via the lazy parameter on that method.

Parameters:
  • s_matrix (SMatrix) – S-matrix specification (any interpolation).

  • transition_potentials (BaseTransitionPotential) – Atomic transition potential.

  • scan (BaseScan or tuple) – Scan positions.

  • detectors (BaseDetector or list, optional) – Detectors. Defaults to FlexibleAnnularDetector().

  • sites (Atoms or SliceIndexedAtoms, optional) – Scattering sites. Auto-extracted from the potential if not given, following the same logic as transition_potential_multislice_and_detect.

  • inelastic_crop (float or tuple of float, optional) – Real-space side length [Å] of the window on which the transition potential H_n0 and the scattered wave are evaluated, following Brown et al. Sec. IV B (their independent inelastic_crop factor). Smaller windows speed up the scatter and — most significantly — the double-channel inner propagation, at the cost of truncating the H_n0 tails (cf. their Fig. 4 / Table II). If None (default) the full PRISM cell extent / interpolation is used (current behaviour). The window is clamped to the PRISM cell: values larger than extent / interpolation are not supported by this real-space reduction (they would admit aliased probe copies) and are clamped with a warning — exceeding the cell requires the beam-basis reduction (see the PRISM-EELS follow-up note).

Returns:

One measurement per detector.

Return type:

BaseMeasurements or list of BaseMeasurements

abtem.inelastic.core_loss.prism_transition_potential_scan_beam_basis(...)[source]#

PRISM-EELS beam-basis reduction (Brown et al. Sec. IV B / Eq. dropped in supplementary; PRISM_double_channeling_nanoparticle.m) — the accuracy-oriented alternative to prism_transition_potential_scan().

Implements Brown’s beam-basis contraction (un-reduced S-matrix columns against a transition-potential window, before applying the periodic position phase ramps). This was originally pursued (GitHub issue abTEM/abTEM#293) to let the transition-potential window exceed the real-space driver’s PRISM-cell cap, in the hope of fixing the delocalized-edge truncation error at interpolation > 1. That goal turned out to be unfounded: the interpolation-decimated PRISM probe is exactly periodic with the PRISM cell (extent / interpolation), so a window larger than the cell multiplies the transition-potential tail against an exact copy of the probe peak — adding spurious signal rather than recovering accuracy. A direct experiment (issue #293, Update 4) confirms the shape error is flat-to-worse as the window grows past the cell, and Brown’s own published run uses a window smaller than the cell. inelastic_crop is therefore clamped to the cell, exactly like the real-space driver. This function is kept as a validated, independent re-derivation of Brown’s reduction (bit-exact at interpolation=1); it does not — and now appears it cannot — beat the real-space path on delocalized-edge accuracy. The lever for delocalized edges is a larger cell (lower interpolation or a bigger supercell), not a larger window.

Normalisation derivation (validated bit-exact against Probe.transition_potential_scan at interpolation=(1, 1) for both single- and double-channel; see project_prism_eels_beam_basis_convention memory note): for an abtem fft2/ifft2 pair (unnormalised forward, 1/N inverse),

fft2(forward_propagate(psi))[q] = N * sum_r conj(S2[q, r]) * psi[r]

where N = prod(gpts) and S2[q] is built by reverse-propagating ifft2(delta_q) through the remaining slices with conventional_multislice_step(..., conjugate=True, transpose=True). The full contraction is

SHn0[q, k]    = N * sum_{r in window} conj(S2[q, r]) * H(r) * S1[k, r]
recip[pos, q] = sum_k coeff[pos, k] * SHn0[q, k]

Limitations (this is a validated reference implementation, not an optimised production path — see GitHub issue abTEM/abTEM#293):

  • inelastic_crop exceeding the PRISM cell is clamped (with a warning): it is not a useful regime — see the docstring intro.

  • S2 (double-channel) is built over the full native reciprocal grid (prod(gpts) beams). Memory and compute scale as O(prod(gpts)^2) per scattering site per slice — only practical for small grids.

  • Single exit plane only (len(potential.exit_planes) == 1).

  • No frozen-phonon ensemble (potential.ensemble_shape == ()).

  • No downsample support (s_matrix.downsampled_gpts == s_matrix.gpts).

  • Eager only; no Dask laziness.

Parameters:
  • s_matrix (SMatrix) – S-matrix specification (any interpolation).

  • transition_potentials (BaseTransitionPotential) – Atomic transition potential.

  • scan (BaseScan or tuple) – Scan positions.

  • detectors (BaseDetector or list, optional) – Detectors. Defaults to FlexibleAnnularDetector().

  • sites (Atoms or SliceIndexedAtoms, optional) – Scattering sites. Auto-extracted from the potential if not given.

  • double_channel (bool, optional) – If True (default), propagate the scattered state to the exit via a reverse-multislice S2 before reducing. If False, detect immediately at the scatter slice (single-channel): S2 is then trivial — the contraction reduces to an FFT of the windowed scattered field directly, no reverse multislice needed.

  • inelastic_crop (float or tuple of float, optional) – Real-space side length [Å] of the window on which H_n0 and the scattered wave are evaluated. Clamped to the PRISM cell (extent / interpolation) with a warning if larger — see Limitations above. If None (default), the PRISM cell is used, matching the real-space driver’s default window.

Returns:

One measurement per detector.

Return type:

BaseMeasurements or list of BaseMeasurements

abtem.inelastic.core_loss.radial_schroedinger_equation(...)[source]#
abtem.inelastic.core_loss.remove_electron_from_config_str(...)[source]#

Remove one electron from the (n, l) subshell in the given configuration string and return the updated configuration string.