Changelog#
Upcoming: 1.1.0#
The dev branch is at version 1.1.0. The entries below are merged into dev but not yet released.
Features:
Energy ensemble support across the codebase:
PlaneWave,Probe,SMatrix,BlochWavesandCTFaccept a list of energies, and the resultingEnergyAxispropagates through indexing, angular sampling, unit conversion and diffraction-spot indexing (PR #257)C-PRISM:
SMatrix(upsample=True)reduces every probe from the complete plane-wave expansion of the aperture, so the interpolation factor only sets the number of multislice runs. AddsCompressedSMatrixArrayandGridScan.commensurate(PR #318)Phonon-loss (thermal diffuse scattering) energy-loss workflow:
EnergyResolvedAtomsEnsemble,phonon_loss_diffraction_patterns,momentum_resolved_spectrumandMomentumResolvedSpectrum, theSpectralAnnularDetectorandSpectralSlitDetector, and detailed-balance thermal weighting that splits the classical TDS signal into loss and gain sides (PR #324, PR #351)Linear-scaling PRISM-EELS for core-loss simulations:
SMatrix.transition_potential_scan, with single- and double-channel scattering and an optional windowed inelastic crop (PR #289)In addition to the Gaussian (G) distribution, now also implemented Lorentzian (L), Voigtian (convolution L * G) and pseudo-Voigtian (L + G) source-size distributions and filters (PR #270)
The exact free-space propagator is now the default for Fourier multislice,
FourierMultislice(order="exact"), replacing the paraxial approximation. Spatial frequencies beyondk > 1 / lambdaare treated as evanescent rather than propagating; the paraxial propagator remains available asorder=1(PR #298)Magnetic potentials and fields from collinear GPAW calculations:
gpaw_magnetic_fieldsbuilds the electrostatic potential, vector potential and magnetic field from the same calculator(s) in one call, returning aGPAWMagneticFieldsbundle with.tile(),.combined_potential()and.show();rotate_fieldnow defaults to"auto"(PR #326)GPAWParametrizationis now usable: it fits a Lobato-form IAM potential to the X-ray scattering factor of an all-electron GPAW calculation, with working ionization support and a regularized fit (PR #329)Potential(sampling="auto", slice_thickness="auto")automatically finds a grid commensurate with the atomic lattice — so translation-equivalent atoms discretize identically — near the usual default targets (\(0.05 \ \mathrm{Å}\), \(1 \ \mathrm{Å}\)), preferring FFT-fast grid sizes wherever that is compatible with commensurability. Newgrid.round-to-fast-fftconfig key ('auto'/True/False),Grid.round_to_fast_fft(), andis_fast_fft_size/next_fast_fft_sizehelpers inabtem.core.fft(PR #274, PR #347)Significant improvements on simulating large potentials on GPU, alongside minor performance improvements (PR #269)
The potential is now built in chunks of contiguous slices instead of all at once, keeping peak VRAM bounded; new config key
potential.slice-chunk-size(default"auto")Opt-in multi-GPU via the new config key
dask.multi-gpu(requiresdask-cuda)cupy.fft-cache-size’s previous0 MBdefault silently disabled the cuFFT plan cache; changed to-1(unlimited) here, then to the device-relativeautodefault below once unbounded retention turned out to cost tens of GB on FFT-unfriendly grids
Performance:
The projection integrator is shared by reference across ensemble members instead of being deep-copied (and re-uploaded to the GPU) for each (PR #350)
Removed a redundant potential rebuild on every scan chunk (PR #340)
Dependencies:
The
core-lossextra is merged into a singlegpaw = ["hankel", "sympy"]extra, and a newallextra installs every optional runtime dependency (PR #329)
Bugfixes:
GPAWPotentialfor the new-style GPAW calculator API (GPAW 26+), andGPAWPotential.from_fileon old-style restarted calculators (PR #325)GPAWPotentialsingle-calculatorfrozen_phononsensemble building (PR #327), plus removal of dead and broken code fromGPAWPotentialandGPAWParametrization(PR #328)FieldArray.tile()for vector-valued fields, and unsupportedfrozen_phonons/repetitionson magnetic fields now raise instead of being silently ignored (PR #326)Silent corruption in eager multislice for potentials with two or more ensemble axes (PR #333)
numbaTypingErrorin quasi-dipole interpolation on some numba/numpy pairings (PR #332)Single-point
GridScanfailing when built lazily (PR #342)LinearAxislosing its offset under dask ensemble chunk partitioning (PR #344)Nondeterministic atom loss in
orthogonalize_cell, and a hardened Gram-Schmidt fallback (PR #345)Repeated axis labels and colorbar overlap in exploded spectrum panels, and silently returned zeros for single-configuration TDS (PR #351)
Azimuthal convention in
prism_coefficients, which reflected azimuthally dependent aberrations in a PRISM reduction with aCTF, and exit planes not being remapped when slicing aPotentialArray(PR #318)numpy2.5 test failures caused by an ASE deprecation warning (PR #343)Probe.transition_potential_scanraised for a scan split into more than one chunk (for example throughmax_batch) unless the scattering sites were passed explicitly (PR #353)Colorbars did not span multi-row exploded plots, and neighbouring panels could abut closely enough for their tick labels to collide (PR #354)
Multi-GPU hardening, and the configuration fix found while chasing it (PR #346)
The client’s configuration now reaches
distributedworkers. abTEM resolves configuration inside each task, and worker processes start fresh and previously saw only the YAML defaults, so any distributed computation with a non-default configuration silently used the defaults instead — most consequentiallyprecision, which meantfloat64runs were computed infloat32. Distributed results obtained with a non-default configuration are worth repeating. Applies to any distributed client, CPU clusters includedto_zarr()on a lazy result honoursdask.multi-gpu; it previously ignored the flag and ran the whole computation on a single devicecupy.fft-cache-sizedefaults toauto— 25 % of each device’s memory, resolved per device — rather than unlimited.-1restores unlimited,0 MBdisables the cache, and a size such as512 MBsets a fixed bound. A single plan larger than the bound runs uncached with a warning instead of raisingNew config keys
dask.multi-gpu-rmm-poolanddask.multi-gpu-devices, for an RMM memory pool per worker and for restricting the cluster to a subset of GPUsAutomatically sized scan batches are halved on grid sizes that force cuFFT’s Bluestein fallback, which needs a much larger FFT workspace
Warnings replace silent fallbacks: multi-GPU requested but declined (with the reason), a missing
if __name__ == "__main__"guard, and a grid size that forces the Bluestein fallback (naming the next fast size)
Documentation:
sampling="auto"/slice_thickness="auto"documented in detail in the potentials walkthrough, including a worked example of the commensurability artifact they remove; cross-referenced from the convergence appendix (manual commensurate sampling) and the performance-tips appendix (fast FFT sizes)New tutorial on phonon-loss spectroscopy: energy-resolved frozen phonons, the TDS decomposition, the momentum-resolved spectrum \(S(q, E)\), the spectral detectors and detailed-balance thermal weighting
Energy ensembles documented in the wave-function walkthrough, with an energy series added to the multislice walkthrough
PRISM-EELS added to the core-loss tutorial, compared against the equivalent multislice scan
The exact free-space propagator is documented in the multislice walkthrough and the real-space multislice tutorial, which now selects the paraxial propagator explicitly where it compares algorithms at equal order
The installation page documents the optional pip extras (
gpaw,extra,all) and why the GPU packages are not among themThe configuration reference is synchronized with the new and changed config keys
The multiple-GPUs section of the parallelization walkthrough is expanded to cover the multi-GPU hardening fixes above, and the FFT plan-cache documentation is corrected to match the shipped
autodefault (it previously described a stale0 MBdefault that was never shipped)
Planned for this release (not yet merged):
1.0.10#
Features:
Expanded real-space multislice with propagator- and fully-corrected algorithms, and backscattered waves (PR #236)
Related internal function name change: standard multislice is now properly called
FourierMultislice
Updated
BullseyeApertureto use smoothed aperture edges/corners (PR #266)Logarithmic scale display for
DiffractionPatternsand images (PR #303)Finite-projection integrals 7x faster on CPU (PR #309)
Documentation:
Expanded tutorial on real-space multislice
Depth-profile visualization of potentials in the walkthrough
Single-file Zarr zip storage, logarithmic display scaling, soft Bullseye apertures, anisotropic Debye-Waller factors and B-factor conversion helpers
All published notebooks verified to run with this release
Dependencies:
NumPy 2.0 or newer is now required (PR #245)
GitHub actions based on
uvand now cover more versions (including Python 3.14) (PR #308)New branching structure:
devfor development,mainfor releases (only via PRs fromdev)Support for Zarr 3
ZipStore(requiringzarr>=3.1)Added Zstandard compression of the arrays in the ZipStore at default level 4 (hat tip: quantEM) (PR #252)
Deprecated
[gpu]optional dependency (as just specifyingcupywill not install the correct CUDA version)Moved
testing,docs, anddevfrom optional dependencies to groupsNarrow Dask version exclusion to !=2025.12.*,!=2026.1.0,!=2026.1.1 (PR #285)
Declared
sympyas an optional dependency (core-lossextra), required for core-loss EELS form factors (PR #320)
Bugfixes:
Frozen-phonon ensemble handling (PR #267 & PR #292)
May also have resulted in incorrect behavior with
ensemble_mean = Falsefor e.g. defocus distributions
CrystalPotentialwith frozen phonons bugs (especially bad on – luckily rare – eager compute) (PR #306)Minor bugs, unsafe patterns, and dead code (PR #265)
Anistropic Debye-Waller factors for Bloch wave (PR #271)
Added helper functions to convert between crystallographic B-factors and thermal sigmas
Added missing
.calculate_exit_wavesforBlochwaveEnsamble(PR #294)Silent atom drop when
z-position lands in SliceIndexedAtoms blind spot (PR #273)Early-exit bug in orthogonalize_cell (PR #291)
Fixed broken tutorial workflow for core-loss filtered imaging (PR #284)
Minor performance improvements for
transition_potential_scan(PR #286)
Bullseyeaperture:ring_widthandspoke_widthare now validated, rejecting values that previously produced a silently wrong (solid disk) aperture; docstring corrected to describe the actual fractional units introduced by the soft-edge redesign (PR #319)Unified the task-level progress bar config key on
diagnostics.task_progress(Bloch-wave code paths previously read a different, non-functional key) (PR #321)
1.0.9#
Dependencies:
Support for
scipy>=1.7andcupy>=12.Restricted Dask versions (
>=2022.12.1,!=2025.12.*,!=2026.1.*") to avoid an issue with Numba in the latest ones
1.0.8#
Starting the changelog with version 1.0.8.
Features:
Fully featured Bloch-wave simulations
Simple real-space multislice algorithm
Core-loss filtered imaging
Structured illumination (custom apertures and phase plates)
Documentation:
Updated and fixed example gallery
Appendix on convergence
Expanded tutorial on orthogonal periodic supercells
Bugfixes:
Numerous small bugfixes and improvements