laue-torch 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- laue_torch-0.1.0/LICENSE +53 -0
- laue_torch-0.1.0/MANIFEST.in +21 -0
- laue_torch-0.1.0/PKG-INFO +186 -0
- laue_torch-0.1.0/README.md +155 -0
- laue_torch-0.1.0/examples/tutorial_coded_aperture_voxel.py +300 -0
- laue_torch-0.1.0/examples/tutorial_per_voxel_odf.py +166 -0
- laue_torch-0.1.0/laue_torch/__init__.py +63 -0
- laue_torch-0.1.0/laue_torch/cli.py +164 -0
- laue_torch-0.1.0/laue_torch/coded_aperture/__init__.py +70 -0
- laue_torch-0.1.0/laue_torch/coded_aperture/absorption.py +59 -0
- laue_torch-0.1.0/laue_torch/coded_aperture/autofocus.py +302 -0
- laue_torch-0.1.0/laue_torch/coded_aperture/baseline_twostage.py +164 -0
- laue_torch-0.1.0/laue_torch/coded_aperture/io_h5.py +186 -0
- laue_torch-0.1.0/laue_torch/coded_aperture/landscape.py +288 -0
- laue_torch-0.1.0/laue_torch/coded_aperture/mask.py +421 -0
- laue_torch-0.1.0/laue_torch/coded_aperture/mask2d.py +423 -0
- laue_torch-0.1.0/laue_torch/coded_aperture/mask_spectral.py +232 -0
- laue_torch-0.1.0/laue_torch/distributions.py +375 -0
- laue_torch-0.1.0/laue_torch/forward.py +510 -0
- laue_torch-0.1.0/laue_torch/geometry.py +168 -0
- laue_torch-0.1.0/laue_torch/io.py +206 -0
- laue_torch-0.1.0/laue_torch/jointfit/__init__.py +79 -0
- laue_torch-0.1.0/laue_torch/jointfit/amplitudes.py +170 -0
- laue_torch-0.1.0/laue_torch/jointfit/design.py +169 -0
- laue_torch-0.1.0/laue_torch/jointfit/footprint.py +279 -0
- laue_torch-0.1.0/laue_torch/jointfit/model.py +351 -0
- laue_torch-0.1.0/laue_torch/jointfit/select.py +211 -0
- laue_torch-0.1.0/laue_torch/jointfit/synthetic.py +239 -0
- laue_torch-0.1.0/laue_torch/nye.py +284 -0
- laue_torch-0.1.0/laue_torch/odf.py +111 -0
- laue_torch-0.1.0/laue_torch/rasterize.py +417 -0
- laue_torch-0.1.0/laue_torch/realdata/__init__.py +84 -0
- laue_torch-0.1.0/laue_torch/realdata/coded_aperture_loader.py +90 -0
- laue_torch-0.1.0/laue_torch/realdata/depth_resolved.py +544 -0
- laue_torch-0.1.0/laue_torch/realdata/driver.py +276 -0
- laue_torch-0.1.0/laue_torch/realdata/geometry.py +233 -0
- laue_torch-0.1.0/laue_torch/realdata/io.py +154 -0
- laue_torch-0.1.0/laue_torch/realdata/multi_grain.py +618 -0
- laue_torch-0.1.0/laue_torch/realdata/multi_voxel_tv.py +245 -0
- laue_torch-0.1.0/laue_torch/realdata/plots.py +264 -0
- laue_torch-0.1.0/laue_torch/realdata/reference_grain.py +191 -0
- laue_torch-0.1.0/laue_torch/realdata/validate.py +392 -0
- laue_torch-0.1.0/laue_torch/spectrum.py +175 -0
- laue_torch-0.1.0/laue_torch/symmetry.py +75 -0
- laue_torch-0.1.0/laue_torch/synthetic.py +119 -0
- laue_torch-0.1.0/laue_torch/uncertainty.py +85 -0
- laue_torch-0.1.0/laue_torch/wire_scan.py +124 -0
- laue_torch-0.1.0/laue_torch.egg-info/PKG-INFO +186 -0
- laue_torch-0.1.0/laue_torch.egg-info/SOURCES.txt +83 -0
- laue_torch-0.1.0/laue_torch.egg-info/dependency_links.txt +1 -0
- laue_torch-0.1.0/laue_torch.egg-info/entry_points.txt +2 -0
- laue_torch-0.1.0/laue_torch.egg-info/requires.txt +15 -0
- laue_torch-0.1.0/laue_torch.egg-info/top_level.txt +1 -0
- laue_torch-0.1.0/pyproject.toml +71 -0
- laue_torch-0.1.0/setup.cfg +4 -0
- laue_torch-0.1.0/tests/__init__.py +0 -0
- laue_torch-0.1.0/tests/conftest.py +72 -0
- laue_torch-0.1.0/tests/test_autofocus_annealing.py +211 -0
- laue_torch-0.1.0/tests/test_autofocus_synthetic.py +268 -0
- laue_torch-0.1.0/tests/test_baseline_twostage.py +94 -0
- laue_torch-0.1.0/tests/test_calibration.py +244 -0
- laue_torch-0.1.0/tests/test_coded_aperture_devices.py +254 -0
- laue_torch-0.1.0/tests/test_coded_aperture_forward.py +262 -0
- laue_torch-0.1.0/tests/test_coded_aperture_landscape.py +189 -0
- laue_torch-0.1.0/tests/test_coded_aperture_loader.py +223 -0
- laue_torch-0.1.0/tests/test_coded_aperture_mask.py +342 -0
- laue_torch-0.1.0/tests/test_coded_aperture_mask2d.py +281 -0
- laue_torch-0.1.0/tests/test_coded_aperture_multilevel.py +179 -0
- laue_torch-0.1.0/tests/test_depth_resolved_posterior.py +167 -0
- laue_torch-0.1.0/tests/test_depth_resolved_strain.py +194 -0
- laue_torch-0.1.0/tests/test_depth_resolved_synthetic.py +222 -0
- laue_torch-0.1.0/tests/test_distributions.py +103 -0
- laue_torch-0.1.0/tests/test_grad.py +198 -0
- laue_torch-0.1.0/tests/test_jointfit_amplitudes.py +282 -0
- laue_torch-0.1.0/tests/test_jointfit_footprint.py +338 -0
- laue_torch-0.1.0/tests/test_jointfit_select.py +155 -0
- laue_torch-0.1.0/tests/test_jointfit_splat.py +195 -0
- laue_torch-0.1.0/tests/test_jointfit_streak_splat.py +192 -0
- laue_torch-0.1.0/tests/test_jointfit_synthetic.py +272 -0
- laue_torch-0.1.0/tests/test_mixture_and_nye.py +97 -0
- laue_torch-0.1.0/tests/test_multi_voxel_tv.py +198 -0
- laue_torch-0.1.0/tests/test_parity.py +176 -0
- laue_torch-0.1.0/tests/test_source_offset.py +132 -0
- laue_torch-0.1.0/tests/test_symmetry_contract.py +159 -0
- laue_torch-0.1.0/tests/test_wire_scan.py +57 -0
laue_torch-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
Copyright (c) 2024, UChicago Argonne, LLC
|
|
2
|
+
|
|
3
|
+
All Rights Reserved
|
|
4
|
+
|
|
5
|
+
LaueMatching: rapid and robust indexing of Laue diffraction patterns
|
|
6
|
+
|
|
7
|
+
Materials Physics and Engineering
|
|
8
|
+
Computational X-ray Science
|
|
9
|
+
Advanced Photon Source
|
|
10
|
+
Argonne National Laboratory
|
|
11
|
+
|
|
12
|
+
Contributing Authors:
|
|
13
|
+
Hemant Sharma (hsharma@anl.gov)
|
|
14
|
+
|
|
15
|
+
OPEN SOURCE LICENSE
|
|
16
|
+
|
|
17
|
+
Redistribution and use in source and binary forms, with or without
|
|
18
|
+
modification, are permitted provided that the following conditions are met:
|
|
19
|
+
|
|
20
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
21
|
+
this list of conditions and the following disclaimer. Software changes,
|
|
22
|
+
modifications, or derivative works, should be noted with comments and
|
|
23
|
+
the author and organization's name.
|
|
24
|
+
|
|
25
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
26
|
+
this list of conditions and the following disclaimer in the documentation
|
|
27
|
+
and/or other materials provided with the distribution.
|
|
28
|
+
|
|
29
|
+
3. Neither the names of UChicago Argonne, LLC or the Department of Energy
|
|
30
|
+
nor the names of its contributors may be used to endorse or promote
|
|
31
|
+
products derived from this software without specific prior written
|
|
32
|
+
permission.
|
|
33
|
+
|
|
34
|
+
4. The software and the end-user documentation included with the
|
|
35
|
+
redistribution, if any, must include the following acknowledgment:
|
|
36
|
+
|
|
37
|
+
"This product includes software produced by UChicago Argonne, LLC
|
|
38
|
+
under Contract No. DE-AC02-06CH11357 with the Department of Energy."
|
|
39
|
+
|
|
40
|
+
****************************************************************************
|
|
41
|
+
|
|
42
|
+
DISCLAIMER
|
|
43
|
+
|
|
44
|
+
THE SOFTWARE IS SUPPLIED "AS IS" WITHOUT WARRANTY OF ANY KIND.
|
|
45
|
+
|
|
46
|
+
Neither the United States GOVERNMENT, nor the United States Department
|
|
47
|
+
of Energy, NOR UChicago Argonne, LLC, nor any of their employees, makes
|
|
48
|
+
any warranty, express or implied, or assumes any legal liability or
|
|
49
|
+
responsibility for the accuracy, completeness, or usefulness of any
|
|
50
|
+
information, data, apparatus, product, or process disclosed, or
|
|
51
|
+
represents that its use would not infringe privately owned rights.
|
|
52
|
+
|
|
53
|
+
****************************************************************************
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# setuptools' default sdist picks up package modules but NOT conftest.py,
|
|
2
|
+
# tests/__init__.py or examples/ -- without this file the shipped test suite
|
|
3
|
+
# is unrunnable (no fixtures) and the tutorials are absent.
|
|
4
|
+
include LICENSE
|
|
5
|
+
include README.md
|
|
6
|
+
include pyproject.toml
|
|
7
|
+
|
|
8
|
+
recursive-include tests *.py
|
|
9
|
+
recursive-include examples *.py
|
|
10
|
+
|
|
11
|
+
# Belt-and-braces against the unpublished research tree. It lives OUTSIDE this
|
|
12
|
+
# directory (repo-root research/, git-excluded) and pyproject uses an explicit
|
|
13
|
+
# packages= list, so these should be unreachable -- but a sdist that silently
|
|
14
|
+
# grows a report/ directory is a disclosure, not a bug report.
|
|
15
|
+
prune report
|
|
16
|
+
prune experiments
|
|
17
|
+
prune research
|
|
18
|
+
|
|
19
|
+
global-exclude __pycache__
|
|
20
|
+
global-exclude *.py[cod]
|
|
21
|
+
global-exclude .DS_Store
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: laue-torch
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Differentiable PyTorch forward model for white-beam Laue microdiffraction, with per-voxel orientation- and strain-distribution (ODF/SDF) recovery, coded-aperture depth resolution, and joint multi-grain fitting.
|
|
5
|
+
Author-email: Hemant Sharma <hsharma@anl.gov>
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/AdvancedPhotonSource/LaueMatching
|
|
8
|
+
Project-URL: Repository, https://github.com/AdvancedPhotonSource/LaueMatching
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: numpy>=1.20
|
|
18
|
+
Requires-Dist: torch>=2.0
|
|
19
|
+
Requires-Dist: h5py>=3.0
|
|
20
|
+
Requires-Dist: Pillow>=9.0
|
|
21
|
+
Requires-Dist: scipy>=1.7
|
|
22
|
+
Requires-Dist: midas-stress>=0.11.0
|
|
23
|
+
Requires-Dist: midas-hkls>=0.9.0
|
|
24
|
+
Requires-Dist: midas-invert>=0.1.1
|
|
25
|
+
Provides-Extra: viz
|
|
26
|
+
Requires-Dist: matplotlib>=3.5; extra == "viz"
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
29
|
+
Requires-Dist: matplotlib>=3.5; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# `laue_torch`
|
|
33
|
+
|
|
34
|
+
A fully differentiable PyTorch forward model for white-beam Laue
|
|
35
|
+
micro-diffraction, plus a per-voxel orientation- and strain-distribution
|
|
36
|
+
function (ODF / SDF) recovery pipeline that runs on top of any
|
|
37
|
+
conventional Laue indexer.
|
|
38
|
+
|
|
39
|
+
The package is built as a drop-in **refinement** stage downstream of the
|
|
40
|
+
existing [LaueMatching](https://github.com/AdvancedPhotonSource/LaueMatching)
|
|
41
|
+
pipeline: LaueMatching's coarse-grid indexer (or any equivalent) gives
|
|
42
|
+
an approximate mean orientation per voxel; `laue_torch` refines the
|
|
43
|
+
*distribution* parameters around that mean from peak shape, with
|
|
44
|
+
analytic gradients through every step of the forward map.
|
|
45
|
+
|
|
46
|
+
## Highlights
|
|
47
|
+
|
|
48
|
+
- **Differentiable forward**: parity-tested against the reference
|
|
49
|
+
NumPy/C simulator (94/94 spot match on the canonical test case);
|
|
50
|
+
passes a strict `torch.autograd.gradcheck` on the geometry path for
|
|
51
|
+
every parameter group (orientation, strain, lattice, detector pose).
|
|
52
|
+
- **Distribution-level recovery**: tangent-Gaussian on SO(3) for
|
|
53
|
+
unimodal mosaic; mixture for twins / sub-grain modes; multivariate
|
|
54
|
+
Gaussian on Voigt-6 strain.
|
|
55
|
+
- **Tensor GND density**: Nye's dislocation density tensor follows
|
|
56
|
+
analytically from the recovered per-voxel ODF gradient; FCC slip-
|
|
57
|
+
system projection helper included.
|
|
58
|
+
- **Posterior uncertainty**: Laplace approximation at convergence
|
|
59
|
+
gives per-parameter marginal credible intervals.
|
|
60
|
+
- **Hessian eigenanalysis**: explicit identification of the physical
|
|
61
|
+
degeneracies of polychromatic Laue (hydrostatic-strain null, lattice
|
|
62
|
+
scale null, $P_z\!\leftrightarrow\!$lattice trade-off, etc.).
|
|
63
|
+
- **Real-data adapter**: reads LaueMatching post-processed H5 output
|
|
64
|
+
and runs the per-voxel ODF refinement with one function call.
|
|
65
|
+
|
|
66
|
+
## Quick start
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
import torch
|
|
70
|
+
from laue_torch import LaueForwardModel, generate_hkls, parse_params
|
|
71
|
+
|
|
72
|
+
p = parse_params("simulation/params_sim.txt")
|
|
73
|
+
hkls = generate_hkls(p.sg_num, p.lattice, p.E_hi)
|
|
74
|
+
t = p.to_tensors()
|
|
75
|
+
|
|
76
|
+
model = LaueForwardModel(
|
|
77
|
+
hkls=hkls, n_pix=t["n_pix"], px_size=t["px_size"],
|
|
78
|
+
psf_sigma=t["psf_sigma"],
|
|
79
|
+
rotation="quat", strain_mode="voigt",
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
U = torch.tensor([[1.0, 0.0, 0.0, 0.0]], dtype=torch.float64) # (G, 4) quaternion
|
|
83
|
+
img = model(U, t["lattice"], t["P"], t["R"]) # (Nx, Ny)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Per-voxel ODF refinement on real data
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from laue_torch import parse_params
|
|
90
|
+
from laue_torch.realdata import LaueScanLoader, VoxelODFRefiner, plot_sigma_map
|
|
91
|
+
|
|
92
|
+
params = parse_params("simulation/params_sim.txt")
|
|
93
|
+
refiner = VoxelODFRefiner(params, sigma_init_deg=1.0,
|
|
94
|
+
M_render=128, n_steps=500)
|
|
95
|
+
|
|
96
|
+
results = []
|
|
97
|
+
for voxel in LaueScanLoader("/path/to/scan/"):
|
|
98
|
+
results.append(refiner.refine(voxel))
|
|
99
|
+
|
|
100
|
+
plot_sigma_map(results, grid_shape=(20, 20),
|
|
101
|
+
out_path="sigma_map.png", show_posterior=True)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Each `result` is a `VoxelODFResult` carrying:
|
|
105
|
+
|
|
106
|
+
- `U_mean`: refined mean orientation (3×3)
|
|
107
|
+
- `sigma_U_deg`: recovered isotropic mosaic spread
|
|
108
|
+
- `posterior_sigma_U_deg`: 1-σ Laplace posterior on `sigma_U_deg`
|
|
109
|
+
- `final_loss`, `n_steps`, `dt_s`, ...
|
|
110
|
+
|
|
111
|
+
For multi-voxel scans, the `plots` module supplies `plot_sigma_map`,
|
|
112
|
+
`plot_orientation_map`, `plot_gnd_map` (which computes Nye's tensor on
|
|
113
|
+
the recovered orientation field by central differences).
|
|
114
|
+
|
|
115
|
+
## Tutorial
|
|
116
|
+
|
|
117
|
+
The single-script tutorial `examples/tutorial_per_voxel_odf.py` walks
|
|
118
|
+
through the full synthetic pipeline end-to-end (forward → render →
|
|
119
|
+
Adam → Nye tensor → Laplace posterior) in $\sim$3 min on CPU.
|
|
120
|
+
|
|
121
|
+
## Synthetic experiments
|
|
122
|
+
|
|
123
|
+
The numerical experiments that characterised this package (mosaic-spread
|
|
124
|
+
recovery, twin-variant identification, intragranular gradients and the Nye
|
|
125
|
+
tensor, Laplace-posterior calibration, basin-of-convergence and Hessian
|
|
126
|
+
eigenanalysis studies) are research scripts and are **not** distributed with the
|
|
127
|
+
package.
|
|
128
|
+
|
|
129
|
+
What ships instead is the part that transfers: the two runnable tutorials in
|
|
130
|
+
`examples/`, and the test suite, which exercises every one of those code paths
|
|
131
|
+
against synthetic ground truth.
|
|
132
|
+
|
|
133
|
+
## Tests
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
cd packages/laue_torch
|
|
137
|
+
pip install -e '.[dev]'
|
|
138
|
+
KMP_DUPLICATE_LIB_OK=TRUE pytest
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
219 tests cover parity against the NumPy/C reference, gradient flow /
|
|
142
|
+
`gradcheck` on every parameter group, calibration recovery, distribution
|
|
143
|
+
moments, mixture / Nye correctness, coded-aperture and joint-fit paths, and a
|
|
144
|
+
contract test pinning the `midas-stress` misorientation convention.
|
|
145
|
+
|
|
146
|
+
The four parity tests need a LaueMatching **checkout** (they read
|
|
147
|
+
`simulation/params_sim.txt` and the reference simulator). Run from an installed
|
|
148
|
+
wheel instead and they skip cleanly rather than failing.
|
|
149
|
+
|
|
150
|
+
## Documentation
|
|
151
|
+
|
|
152
|
+
- [`docs/torch-forward-model.md`](../../docs/torch-forward-model.md) — math + API
|
|
153
|
+
reference: the forward map, every differentiable parameter group, and the
|
|
154
|
+
parameterisation choices.
|
|
155
|
+
- `examples/` — two runnable tutorials: per-voxel ODF recovery, and the
|
|
156
|
+
coded-aperture voxel workflow.
|
|
157
|
+
- The test suite is the other reference. `tests/test_parity.py` pins the forward
|
|
158
|
+
model against the repository's NumPy/C simulator, and
|
|
159
|
+
`tests/test_grad.py` gradchecks every parameter group.
|
|
160
|
+
|
|
161
|
+
## Dependencies
|
|
162
|
+
|
|
163
|
+
Runtime (installed automatically):
|
|
164
|
+
|
|
165
|
+
- `torch >= 2.0`, `numpy >= 1.20`, `scipy >= 1.7`, `h5py >= 3.0`, `Pillow >= 9.0`
|
|
166
|
+
- `midas-stress >= 0.11.0` — symmetry-reduced misorientation. Note it returns
|
|
167
|
+
**radians**; `laue_torch.symmetry` converts to degrees in one place.
|
|
168
|
+
- `midas-hkls >= 0.9.0` — lattice, space group, hkl generation, absorption
|
|
169
|
+
- `midas-invert >= 0.1.1` — Laplace uncertainty, fit / loss primitives
|
|
170
|
+
|
|
171
|
+
Optional: `matplotlib >= 3.5` (`pip install 'laue-torch[viz]'`) for the plotting
|
|
172
|
+
helpers in `laue_torch.realdata.plots`.
|
|
173
|
+
|
|
174
|
+
## Citation
|
|
175
|
+
|
|
176
|
+
If you use this package, please cite the LaueMatching pipeline that produces the
|
|
177
|
+
indexer seed orientations:
|
|
178
|
+
|
|
179
|
+
> H. Sharma, D. Sheyfer, R. Harder, J.Z. Tischler.
|
|
180
|
+
> *LaueMatching: an approach for rapid and robust indexing of Laue
|
|
181
|
+
> diffraction patterns.*
|
|
182
|
+
> J. Appl. Cryst. **59**, 552–563 (2026).
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
BSD-3-Clause (UChicago Argonne, LLC) — see [`LICENSE`](LICENSE).
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# `laue_torch`
|
|
2
|
+
|
|
3
|
+
A fully differentiable PyTorch forward model for white-beam Laue
|
|
4
|
+
micro-diffraction, plus a per-voxel orientation- and strain-distribution
|
|
5
|
+
function (ODF / SDF) recovery pipeline that runs on top of any
|
|
6
|
+
conventional Laue indexer.
|
|
7
|
+
|
|
8
|
+
The package is built as a drop-in **refinement** stage downstream of the
|
|
9
|
+
existing [LaueMatching](https://github.com/AdvancedPhotonSource/LaueMatching)
|
|
10
|
+
pipeline: LaueMatching's coarse-grid indexer (or any equivalent) gives
|
|
11
|
+
an approximate mean orientation per voxel; `laue_torch` refines the
|
|
12
|
+
*distribution* parameters around that mean from peak shape, with
|
|
13
|
+
analytic gradients through every step of the forward map.
|
|
14
|
+
|
|
15
|
+
## Highlights
|
|
16
|
+
|
|
17
|
+
- **Differentiable forward**: parity-tested against the reference
|
|
18
|
+
NumPy/C simulator (94/94 spot match on the canonical test case);
|
|
19
|
+
passes a strict `torch.autograd.gradcheck` on the geometry path for
|
|
20
|
+
every parameter group (orientation, strain, lattice, detector pose).
|
|
21
|
+
- **Distribution-level recovery**: tangent-Gaussian on SO(3) for
|
|
22
|
+
unimodal mosaic; mixture for twins / sub-grain modes; multivariate
|
|
23
|
+
Gaussian on Voigt-6 strain.
|
|
24
|
+
- **Tensor GND density**: Nye's dislocation density tensor follows
|
|
25
|
+
analytically from the recovered per-voxel ODF gradient; FCC slip-
|
|
26
|
+
system projection helper included.
|
|
27
|
+
- **Posterior uncertainty**: Laplace approximation at convergence
|
|
28
|
+
gives per-parameter marginal credible intervals.
|
|
29
|
+
- **Hessian eigenanalysis**: explicit identification of the physical
|
|
30
|
+
degeneracies of polychromatic Laue (hydrostatic-strain null, lattice
|
|
31
|
+
scale null, $P_z\!\leftrightarrow\!$lattice trade-off, etc.).
|
|
32
|
+
- **Real-data adapter**: reads LaueMatching post-processed H5 output
|
|
33
|
+
and runs the per-voxel ODF refinement with one function call.
|
|
34
|
+
|
|
35
|
+
## Quick start
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
import torch
|
|
39
|
+
from laue_torch import LaueForwardModel, generate_hkls, parse_params
|
|
40
|
+
|
|
41
|
+
p = parse_params("simulation/params_sim.txt")
|
|
42
|
+
hkls = generate_hkls(p.sg_num, p.lattice, p.E_hi)
|
|
43
|
+
t = p.to_tensors()
|
|
44
|
+
|
|
45
|
+
model = LaueForwardModel(
|
|
46
|
+
hkls=hkls, n_pix=t["n_pix"], px_size=t["px_size"],
|
|
47
|
+
psf_sigma=t["psf_sigma"],
|
|
48
|
+
rotation="quat", strain_mode="voigt",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
U = torch.tensor([[1.0, 0.0, 0.0, 0.0]], dtype=torch.float64) # (G, 4) quaternion
|
|
52
|
+
img = model(U, t["lattice"], t["P"], t["R"]) # (Nx, Ny)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Per-voxel ODF refinement on real data
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from laue_torch import parse_params
|
|
59
|
+
from laue_torch.realdata import LaueScanLoader, VoxelODFRefiner, plot_sigma_map
|
|
60
|
+
|
|
61
|
+
params = parse_params("simulation/params_sim.txt")
|
|
62
|
+
refiner = VoxelODFRefiner(params, sigma_init_deg=1.0,
|
|
63
|
+
M_render=128, n_steps=500)
|
|
64
|
+
|
|
65
|
+
results = []
|
|
66
|
+
for voxel in LaueScanLoader("/path/to/scan/"):
|
|
67
|
+
results.append(refiner.refine(voxel))
|
|
68
|
+
|
|
69
|
+
plot_sigma_map(results, grid_shape=(20, 20),
|
|
70
|
+
out_path="sigma_map.png", show_posterior=True)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Each `result` is a `VoxelODFResult` carrying:
|
|
74
|
+
|
|
75
|
+
- `U_mean`: refined mean orientation (3×3)
|
|
76
|
+
- `sigma_U_deg`: recovered isotropic mosaic spread
|
|
77
|
+
- `posterior_sigma_U_deg`: 1-σ Laplace posterior on `sigma_U_deg`
|
|
78
|
+
- `final_loss`, `n_steps`, `dt_s`, ...
|
|
79
|
+
|
|
80
|
+
For multi-voxel scans, the `plots` module supplies `plot_sigma_map`,
|
|
81
|
+
`plot_orientation_map`, `plot_gnd_map` (which computes Nye's tensor on
|
|
82
|
+
the recovered orientation field by central differences).
|
|
83
|
+
|
|
84
|
+
## Tutorial
|
|
85
|
+
|
|
86
|
+
The single-script tutorial `examples/tutorial_per_voxel_odf.py` walks
|
|
87
|
+
through the full synthetic pipeline end-to-end (forward → render →
|
|
88
|
+
Adam → Nye tensor → Laplace posterior) in $\sim$3 min on CPU.
|
|
89
|
+
|
|
90
|
+
## Synthetic experiments
|
|
91
|
+
|
|
92
|
+
The numerical experiments that characterised this package (mosaic-spread
|
|
93
|
+
recovery, twin-variant identification, intragranular gradients and the Nye
|
|
94
|
+
tensor, Laplace-posterior calibration, basin-of-convergence and Hessian
|
|
95
|
+
eigenanalysis studies) are research scripts and are **not** distributed with the
|
|
96
|
+
package.
|
|
97
|
+
|
|
98
|
+
What ships instead is the part that transfers: the two runnable tutorials in
|
|
99
|
+
`examples/`, and the test suite, which exercises every one of those code paths
|
|
100
|
+
against synthetic ground truth.
|
|
101
|
+
|
|
102
|
+
## Tests
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
cd packages/laue_torch
|
|
106
|
+
pip install -e '.[dev]'
|
|
107
|
+
KMP_DUPLICATE_LIB_OK=TRUE pytest
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
219 tests cover parity against the NumPy/C reference, gradient flow /
|
|
111
|
+
`gradcheck` on every parameter group, calibration recovery, distribution
|
|
112
|
+
moments, mixture / Nye correctness, coded-aperture and joint-fit paths, and a
|
|
113
|
+
contract test pinning the `midas-stress` misorientation convention.
|
|
114
|
+
|
|
115
|
+
The four parity tests need a LaueMatching **checkout** (they read
|
|
116
|
+
`simulation/params_sim.txt` and the reference simulator). Run from an installed
|
|
117
|
+
wheel instead and they skip cleanly rather than failing.
|
|
118
|
+
|
|
119
|
+
## Documentation
|
|
120
|
+
|
|
121
|
+
- [`docs/torch-forward-model.md`](../../docs/torch-forward-model.md) — math + API
|
|
122
|
+
reference: the forward map, every differentiable parameter group, and the
|
|
123
|
+
parameterisation choices.
|
|
124
|
+
- `examples/` — two runnable tutorials: per-voxel ODF recovery, and the
|
|
125
|
+
coded-aperture voxel workflow.
|
|
126
|
+
- The test suite is the other reference. `tests/test_parity.py` pins the forward
|
|
127
|
+
model against the repository's NumPy/C simulator, and
|
|
128
|
+
`tests/test_grad.py` gradchecks every parameter group.
|
|
129
|
+
|
|
130
|
+
## Dependencies
|
|
131
|
+
|
|
132
|
+
Runtime (installed automatically):
|
|
133
|
+
|
|
134
|
+
- `torch >= 2.0`, `numpy >= 1.20`, `scipy >= 1.7`, `h5py >= 3.0`, `Pillow >= 9.0`
|
|
135
|
+
- `midas-stress >= 0.11.0` — symmetry-reduced misorientation. Note it returns
|
|
136
|
+
**radians**; `laue_torch.symmetry` converts to degrees in one place.
|
|
137
|
+
- `midas-hkls >= 0.9.0` — lattice, space group, hkl generation, absorption
|
|
138
|
+
- `midas-invert >= 0.1.1` — Laplace uncertainty, fit / loss primitives
|
|
139
|
+
|
|
140
|
+
Optional: `matplotlib >= 3.5` (`pip install 'laue-torch[viz]'`) for the plotting
|
|
141
|
+
helpers in `laue_torch.realdata.plots`.
|
|
142
|
+
|
|
143
|
+
## Citation
|
|
144
|
+
|
|
145
|
+
If you use this package, please cite the LaueMatching pipeline that produces the
|
|
146
|
+
indexer seed orientations:
|
|
147
|
+
|
|
148
|
+
> H. Sharma, D. Sheyfer, R. Harder, J.Z. Tischler.
|
|
149
|
+
> *LaueMatching: an approach for rapid and robust indexing of Laue
|
|
150
|
+
> diffraction patterns.*
|
|
151
|
+
> J. Appl. Cryst. **59**, 552–563 (2026).
|
|
152
|
+
|
|
153
|
+
## License
|
|
154
|
+
|
|
155
|
+
BSD-3-Clause (UChicago Argonne, LLC) — see [`LICENSE`](LICENSE).
|