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. For full 4D-STEM datasets, use Show4DSTEM. See the ShowDiffraction tutorial for a worked example.

Viewer UI#

ShowDiffraction supports the shared ui_mode, show_title, show_controls, controls_collapsed, and show_stats names. See Viewer UI controls.

Reference#

class quantem.widget.showdiffraction.ShowDiffraction(*args: Any, **kwargs: Any)#

Bases: AnyWidget

Interactive 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 optional sub-pixel Gaussian refinement. Works with a single 2D pattern (SAED) or a 3D stack of patterns, and accepts NumPy arrays, PyTorch tensors, or quantem datasets. 4D-STEM stacks are not supported here; use Show4DSTEM instead.

Parameters:
  • data (np.ndarray or torch.Tensor) – 2D (det_rows, det_cols) single pattern or 3D (n_frames, det_rows, det_cols) stack of patterns. A quantem dataset or io LoadResult is also accepted and unwrapped. 4D input raises.

  • k_pixel_size (float, optional) – k-space sampling in 1/Å per pixel. Marks the pattern calibrated.

  • pixel_size (float, optional) – Real-space pixel size in Å.

  • center (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.

  • bf_radius (float, optional) – Bright-field disk radius in pixels. Defaults to 1/8 of the detector size.

  • title (str, default "") – Title displayed above the widget.

  • snap_enabled (bool, default False) – Snap clicked spots to the local intensity maximum.

  • snap_radius (int, default 5) – Search radius in pixels for snapping / Gaussian refinement.

  • spot_refine (bool, default True) – Sub-pixel refine spots with a 2D Gaussian fit on add.

  • dp_scale_mode (str, default "log") – Diffraction display scaling (“linear”, “log”, “sqrt”).

  • ui_mode ({"interactive", "presentation", "report", "minimal"}, default "interactive") – Shared viewer UI preset. Explicit show_* keyword arguments override preset values.

  • show_title (bool, default True) – Show the top title row.

  • show_stats (bool, default True) – Show statistics (mean, min, max, std).

  • show_controls (bool, default True) – Show the control panel.

  • controls_collapsed (bool, default False) – Start with controls hidden while keeping a recoverable Controls button in the frontend.

  • panel_width_px (int, optional) – Initial diffraction canvas width in CSS pixels. The frontend still lets users resize the panel interactively.

  • verbose (bool, default True) – Print load timing on construction.

  • state (str, pathlib.Path, or dict, optional) – Saved state to restore after construction.

Examples

>>> import numpy as np
>>> from quantem.widget.showdiffraction import ShowDiffraction

Single 2D diffraction pattern:

>>> ShowDiffraction(np.random.rand(256, 256))

Calibrated stack of diffraction patterns:

>>> ShowDiffraction(np.random.rand(20, 128, 128), k_pixel_size=0.012)
auto_detect_center() Self#

Auto-detect BF disk center and radius from the summed diffraction stack.

set_center(row: float, col: float) Self#

Set the diffraction center to (row, col) and mark the mode manual.

detect_spots(max_spots: int = 20, min_distance: int = 6, threshold_rel: float = 0.15, exclude_radius: float | None = None, replace: bool = True) Self#

Auto-detect Bragg spots as local maxima in the current frame.

The saturated central beam is log-compressed and high-passed so its halo does not dominate, peaks within exclude_radius of the center are dropped, and the strongest remaining peaks are kept.

Parameters:
  • max_spots (int, default 20) – Maximum number of spots to keep, ordered by prominence.

  • min_distance (int, default 6) – Minimum separation in pixels between detected peaks.

  • threshold_rel (float, default 0.15) – Relative prominence threshold; higher keeps fewer, stronger peaks.

  • exclude_radius (float, optional) – Radius in pixels around the center to ignore. Defaults to the larger of bf_radius and 2 * min_distance.

  • replace (bool, default True) – Clear existing spots before adding the detected ones.

Returns:

The widget, for chaining.

Return type:

Self

detect_rings(max_rings: int = 10, prominence_rel: float = 0.05, min_separation: int = 5, exclude_radius: float | None = None, replace: bool = True) Self#

Auto-detect Debye-Scherrer rings as peaks in the radial profile.

The radial profile is log-compressed and detrended so rings read as peaks, peaks inside exclude_radius are dropped, and the innermost (low-order) rings are kept. Use this instead of detect_spots for polycrystalline / powder patterns.

Parameters:
  • max_rings (int, default 10) – Maximum number of rings to keep.

  • prominence_rel (float, default 0.05) – Peak prominence as a fraction of the detrended profile span.

  • min_separation (int, default 5) – Minimum separation in radial bins between detected peaks.

  • exclude_radius (float, optional) – Radius in pixels around the center to ignore. Defaults to bf_radius.

  • replace (bool, default True) – Clear existing rings before adding the detected ones.

Returns:

The widget, for chaining.

Return type:

Self

add_spot(row: float, col: float) Self#

Add a spot at (row, col). Sub-pixel Gaussian refine if spot_refine, else snap if enabled.

clear_spots() Self#

Remove all spots.

undo_spot() Self#

Remove the most recently added spot.

remove_spot(spot_id: int) Self#

Remove the spot with id spot_id (no-op if not present).

add_ring(radius_px: float) Self#

Add a ring at radius_px from the center (polycrystalline d-spacing pick).

clear_rings() Self#

Remove all rings.

undo_ring() Self#

Remove the most recently added ring.

remove_ring(ring_id: int) Self#

Remove the ring with id ring_id (no-op if not present).

calibrate_from_spot(row: float, col: float, d_known: float) Self#

Calibrate k_pixel_size from a spot of known d-spacing.

Sets the k-space sampling so the spot at (row, col), measured from the current center, corresponds to a d-spacing of d_known.

Parameters:
  • row (float) – Spot position in detector pixels.

  • col (float) – Spot position in detector pixels.

  • d_known (float) – Known d-spacing in Å (must be positive).

Returns:

The widget, for chaining.

Return type:

Self

Raises:

ValueError – If d_known is not positive or the spot lies at the center.

calibrate_from_ring(radius_px: float, d_known: float) Self#

Calibrate k_pixel_size from a ring of known d-spacing.

Sets the k-space sampling so a ring at radius_px from the center corresponds to a d-spacing of d_known.

Parameters:
  • radius_px (float) – Ring radius in detector pixels (must be positive).

  • d_known (float) – Known d-spacing in Å (must be positive).

Returns:

The widget, for chaining.

Return type:

Self

Raises:

ValueError – If d_known or radius_px is not positive.

export_measurements(path: str) Path#

Export the spot and ring measurements to a CSV or JSON file.

The format is inferred from the file extension: .json writes a {"metadata": ..., "measurements": ...} document, anything else writes CSV with the columns in _MEASUREMENT_COLUMNS. This table is fully contained in the saved state, so you do not need to keep it as a separate file – measurements_from_state rebuilds it on demand.

Parameters:

path (str) – Output file path. A .json suffix selects JSON; otherwise CSV.

Returns:

The written file path.

Return type:

pathlib.Path

classmethod measurements_from_state(state, path=None)#

Rebuild the spot/ring measurement table from a saved state.

The saved state already holds every spot and ring, so the measurement table is derived from it – there is no need to keep a separate CSV/JSON export next to the state file. Regenerate it whenever needed, without loading the image data.

Parameters:
  • state (dict, str, or pathlib.Path) – A saved state file path, or an already-loaded state dict/envelope.

  • path (str or pathlib.Path, optional) – Where to write the table (.json selects JSON, otherwise CSV). If omitted, the list of measurement records is returned instead.

Returns:

The measurement records, or the written file path when path is set.

Return type:

list[dict] or pathlib.Path

export_html(path: str | Path | None = None, *, title: str | None = None, **options) Path#

Write a standalone HTML viewer for this widget.

The exported file mounts the live anywidget JS bundle with the current widget state (frames, center, calibration, spots, rings, display settings) and opens in any browser without a Jupyter kernel.

ShowDiffraction always embeds the exact full float32 frames – there is no gallery and no reduced encoding. The mode/encoding/ downsample keys are accepted via **options for cross-widget API compatibility but are treated as no-ops.

Parameters:
  • path (str or pathlib.Path, optional) – Destination HTML path. Defaults to a slug derived from the title.

  • title (str, optional) – Browser page title. Defaults to the widget title or "ShowDiffraction".

  • **options – Accepted and ignored (compatibility with the HTML export protocol).

Returns:

The written file path.

Return type:

pathlib.Path

set_image(data) Self#

Replace data. Preserves display settings, clears spots and rings.

collapse_controls() Self#

Collapse controls behind the frontend Controls button.

expand_controls() Self#

Expand frontend controls when show_controls is enabled.

toggle_controls() Self#

Toggle whether frontend controls start collapsed.

Interactive controls#

Each control mutates the listed synced trait. 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

dp_colormap

Pattern recolors to the chosen map

Scale mode dropdown

dp_scale_mode

Intensity mapped linear / log / sqrt

Invert toggle

dp_invert

Colormap reversed

Contrast min / max sliders

dp_vmin_pct, dp_vmax_pct

Display clamp changes; histogram markers move

Center mode dropdown

center_mode

auto re-detects the BF disk; manual enables click-to-set

Click to set center (manual)

center_row, center_col

Crosshair moves; spot d-spacings recompute

Detect spots

_detect_spots_request, spots

Auto-finds Bragg peaks; d-spacing table fills

Add / remove spot (click)

_spot_add_request, _spot_remove_request, spots

Marker placed/removed; d-spacing updates

Snap toggle

snap_enabled, snap_radius

New spots snap to the nearest local maximum

Refine toggle

spot_refine

Sub-pixel Gaussian fit on/off

Detect rings

_detect_rings_request, rings

Auto-finds Debye–Scherrer rings

Add / remove ring

_ring_add_request, _ring_remove_request, rings

Ring overlay; ring d-spacing updates

Calibrate from spot / ring

_calibrate_from_spot_request, _calibrate_from_ring_request, k_pixel_size

Sets k-space pixel size from a known d

Frame slider (3D)

frame_idx

Scrubs to a different pattern in the stack

Pan (drag) / zoom (wheel)

view transform

Pattern translates / zooms about the cursor

Export → HTML

export_request, export_payload

Writes a standalone HTML viewer

See also

The shared HTML-export contract is documented in html-export.