de-ebsd
Differentiable, GPU-accelerated EBSD in PyTorch: dynamical master-pattern simulation from a crystal structure, native Monte Carlo electron transport, orientation indexing (dictionary, spherical-harmonic and live), gradient and high-resolution refinement, pattern-center calibration and HR-EBSD strain. The API is composable and object oriented, in the manner of abTEM, and every intermediate stage is inspectable.
A master pattern is the backscattered-electron intensity as a function of crystal direction, stored on the square-Lambert grid. de-ebsd builds it from first principles -- crystal, structure factors with absorption, reflections, Bloch-wave dynamical solve, depth integration over a Monte Carlo exit-depth profile -- and then runs the inverse problem against measured patterns. The physics is ported from EMsoft (Callahan & De Graef 2013), which remains the validation oracle (de-ebsd does not call EMsoft at runtime); see NOTICE. Indexing follows EMSphInx (Lenthe, Singh & De Graef 2019) and emits orix objects, so kikuchipy and other tools can use it as a backend.
Installation
Windows / Linux with uv (Python >= 3.11; torch comes from the CUDA 12.4
index on Windows and the CPU index on Linux, configured in pyproject.toml):
git clone https://github.com/directelectron/de-ebsd
cd de-ebsd
uv sync
The distribution is named de-ebsd; the Python package is de_ebsd. The
fused CUDA kernels of live indexing need CuPy: uv sync --extra live.
Quickstart: simulation
import de_ebsd as de
crystal = de.Crystal.from_parameters(
a=0.5431, space_group=227, atoms=[("Si", (0.125, 0.125, 0.125))]
)
microscope = de.Microscope(energy=20e3, sample_tilt=70.0)
sim = de.MasterPatternSimulator(
crystal,
microscope,
npx=500,
dmin=0.05,
bethe=de.BetheParameters(),
# backend="bloch_prism" is the default: the batched dynamical solve.
# "bloch" is the one-direction-at-a-time float64 reference it reproduces.
)
# every stage is inspectable (all figures render through anyplotlib):
sim.structure_factors().show() # |U_g| per family, absences, V_0
sim.reflections(k=(0, 0, 1)).show() # Bethe strong / weak split for one beam
sim.dynamical_matrix(k=(0, 0, 1)).show()
master = sim.compute(device="cuda") # -> MasterPattern
master.show(projection="lambert") # also "stereographic" and "sphere"
sim.crystal.show() # real 3-D expanded crystal structure
# refine and recompute (structure factors are reused when still valid):
better = sim.refine(npx=1000, dmin=0.04)
# project to a detector for a batch of orientations (orix Rotation):
detector = de.EBSDDetector(shape=(480, 480), pattern_center=(0.5, 0.5, 0.6))
patterns = master.project(detector, orientation=rotations)
# interactive geometry widget in Jupyter (anywidget):
sim.show_setup(detector=detector)
# phase composition for Jupyter or a host application; figures stay native:
phase = sim.crystal.overview(master_pattern=master)
sim.microscope.show(detector=detector, crystal=sim.crystal)
# STEM zone-axis exploration: geometric Kikuchi lines + kinematic spots,
# independently toggleable in one projection; no master pattern required:
explorer = sim.crystal.explore(energy_kev=200, dmin=0.1)
The exit-depth statistics the dynamical solve integrates over come from a native
Monte Carlo (de_ebsd.sim.montecarlo) unless you pass a DepthDistribution,
for example one read from an EMsoft Monte Carlo file.
Quickstart: indexing
from de_ebsd.index import (
DictionaryIndexer,
SphericalIndexer,
refine_orientation,
remove_background,
)
patterns = remove_background(raw, static_bg=static_bg, operation="divide")
# Spherical indexing: one SO(3) cross-correlation per pattern, on the GPU.
indexer = SphericalIndexer(master, detector, bandwidth=68, device="cuda")
rotations, quality = indexer.index(patterns)
# Dictionary indexing over a fundamental-zone sample, as an orix CrystalMap:
xmap = DictionaryIndexer(master, detector, resolution=2.5).index_scan(scan, step=0.5)
# Sharpen a coarse index by gradient or Levenberg-Marquardt refinement:
refined, score = refine_orientation(patterns, master, detector, rotations, method="lm")
Also in de_ebsd.index: refine_hr (band-edge refinement of orientation and,
optionally, pattern center), determine_pattern_center (one center shared by
many patterns), hrebsd (lattice strain and rotation by cross-correlation
against a reference pattern) and LiveIndexer, which indexes, refines and
strain-fits a camera's frames where they already are on the GPU, at thousands of
patterns a second.
Examples
The examples folder contains executable Sphinx-Gallery tutorials, grouped by the layer they exercise.
Master-pattern simulation -- the forward chain:
- CIF to detector: silicon structure, native Monte Carlo, diffraction intermediates, full 3D master pattern, orix orientations, detector images, phase overview, and HDF5 round trip.
- Energy-resolved simulation: nickel transport statistics and dynamical patterns at multiple energies.
- Resolution and backends: grid refinement, detector-space differences, and PRISM/Bloch comparison, plus the microscope, probe, detector and depth-slice inspectors.
- Compare with EMsoft: use the bundled nickel reference's crystal, Bethe settings and Monte Carlo profile, then compare both hemispheres, normalized residuals, and detector patterns.
- STEM orientation explorer: a band-line sphere, crystal structure, and a combined lines/spots view. It provides geometric band centerlines and relative elastic kinematic spot intensities; it does not simulate transmission Kikuchi contrast or convergent-beam discs.
Orientation indexing -- the inverse problem, each on a synthetic two-grain scan with known orientations:
- Dictionary indexing: background
removal, a fundamental-zone template library, a
CrystalMapwith IPF and quality maps, and Levenberg-Marquardt refinement to sub-degree accuracy. - Spherical indexing: the SO(3) cross-correlation surface, the bandwidth accuracy/cost trade-off and how it fails when truncated too far, then refinement off the peak.
Run scripts with uv run python examples/simulation/cif_to_detector.py. They
use small CPU-friendly teaching settings; see
examples/README.rst for execution, display, and
convergence notes.
Documentation
The full site -- user guide, design notes, the executable example gallery, and an API reference generated from the docstrings -- is published at https://directelectron.github.io/de-ebsd/. To build it locally:
uv sync --group docs
uv run python -m sphinx -b html -W --keep-going docs docs/_build/html
Open docs/_build/html/index.html. The build executes every example, so a
broken example fails the build.
Start at docs/user/conventions.rst before
interpreting any number: units, the Cartesian crystal frame, square-Lambert
storage, the orientation convention and the space-group origin choice are all
load-bearing, and they are what make de-ebsd's output comparable to EMsoft's
and kikuchipy's. The design notes under docs/dev/ cover the
architecture, the dynamical algorithm, the Monte Carlo, the indexers and the
validation numbers.
Validation
EMsoft is the oracle (validation only). The script compares a simulated master pattern with EMsoft references by per-pixel Pearson correlation of the Lambert maps -- scale invariant, so normalization differences do not matter:
uv run python scripts/validate_master_pattern.py --material ni
uv run python scripts/validate_master_pattern.py --material si \
--mc /path/to/Si_MC.h5 --device cuda
Ni uses kikuchipy's bundled master pattern and runs with no external files. Si
needs a local EMsoft Si_MC.h5 reference run (not redistributed here) -- point
--mc or DE_EBSD_SI_MC at your copy.
Si r = 1.0000 at native npx-500 against Si_MC.h5, and Ni r = 1.00000
against a matched-settings EMsoft master; cubic and tetragonal phases, single-
and multi-component, agree to that precision. The npx-500 Si master (about two
million directions) computes in about 10 s (fp32) on a Pascal TITAN X, roughly
10 times faster than EMsoft on a 24-thread CPU for a full energy-resolved
master. Monoclinic settings and one hexagonal intensity residual are the open
items; see the validation page of the design notes.
Development
uv run pytest
uv run ruff check
uv run ruff format --check
License
GPL-3.0-or-later. See LICENSE and NOTICE for the work this package is built on.
Metadata
Release files for de-ebsd 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| de_ebsd-0.2.0.tar.gz | 198.3 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| de_ebsd-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 396.7 kB
Release files / de_ebsd-0.2.0.tar.gz
| Download URL | de_ebsd-0.2.0.tar.gz |
|---|---|
| Size | 198.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
89b0da2dfbc44e4022bea4fa912cb07f5241f3f21f65c912d7b0ea06b4e4fe75
|
|
BLAKE2b-256 checksum How to use checksums |
f0e6a97c70b2bcf3e22dd5b73b162f8302d814a290be632857a568567c2d8144
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / de_ebsd-0.2.0-py3-none-any.whl
| Download URL | de_ebsd-0.2.0-py3-none-any.whl |
|---|---|
| Size | 198.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b1fd9618725c2e16abbb6bfe1a0917a37882cae4eae1b6b79ed0b240ca476a4f
|
|
BLAKE2b-256 checksum How to use checksums |
a6c3a239dcd887e12fd030dfb2048898ded0c35482e5799fccb3ace8f4ac33d6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logSecurity for de-ebsd 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for de_ebsd-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.