Detector and DPC API#
The detector and DPC namespaces own reusable reductions from
\(I[R_r,R_c,k_r,k_c]\) to detector-shaped or scan-shaped scientific products.
They return numerical arrays; use show_2d for a static figure or a viewer for
interactive exploration.
Start with automatic disk fitting#
from quantem.gpu import detector, io
from quantem.core.visualization import show_2d
data = io.load("gold_master.h5")
bf = detector.bf(data)
adf = detector.adf(data)
show_2d([bf, adf], title=["BF", "ADF"], norm="power_sqrt", cmap="inferno")
The first BF/ADF/DF call estimates the disk center and radius from the mean
diffraction pattern. Calls on the same encoded acquisition reuse that geometry.
Mutable array inputs are fitted again. No prepare or manual fit is needed.
Image |
Default detector selection |
|---|---|
|
From the center through one fitted radius |
|
Between one and two fitted radii |
|
Outside one fitted radius |
Selections stop at the detector boundary. These are sums, not averages.
Keep data open until calculations and viewers finish, then call data.close().

The left panels use shared log contrast. BF and ADF use independent square-root
contrast; their displayed brightness is not a shared count scale. See the
README plotting workflow to
draw the same selection outlines. Pass cmap="inferno" to choose that colormap.
Override the detector selection#
bf = detector.bf(data, bright_field_radius_px=45) # radius in detector pixels
adf = detector.adf(data, inner_radius_px=60, outer_radius_px=85)
df = detector.df(data, inner_radius_px=60)
adf = detector.adf(data, inner_radius_px=60, outer_radius_px=85, bright_field_center_px=(96, 96))
Supply only the values you know. Missing geometry is fitted automatically;
overrides apply to that call and do not replace the cached automatic fit.
bright_field_radius_px (BF) and bright_field_edge_radius_px (ADF/DF) always
mean the bright-field disk radius in pixels. In ADF, it sets
the default one-to-two-radius band; use inner_radius_px and outer_radius_px
for explicit limits in pixels, or inner_angle_mrad and outer_angle_mrad in
milliradians. The unit is in the keyword name; a bound given both ways raises.
Inputs and outputs#
Call |
Input |
Output |
|---|---|---|
|
one supported 4D source |
detector-shaped mean diffraction pattern |
|
2D mean diffraction pattern, or a 4D source whose mean pattern is used |
|
|
2D mean diffraction pattern, or a 4D source whose mean pattern is used; optional convergence semiangle (mrad) |
|
|
a loaded acquisition with a recorded |
the same |
|
2D mean diffraction pattern |
radius in detector pixels at which the bright-field disk falls to half its plateau |
|
2D mean diffraction pattern and the convergence semiangle (mrad) |
|
|
4D source; optional geometry overrides |
scan-shaped bright-field sum |
|
4D source; optional annular limits |
scan-shaped annular dark-field sum |
|
4D source; optional inner limit |
scan-shaped dark-field sum |
|
4D source plus optional detector mask/rotation |
|
The current detector convenience functions return NumPy product arrays after
backend execution. DPCResult.phase, com_row, com_col,
com_row_aligned, and com_col_aligned are float32 scan-shaped arrays.
Inspect the inferred rotation without assembling a notebook-side summary:
dpc_result = dpc.run(data)
dpc_result.report()
The table labels the scan-detector rotation in degrees, the detector-axis swap, and elapsed seconds. DPC’s curl minimum does not resolve the 180° ambiguity; SSB can check the phase polarity before selecting a branch.
Shapes, coordinates, dtypes, and units#
Every input follows (scan_row, scan_column, detector_row, detector_column).
Every BF/DF/ADF and DPC product follows (scan_row, scan_column). Mean
diffraction follows (detector_row, detector_column).
bright_field_center_px=(row, col) is always detector order. Bounds named
*_radius_px are detector pixels. Bounds named *_angle_mrad require convergence-semiangle
calibration in the source metadata. The convenience detector products return
float32 NumPy arrays, even for integer counts. For exact large integer totals,
use the advanced session’s masked_sum_exact described in
the integer-product contract.
DPC moments and phase products are float32.
Errors and unsupported requests#
A milliradian detector limit without
semiangle_mradraises with a corrective instruction; it is never interpreted as pixels.A supplied scan shape whose product differs from the number of diffraction patterns raises rather than reshaping silently.
Missing accelerator capability fails explicitly; it is not reported as GPU work after a hidden CPU fallback.
Row and column components may not be swapped to match a private launch layout.
Provenance#
An application records the source identity, original and loaded shapes, detector bin/crop, source and accumulation dtypes, detector mask or center/radius, calibration and units, selected backend/device, DPC rotation, rotation flip, and package revision. A binned input produces a binned-source product and must not be labeled native detector resolution.
Inspect the fitted disk#
from quantem.gpu import detector, io
mean_dp = detector.mean(data)
center, radius = detector.fit_probe(mean_dp)
show_2d(mean_dp, norm="log_auto", title="Mean diffraction pattern", cmap="inferno")
fit_probe retains the threshold/centroid estimator and estimates disk geometry,
not complex probe phase or aberrations. This explicit call is useful for
checking or drawing the geometry. It is optional for ordinary BF/ADF/DF images.
Calculate DPC#
from quantem.gpu import dpc
result = dpc.run(data)
show_2d(result.phase, title="Integrated DPC phase", cmap="inferno")
Supply scan_detector_rotation_deg (with scan_detector_rotation_flipped) to hold the
scan-detector rotation fixed, or omit it for the DPC rotation search. Inspect
result for the rotation and CoM components: a fitted rotation is
scan_detector_rotation_mod180_deg, known only modulo 180 degrees, and a given
one is scan_detector_rotation_deg. The fitted value lies in [0, 180]: an
unrotated scan fits the end point of the search grid, float32 pi, which reads
180.000005, and 0 and 180 describe the same estimate. DPC does not estimate
SSB aberrations.
For a client that needs several launch products from the same source, use
screening.prepare() and reuse its small derived state instead of traversing
the complete detector volume independently for every product.
Integration boundary#
QuantEM.GPU owns detector geometry, exact reduction arithmetic, CoM/DPC/iDPC math, backend dispatch, and result fields. A consuming application owns when to run the operations, cache admission, memory-policy choices, and presentation.
See BF, DF, and ADF reductions and CoM, DPC, and iDPC for the equations, optimization model, source map, and parity gates.