Skip to content

Fixes for strain mapping - #271

Open
cophus wants to merge 141 commits into
electronmicroscopy:fitting_models_cleanfrom
cophus:strain-fitting-multi-optimizer
Open

Fixes for strain mapping#271
cophus wants to merge 141 commits into
electronmicroscopy:fitting_models_cleanfrom
cophus:strain-fitting-multi-optimizer

Conversation

@cophus

@cophus cophus commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Some bug fixes for disk detection strain mapping.

cedriclim1 and others added 30 commits June 18, 2026 17:05
…re/update-lockfile-20260629

chore: Update dependencies
…re/update-lockfile-20260706

chore: Update dependencies
create_batch_rays and integrate_rays were decorated with
@torch.compile(mode="reduce-overhead"). Calling them triggers
TorchInductor, which needs a C compiler to build its kernel. On Windows
runners without MSVC (cl.exe) on PATH this raises InductorError, failing
tests/tomography/test_dataset_models.py::TestINRRayMath on windows-latest.

Both are trivial tensor ops (a small fill and a single reduction) and
reduce-overhead is a no-op on CPU, so eager execution is equivalent and
portable across platforms.
…-torch-compile-rays

Remove torch.compile from INR ray helpers for Windows compatibility
…re/update-lockfile-20260713

chore: Update dependencies
…re/update-lockfile-20260720

chore: Update dependencies
…re/update-lockfile-20260727

chore: Update dependencies
get_individual_uv_vectors fell through to pos_state.keys() after writing
NaNs for an unfitted position, raising AttributeError whenever
fit_individual_diffraction_pattern was run with rows=/cols= subsets; skip
to the next position instead. reset(reset_to="individual") now raises a
clear RuntimeError for an unfitted position rather than failing inside
state loading.

StrainMapAutocorrelation.diffraction_mask raised a zero-size-array
ValueError when edge_blend (default 64) exceeded the kept region's
inradius (e.g. any 128x128 detector); clamp edge_blend to the largest
feasible feather with a warning, and raise a clear error when the
threshold masks every pixel.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
probe_centroid built its index grids on the CPU, crashing
make_template_from_data on a CUDA/MPS device. The cepstral batched
fitter forced float64, which MPS does not support at all and consumer
CUDA cards run ~30x slower than float32; float32 is ample for the
~0.01 px peak-fit noise floor (verified identical strain output on the
LFP tutorial dataset).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The correlation map is relu-clamped before the local-maxima search. With a
zero-sum template, a bright unscattered beam imprints a broad negative moat
on the correlation map; weak disk peaks ride below zero there and the clamp
erased them before any threshold applied -- at quasi-vacuum positions of the
LFP tutorial dataset 96% of the map clamped to zero and only 4 of 39 maxima
survived, and even on-particle patterns lost their weakest disks.

Add background_sigma: a Fourier-domain Gaussian high-pass applied to the
correlation product (batched, both fft and rfft paths, also used by the DFT
subpixel refinement) that removes the smooth background so peak intensities
become prominence above the local baseline. BraggVectors detect_disks /
show_detection / correlation_map default to background_sigma="auto" (twice
the central-beam radius); pass None for the previous behavior.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Design decision: keep the correlation map strictly positive so peak
intensities roughly measure the probe-weighted counts under each disk and
min_abs_intensity is always a nonnegative counts-scale threshold. The
previous zero-sum default subtracted the pattern-mean from the correlation,
pushing weak disk peaks below zero where the relu clamp erased them (the
missing-peaks bug on the LFP tutorial data).

make_template_* now default subtract_mean=False; background_sigma (the
Gaussian high-pass) defaults to None everywhere, remaining available for
patterns with a strong smooth background.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One-call utility that shifts the detected peak coordinates so every scan
position shares a common origin: subtracts the supplied per-position
diffraction origins (e.g. the plane-fitted CoM of the central beam) and adds
back a reference origin (default: the scan mean), then recomputes the BVM.
The raw data is never resampled -- the measurements are calibrated, not the
images. Returns a corrected copy by default so repeated calls (re-running a
notebook cell) never double-apply the shift; the shift itself is applied
vectorized on the flat peak table via Vector.flatten()/set_flattened().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ModelDiffraction.preprocess(origins=...) builds a descan-free mean CBED:
each pattern is shifted by (scan-mean origin - its measured origin), e.g.
from the plane-fitted CoM of the central beam, before averaging. Only the
image_ref fit target is built from shifted copies -- the raw data is never
resampled. The existing align=True cross-correlation self-alignment stays
available but is unreliable when diffraction contrast varies across the
scan (on the LFP tutorial data it produced +/-68 px shifts against a true
+/-5 px descan, chasing pattern content instead of the beam); origins takes
precedence when both are given.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… model fitting, and optimizer batched implementation
…odels' into strain-fitting-multi-optimizer

fixing some conflicts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants