Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2187b25
Check the fitted detector rotation in the overfocus optimizer test
uellue Oct 12, 2026
3f10a32
Compare inverted rays with the inverted model's center in test_invert…
uellue Oct 12, 2026
f22dd3a
Dispatch cos/sin on the argument type instead of always using SymPy
uellue Oct 12, 2026
3342ff2
Remove value check from adjust_flip_factor() so that it works with ja…
uellue Oct 12, 2026
dd69cc8
Fix lambdify(args=...), which always raised a TypeError
uellue Oct 12, 2026
b08c68d
Implement Model4DSTEM.derive() with dataclasses.replace()
uellue Oct 12, 2026
7f3ce2f
Pass _one from trace() to _components() for consistency
uellue Oct 12, 2026
bf4a7df
Pass fix points to solvers as float64 instead of float32
uellue Oct 12, 2026
7be6c92
Fit both flip factors in solve_coords_points() instead of a continuou…
uellue Oct 12, 2026
269ad1c
Fit camera length with the model's diffraction geometry in solve_came…
uellue Oct 12, 2026
05e4121
Reject strings in Model4DSTEM.normalize_types() and name the field in…
uellue Oct 12, 2026
1659c81
Seed random test inputs per test and relax descan deviation tolerance
uellue Oct 12, 2026
f0646b4
Share the least-squares call of the solvers in one helper
uellue Oct 12, 2026
e391d0c
Remove duplicated regression residual and descan error code from the …
uellue Oct 12, 2026
1216c7a
Reject too few points in the point-based solvers instead of returning…
uellue Oct 12, 2026
38f5d46
Document the solvers and annotate their return types
uellue Oct 12, 2026
86c6fa3
Calculate the UDF transformation matrices per task instead of in __in…
uellue Oct 12, 2026
f1828a8
Clean up the overfocus UDFs
uellue Oct 12, 2026
c2e741c
Replace the backend dispatch of cos/sin with lambdify() at the call s…
uellue Oct 13, 2026
3089b0c
Update the Apptainer image and its pinned requirements to Python 3.14
uellue Oct 13, 2026
2abde36
Move the coverage configuration to pyproject.toml and remove stale files
uellue Oct 13, 2026
bf582e6
Move optax to the test extra and drop Numba constraints for old Pytho…
uellue Oct 13, 2026
ea48329
Read DM4 tags once per file in jeol_dm4 and test it with fake tags
uellue Oct 13, 2026
d2ea398
Calculate the affine maps of the Numba kernels with one shared helper
uellue Oct 13, 2026
55c11c7
Check the number of reflections in test_twothetas instead of truncating
uellue Oct 13, 2026
0b1a538
Include underfocus in the random_model test fixture
uellue Oct 13, 2026
54804e5
Combine the test_correct variants with shared helpers and non-square …
uellue Oct 13, 2026
96c9aae
Treat semiconv consistently as the slope at the source
uellue Oct 14, 2026
7b29c0a
Split CoordinateCorrectionLayout.__init__() into state, figures, widg…
uellue Oct 14, 2026
1b31bd1
Share the row handling of the two fix point tables in the calibration UI
uellue Oct 14, 2026
99efb9a
Move the calculations of the calibration UI into tested functions
uellue Oct 14, 2026
daaec93
Move the instruction texts of the calibration UI layout to module con…
uellue Oct 14, 2026
aaa32f5
Move CalibratedDataset to its own module so jeol_dm4 doesn't import t…
uellue Oct 14, 2026
7daa7ae
Fix the instructions of the calibration UI and order the sections acc…
uellue Oct 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,13 @@ jobs:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

pinned-requirements:
if: false # skip job
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Choose Python version ${{ matrix.python_version }}
- name: 'Choose Python version 3.14'
uses: actions/setup-python@v7
with:
python-version: '3.11'
python-version: '3.14'
- name: install the package
run: python3 -m pip install uv && uv pip install --system .[test,common,diffraction,gui] -r packaging/requirements.txt
- name: run pytest
Expand Down
18 changes: 12 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ third-party dependency you introduce.
The whole library is organized around one central object, **`Model4DSTEM`**
(`common/model.py`), a `jax_dataclasses.pytree_dataclass` holding the full geometric
calibration of a 4D-STEM experiment (overfocus, scan pixel pitch, scan center/rotation,
camera length, detector pixel pitch/center/rotation, semi-convergence angle, flip factor, and
camera length, detector pixel pitch/center/rotation, semi-convergence slope, flip factor, and
a 12-parameter `DescanError`). Because it is a JAX pytree, it is both differentiable and
traceable.

Expand Down Expand Up @@ -88,8 +88,8 @@ Key layers, bottom-up:
4. **`udf/stem_overfocus.py`** — LiberTEM UDFs that apply (3) over a real dataset:
`OverfocusUDF` (reconstruct an overfocus/real-space image) and `CorrectedPickUDF`. Models
are passed wrapped in a `dict` so they can be mutated in place (LiberTEM issue #1780); the
transformation matrices are cached via `lru_cache` and only recomputed when the model
changes.
transformation matrices are calculated in `get_task_data()` and cached per model via
`lru_cache`.

5. **`util/stem_overfocus_sim.py`** — forward simulator (e.g. `smiley()` test object,
`project()`) that generates synthetic 4D-STEM data from a model, used heavily in tests and
Expand All @@ -104,9 +104,10 @@ Key layers, bottom-up:
structure (uses the `diffraction` extra); feeds known-geometry references into the
optimizers.

8. **`ui.py`** — interactive Panel/Bokeh calibration GUI (`gui` extra). `CalibratedDataset`
pairs a dataset with a model; `CoordinateCorrectionLayout` wires sliders/tables to live
re-projection so a user can tune calibration against a displayed dataset.
8. **`ui.py`** — interactive Panel/Bokeh calibration GUI (`gui` extra).
`CoordinateCorrectionLayout` wires sliders/tables to live re-projection so a user can tune
calibration against a displayed dataset. `CalibratedDataset` (`dataset.py`, also importable
from `ui`) pairs a dataset with a model.

### Mental model for making changes

Expand All @@ -115,6 +116,11 @@ Key layers, bottom-up:
you see `try/except TracerBoolConversionError` and `_one`/`flip_factor` style tricks
(constants threaded through so operations stay differentiable instead of using Python
conditionals). Preserve that pattern.
- Model functions are always SymPy-compatible and use SymPy math (`sym.cos`, `sym.pi`, ...);
called directly on floats they may return SymPy numbers. For NumPy or JAX, wrap the call
site with `@lambdify(modules=np|jnp, recurse_for=...)` (or use `lambdify_trace_for`). Create
the lambdified function once, e.g. at module level: each new function object triggers a new
symbolic derivation, so don't decorate inside loops or frequently called functions.
- `trace()` is the single source of truth. Derive relations from it symbolically instead of
hard-coding them: register the derivation in a `GENERATED_FUNCTIONS` registry (collected in
`common/generate.py`) and run the generator. Never edit `common/_generated.py` by hand.
Expand Down
2 changes: 1 addition & 1 deletion examples/stem_overfocus.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1997,7 +1997,7 @@
"outputs": [],
"source": [
"# We assume it is constant over the series\n",
"acceleration_voltage = jeol_dm4.acceleration_from_dm4(descan.dm4)"
"acceleration_voltage = jeol_dm4.acceleration_from_dm4(descan.tags)"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion packaging/overfocus.def
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
bootstrap: docker
from: python:3.11-slim
from: python:3.14-slim

%files
./Microscope-Calibration /Microscope-Calibration
Expand Down
Loading
Loading