ShowDiffraction#
Interactive d-spacing analysis for a single 2D diffraction pattern or a 3D stack (tilt/time series). Find the beam center, pick Bragg spots and rings, read calibrated d-spacings, and calibrate k-space from a known reflection. See the ShowDiffraction tutorial for a worked example.
The primary phase workflow is candidate verification: you usually know which
phases to expect, so build them (library_phase, Phase.from_cubic,
Phase.from_dspacings, or custom phases in the Phase menu) and rank only
those with identify_phase(database) or the candidates only switch.
search_phases() against the built-in library is the fallback for when you
have no candidates in mind; narrow it with an element filter.
Reference data sources: every lattice parameter in the built-in phase library
(PHASE_LIBRARY in showdiffraction/phases.py) is a room-temperature value taken from a
license-clean source cited next to the entry: NIST SRM certificates and NBS
circulars/monographs (US public domain), the Crystallography Open Database
(CC0), or the primary literature. No values come from proprietary compilations
such as the ICDD PDF or Pearson’s Handbook.
The lattice-based phase model enumerates d-spacings and geometric systematic
absences. It does not calculate structure-factor intensities, thermal effects,
or dynamical diffraction; use Phase.from_dspacings when matching against a
measured or literature line table with intensities.
Calibrated radial axes are reported as g = 1/d in 1/Å, not as a 2πg
scattering-vector axis.
Viewer UI#
ShowDiffraction has the shared show_title, show_controls,
controls_collapsed, and show_stats traits (set them after construction). See
Viewer UI controls.
Reference#
- class quantem.widget.showdiffraction.ShowDiffraction(*args: t.Any, **kwargs: t.Any)#
Bases:
StateFileMixin,HtmlExportMixin,AnyWidgetInteractive d-spacing analysis for 2D/3D diffraction patterns.
Pick Bragg spots and rings on the diffraction pattern to measure d-spacings, g-vectors, and inter-spot angles, with sub-pixel Gaussian refinement. Works with a single 2D pattern (SAED) or a 3D stack of patterns, and accepts NumPy arrays, PyTorch tensors, or
Dataset2d/Dataset3d. 4D input is not supported.- Parameters:
data (np.ndarray, torch.Tensor, Dataset2d or Dataset3d) – 2D
(det_rows, det_cols)single pattern or 3D(n_frames, det_rows, det_cols)stack of patterns. A dataset supplies the title and, when its detector axes are a reciprocal length (1/angstrom,1/Å,1/nm), the k calibration.detector_sampling_inv_A (float, optional) – k-space sampling in 1/Å per pixel. Marks the pattern calibrated. A dataset is the source of its own calibration: a value that contradicts it raises.
bright_field_center_px (tuple[float, float], optional) – (row, col) of the diffraction center in pixels. Defaults to the detector center, then auto-detected from the bright-field disk if also no radius.
bright_field_radius_px (float, optional) – Bright-field disk radius in pixels. Defaults to 1/8 of the detector size.
title (str, default "") – Title displayed above the widget.
panel_width_px (int, optional) – Initial diffraction canvas width in CSS pixels.
offline (bool, default False) – Pack every frame into the page so an exported HTML scrubs without a kernel.
device (str, default "auto") – Where the frames are reduced:
"auto"(CUDA, then MPS, then CPU; printed once),"cuda","cuda:N","mps"or"cpu". A tensor stays on its device unless this names another.remove_hot_pixels (bool, default False) – Zero integer counts above three times the 99.9th percentile when the frame maximum exceeds five times it (hot pixels on counting detectors). Off by default so the frames hold the recorded counts; when such pixels are present a one-line notice says how many.
verbose (bool, default True) – Print the loaded shape and device.
**kwargs – Any synced trait, for example
dp_scale_mode="linear"orshow_controls=False.
Examples
>>> import numpy as np >>> from quantem.widget import ShowDiffraction >>> ShowDiffraction(np.random.rand(256, 256)) >>> ShowDiffraction(np.random.rand(20, 128, 128), detector_sampling_inv_A=0.012)
- detect_spots(max_spots: int | None = None, min_distance: int = 6, min_relative: float = 0.1, exclude_radius: float | None = None, noise_sigma: float = 5.0) Self#
Replace the spots with detected Bragg peaks, strongest first.
Candidates come from the
detect_denoiseview; each is then picked on the raw frame like a click (Gaussian-refined whenspot_refine).min_relativeis the contrast floor relative to the strongest peak,noise_sigmathe shot-noise floor in robust sigma units; lower it on frames whose background structure inflates the estimate.
- index_spots(phase: Phase, tol: float = 0.03, angle_tol: float = 3.0) Self#
Index the spots against
phaseand solve the zone axis.Needs a calibrated pattern and a lattice-based phase (
Phase.from_cubicor the full constructor): the zone axis comes from the inter-spot angles, which a d-spacing card does not have. Seelattice.index_spot_vectors().
- run_auto(phase: Phase | None = None, *, max_rings: int = 8, exclude_radius: float | None = None) Self#
Center finding, ring detection, ring fitting, k calibration from
phase(default: the selectedphase_name), recovery of predicted rings and indexing.max_ringskeeps the most significant ring peaks (standard errors above the profile envelope,lattice.detect_ring_radii()). The calibration is verified scale-free, ring-radius ratios against the phase’s d-spacing ratios (lattice.calibration_scale_from_phase()), and is not applied when the rings do not decide it.analysis_statusreports every failed step and the rings the phase does not explain; it is empty on a clean result.
- identify_phase(database, tol: float = 0.03) list[dict]#
Rank an explicit list of candidate phases against the measured d-spacings.
This is the primary verification workflow: build the candidates you expect (
library_phase(),Phase.from_cubic(),Phase.from_dspacings()) and rank only those. Usesearch_phases()when you have no candidates in mind.
- search_phases(*, tol: float = 0.03, elements=None, custom_only: bool | None = None, top_n: int = 10) list[dict]#
Rank the built-in library plus the custom phases against the measured d-spacings.
elements(default: theidentify_elementstrait, for example"Fe, O") keeps only phases whose formula uses those elements; withcustom_only(default: theidentify_custom_onlytrait) the library is skipped.
- classmethod measurements_from_state(state, path: str | Path | None = None)#
Measurement rows (
MEASUREMENT_COLUMNS) from a saved state file or dict; withpaththey are written as CSV (or JSON with the calibration metadata).
- export_html(path: str | Path | None = None, *, title: str | None = None) Path#
Write a standalone HTML viewer with exact float32 frames that opens with no kernel and no network.
- state_dict() dict#
The persistable widget state (calibration, picks, display) as a plain dict.
- load_state_dict(state: dict | str | Path) None#
Restore a
state_dict, its envelope or asavefile; a file of anotherschemaor an unknown key raises before anything is applied.
- summary() None#
Print calibration, center, spots, rings, zone axis and phase match.
- free() None#
Release the frame stack.
del widgetalone does not free it because the traitlets observers pin the widget.
Interactive controls#
Each control mutates the listed synced trait. Analysis buttons send one
_request message ({"action": ..., "args": [...], "seq": n}); Python runs the
action, reports in analysis_status, and clears _request. A UI-test agent acts on the
control, then asserts the trait changed and the canvas repainted (non-zero,
no console error, no NaN frame).
Control |
Trait |
Expected effect |
|---|---|---|
Colormap dropdown |
|
Pattern recolors to the chosen map |
Scale mode dropdown |
|
Intensity mapped linear / log / sqrt |
Invert toggle |
|
Colormap reversed |
Contrast histogram (dual-thumb slider) |
|
Drag either thumb (mouse or touch) for a live preview; traits update once on release |
Center mode dropdown |
|
|
Click to set center (manual) |
|
Crosshair moves; spot d-spacings recompute |
Detect spots |
|
Auto-finds every isolated peak with contrast at least 10% of the strongest ( |
Add / remove spot (click) |
|
Marker placed/removed; d-spacing updates |
Move spot (Move + drag) |
|
Re-picks the spot at the drop position; stale hkl clears |
Spot pick dropdown |
|
Clicked spots are Gaussian-fitted, snapped to the local maximum, or kept exactly as clicked |
Detect rings |
|
Auto-finds every Debye–Scherrer ring that stands at least 5 standard errors of the azimuthal mean above the profile’s lower envelope; peaks are located on the |
Add / remove ring |
|
Ring overlay; ring d-spacing updates |
Calibrate from spot / ring |
|
Sets k-space pixel size from a known d |
Auto button |
|
Runs center, rings, calibration, fit, and indexing in one pass; the calibration is applied only when the ring-radius ratios verify it; status reports failed steps and the rings the phase does not explain |
Phase menu |
|
Selects a library or custom phase for calibration and indexing; custom entries take a full lattice (a, b, c, α, β, γ) and absence rule |
Identify candidates only |
|
Identify ranks only custom phases, skipping the library |
Calibrate from phase |
|
Fits k-space sampling from the ring-to-reflection assignment whose radius ratios match the phase’s d-spacing ratios within 1%; refuses (status says why) when two scales explain the rings about equally or most rings stay unexplained |
Index rings / spots |
|
Fills hkl labels at the current calibration. A ring label needs the ring-radius ratios to agree with the phase and with the calibration (within 3 %); a ring whose d only falls within 3 % of a reflection shows that candidate with |
Exclude menu |
|
Edits wedge/disk regions excluded from analysis |
Draw excluded disk / wedge (drag) |
|
Drag on the pattern to add an excluded region with live preview |
Mask view toggle |
|
Shows or hides excluded-region overlays |
Fit rings |
|
Refines ring radius and width; fwhm column appears |
Fit ellipse / use correction |
|
Measures distortion; the switch circularizes radii |
Profile panel |
|
Radial profile with ring markers; click adds a ring |
Azimuthal panel |
|
Intensity vs azimuth around the outermost ring |
hkl toggle |
|
Shows or hides hkl labels on spots and rings |
Stats toggle |
|
Shows or hides the pattern-statistics readout |
Undo / clear spots and rings |
|
Removes the last or all markers (Ctrl+Z also undoes) |
Center view |
view transform |
Recenters and zooms the view to the diffraction center |
Spot / ring CSV and JSON |
measurement tables |
Downloads the visible measurement table rows |
Refine method dropdown |
|
Picks the center-refinement algorithm (auto / symmetry / phase_corr) |
Refine center |
|
Refines the center; records the method used |
Merge frames (3D) |
|
Align + merge frames; appends the combined pattern |
Element filter box |
|
Restricts the phase search to these elements (e.g. |
Identify phases |
|
Ranked candidate phases with per-line match tables |
Quality panel |
|
Analysis-quality snapshot: center, calibration, ellipse, ring fits, rings the selected phase does not explain, mask coverage |
Ring click in profile |
|
Highlights the picked ring marker (0 clears) |
Frame slider (3D) |
|
Scrubs to a different pattern in the stack |
Pan (drag) / zoom (wheel) |
view transform |
Pattern translates / zooms about the cursor |
Touch: two-finger pinch / drag, double-tap |
view transform |
Pinch zooms about the fingers, two-finger drag pans, double-tap resets the view |
Export → PNG / HTML |
|
Saves the current view as a PNG image or a standalone HTML viewer |
See also
The shared HTML-export contract is documented in html-export.