Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
186 commits
Select commit Hold shift + click to select a range
db68c3a
trying to figure out local curvature change
DavidLanders95 Sep 18, 2025
9678453
About to implement local hessian solution
DavidLanders95 Sep 19, 2025
af4d26d
Opl difference for one local gaussian seems to work
DavidLanders95 Sep 20, 2025
adfcecb
Added gaussian evaluation routine
DavidLanders95 Sep 20, 2025
730d6dd
Gaussian Beams with Aberrated Lens, Aperture and Single Atom seem to …
DavidLanders95 Sep 22, 2025
1d80cc2
Simplified notebook and added large input plane wave to atom
DavidLanders95 Sep 22, 2025
4bb0b43
Ah confused about single atom and how to fit the surface with a cubic
DavidLanders95 Sep 22, 2025
7bbc136
Not working potential
DavidLanders95 Sep 23, 2025
d59d66f
going to simplify further
DavidLanders95 Sep 23, 2025
b01096b
simplified taylor solution
DavidLanders95 Sep 23, 2025
cbb7cac
simplified taylor solution saved
DavidLanders95 Sep 23, 2025
dd1db45
simplified taylor solution - removed tangent and normal calculation
DavidLanders95 Sep 23, 2025
ea34774
single_ray_single_atom works
DavidLanders95 Sep 23, 2025
191aed3
Functional version against handcoded single ray single atom works
DavidLanders95 Sep 23, 2025
2b3dc91
Single atom multiple rays seems to work
DavidLanders95 Sep 23, 2025
a15a629
Rearranged files tidily in neccessary folders
DavidLanders95 Sep 24, 2025
7729158
Aperture working
DavidLanders95 Sep 24, 2025
a38490b
Gaussian Taylor working with simplified design
DavidLanders95 Sep 26, 2025
a3b944e
Removed unneccessary functions
DavidLanders95 Sep 26, 2025
b3a40ee
Fixed up evaluate.py
DavidLanders95 Sep 26, 2025
f0b7bbe
Getting closer to it working well, about to test amplitude component
DavidLanders95 Sep 27, 2025
a262521
Attenuation seems to work correctly.
DavidLanders95 Sep 27, 2025
8bc3915
aberrated lens working again
DavidLanders95 Sep 29, 2025
86bbb2c
Finalising aberrated fit with gaussians.
DavidLanders95 Oct 7, 2025
6bbb588
Aberration of lens with many gaussians beginning to work.
DavidLanders95 Oct 7, 2025
5c64dd2
Renamed aberrated lens
DavidLanders95 Oct 7, 2025
89b564a
adjusted and cleaned evaluate.py functions
DavidLanders95 Oct 7, 2025
e2123f7
Fixed bug in gaussian_taylor where ray.dx was coming out with an extr…
DavidLanders95 Oct 7, 2025
6bb9bb6
Aberrated lens runs with gpu_kernel and is quite fast
DavidLanders95 Oct 7, 2025
6772714
Edited pallas kernel and added single gaussian test
DavidLanders95 Oct 7, 2025
b36bb18
Very important sign change added to gaussian_taylor.
DavidLanders95 Oct 7, 2025
f7255fc
Aberrated lens and individual biprism seem to work.
DavidLanders95 Oct 7, 2025
36b2288
Adjusted settings in aperture notebook
DavidLanders95 Oct 7, 2025
f114e26
Removed unneccessary notebooks
DavidLanders95 Oct 7, 2025
6d3438b
Edited sign of single gaussian so it matches forward model now
DavidLanders95 Oct 7, 2025
f6e0be3
Renamed aberrated lens simple
DavidLanders95 Oct 7, 2025
6ecaebb
Created aberrated probe notebook
DavidLanders95 Oct 7, 2025
5d5daf3
Added complete Krivanek lens to Gaussian Taylor
DavidLanders95 Oct 7, 2025
d419aa7
Added CollinsPropagator, and FourierTransform Functions - Still need …
DavidLanders95 Oct 7, 2025
5587791
Swapped sign conventions where neccessary so that we correctly follow…
DavidLanders95 Oct 10, 2025
c243312
Switched to more common sign convention... and I think it all works now.
DavidLanders95 Oct 10, 2025
f14e05f
Cleaned up tests and added a Fraunhofer test too
DavidLanders95 Oct 10, 2025
8735a18
Aberrated probe with new gaussians works again.
DavidLanders95 Oct 10, 2025
c063156
Fixed amplitude damping coefficient of components, aberrated probe wo…
DavidLanders95 Oct 11, 2025
37ced48
Added make gaussian aperture function to streamline making of an inpu…
DavidLanders95 Oct 11, 2025
90e1b4b
Updated notebooks with convenience changes
DavidLanders95 Oct 11, 2025
43f5460
Added square plane wave input function for convenience
DavidLanders95 Oct 11, 2025
cdc2821
Making sure notebooks still run
DavidLanders95 Oct 11, 2025
15c2d36
Renamed old aberrations test and replaced it with Krivanek Function
DavidLanders95 Oct 11, 2025
70fbd12
Renamed make_gaussian_aperture with make_gaussian_plane_wave_round_ap…
DavidLanders95 Oct 11, 2025
87d09a0
Added krivanek aberrations
DavidLanders95 Oct 11, 2025
be4809b
Tried to build aberrated probe, but it's not so easy.
DavidLanders95 Oct 11, 2025
1d07aba
Removed needless test
DavidLanders95 Oct 13, 2025
e9ce68c
Trying to test aberrated probe but it's really not so easy. About to…
DavidLanders95 Oct 13, 2025
2bce1d8
Aberrated probe seems to work for small aberrations. More testing req…
DavidLanders95 Oct 13, 2025
58c727f
Aberrated probe seems to work for small aberrations. More testing req…
DavidLanders95 Oct 13, 2025
ef4510a
Added angular spectrum propagator too to test against gaussian beams.
DavidLanders95 Oct 13, 2025
2c23217
Added magnetic phase sample and start of notebook
DavidLanders95 Oct 14, 2025
aa71885
rough gaussian physics solution explained with interactive sliders. A…
DavidLanders95 Oct 16, 2025
c3e8ade
Working on reworked formulation of gaussian beam that has no position…
DavidLanders95 Oct 20, 2025
fbcac47
Tidied up notebook a little.
DavidLanders95 Oct 20, 2025
e4d7aa5
Finalised 1D example with ABCD testcase too.
DavidLanders95 Oct 20, 2025
bab5bf7
Finalised 1D example with ABCD testcase too.
DavidLanders95 Oct 20, 2025
42788cd
Finalised 1D example with ABCD testcase too.
DavidLanders95 Oct 20, 2025
f8aaf82
Merge branch 'gaussian_aberrations2' of https://github.com/TemGym/Tem…
DavidLanders95 Oct 20, 2025
b58a10e
Getting ready to lift from notebook to .py file
DavidLanders95 Oct 20, 2025
4729fd9
Simplified Gaussian1D some more in preparation for .py file
DavidLanders95 Oct 22, 2025
441b031
Removed comment
DavidLanders95 Oct 22, 2025
39b3c91
Moved gaussian code to .py file and verified it still works.
DavidLanders95 Oct 22, 2025
4f3e1f5
Gaussian1D and 2D seem to work.
DavidLanders95 Oct 23, 2025
a4b2314
Moved explainer files
DavidLanders95 Oct 23, 2025
4e2ebc5
Modified BeamFactory to work with new gaussian implementation
DavidLanders95 Oct 23, 2025
ed1e447
Removing old files
DavidLanders95 Oct 28, 2025
63589bd
simplified utils.py energy2wavelength
DavidLanders95 Oct 28, 2025
0f0b8df
Updated Gaussian_Action2D function as the final gaussian beam solutio…
DavidLanders95 Oct 28, 2025
d046b36
Edited ray properties of r_xy and d_xy
DavidLanders95 Oct 28, 2025
8a20570
making new notebooks work and added some tests.
DavidLanders95 Oct 28, 2025
e96ce59
Only one notebook left to get working - aperture_probe.ipynb.
DavidLanders95 Oct 28, 2025
8db4849
Tests pass, all notebooks seem correct. Energy and constant phase not…
DavidLanders95 Oct 28, 2025
b5761ad
Updated FresnelPropagator to have prefactor for test
DavidLanders95 Oct 29, 2025
196fecf
Started adding distorted_projector, and seidel aberrated lens
DavidLanders95 Oct 29, 2025
b5e8d6f
Added make_gaussian_grid_input function so we can test the distortion…
DavidLanders95 Oct 29, 2025
0c411a0
Renamed aberrations in aberrations.py
DavidLanders95 Oct 29, 2025
a40cbab
Renamed variables on make_gaussian and added distorted lens .py file.…
DavidLanders95 Oct 29, 2025
fbac2eb
Added distorted lens
DavidLanders95 Oct 29, 2025
f1b48ff
Updated notebooks
DavidLanders95 Oct 29, 2025
5b17dc7
Resetting again before implementing simpler propagator
DavidLanders95 Nov 3, 2025
6ec31fb
Simplifying action update without amplitude for now. Added tests whic…
DavidLanders95 Nov 4, 2025
5201a74
All tests except for fourierABCD propagator pass
DavidLanders95 Nov 4, 2025
6ee2290
Distorted lens works.
DavidLanders95 Nov 4, 2025
e66f1ef
Added spiral distortion solution and fixed zero_phase error in aberra…
DavidLanders95 Nov 5, 2025
c15b4a8
Removed redundant explainer notebooks
DavidLanders95 Nov 5, 2025
9e40f3e
Got magnetic phase sample working again
DavidLanders95 Nov 5, 2025
06204d1
Sample Hologram tidied up a bit but works
DavidLanders95 Nov 6, 2025
b24e16a
Moved files to utils, tidied up sample phase hologram a bit more
DavidLanders95 Nov 6, 2025
39fcb94
on-axis distortion seems to work
DavidLanders95 Nov 6, 2025
96f331e
Off axis and on axis aberrated hologram programmes are made, but I ha…
DavidLanders95 Nov 6, 2025
118eb42
Found parameters to make distortion field
DavidLanders95 Nov 6, 2025
23bb058
Lowered simulation size
DavidLanders95 Nov 6, 2025
26ce3de
Removed old gaussian code
DavidLanders95 Nov 6, 2025
3a2e54b
Removing old code and simplifying gaussian.py
DavidLanders95 Nov 6, 2025
f973125
Tidied up gaussian.py and moved functions to utils.py
DavidLanders95 Nov 6, 2025
06ab5d8
Added offset to input plane wave object
DavidLanders95 Nov 6, 2025
fd7f182
made elaborate sample notebook, but not working yet
DavidLanders95 Nov 7, 2025
6728bda
Created aberrated Sample notebook and it seems to work ok.
DavidLanders95 Nov 7, 2025
e1c8b5b
changes to get model working for malika
DavidLanders95 Nov 7, 2025
3099be9
hard to get chosen fringe spacing to line up with model
DavidLanders95 Nov 13, 2025
44ef710
Down to 6nm fringe spacing and with the equations to automate it
DavidLanders95 Nov 13, 2025
8653238
Updated lens_biprism with some titles.
DavidLanders95 Nov 13, 2025
f2b1ded
Added in overlap factor instead of num_rays argument to square wave
DavidLanders95 Nov 13, 2025
d96fb29
added overlap factor to rectangular_input_wave
DavidLanders95 Nov 13, 2025
54de327
Working with projector lens turned off
DavidLanders95 Nov 13, 2025
464a697
Readded in projector lens
DavidLanders95 Nov 13, 2025
79c7a20
Began to add amplitude back into the gaussian update
DavidLanders95 Nov 14, 2025
51299de
Modified GaussianBeam representation to be a a litle simpler, and add…
DavidLanders95 Nov 14, 2025
c2dba27
Reran notebooks to make sure they still work
DavidLanders95 Nov 14, 2025
d67174f
Simplified _call__ method
DavidLanders95 Nov 14, 2025
dc27f3b
Added and removed some comments
DavidLanders95 Nov 17, 2025
3c5b5fc
Tried to add hologram test against libertem - a bit finicky as everyt…
DavidLanders95 Nov 17, 2025
1c1202a
Add 2D intepolating function and normalisation to square wave input. …
DavidLanders95 Nov 17, 2025
21397c8
renamed variables in libertem_holo_test and added 3D interpolator
DavidLanders95 Nov 18, 2025
b2a596e
Removed constants from utils and put them into new file and simplifie…
DavidLanders95 Nov 18, 2025
9849edf
Linting
DavidLanders95 Nov 18, 2025
7a62b8a
First pass at interpolated sample in holograph aberrations
DavidLanders95 Nov 18, 2025
46ac67b
Added linear phase cube, amplitude, rotation and reference hologram g…
DavidLanders95 Nov 19, 2025
f1352c2
Removed old magnetic sample
DavidLanders95 Nov 19, 2025
931fc54
Added explanation headings to notebook and astigmated hologram compar…
DavidLanders95 Nov 19, 2025
5f470b5
Run first hologram with no astigmatism
DavidLanders95 Nov 19, 2025
648ed1a
Added phase plate visualisation
DavidLanders95 Nov 19, 2025
f0d8ace
Added unit option to gaussian beam
DavidLanders95 Nov 20, 2025
f1195fe
Added single slice of atomic potential, and Atom simulation seems to …
DavidLanders95 Nov 21, 2025
9fbf8ab
Removed old gaussian test notebook that is no longer needed
DavidLanders95 Nov 21, 2025
5e40a98
Glauber solution is fairly complicated, and not sure what integration…
DavidLanders95 Nov 21, 2025
7553a5c
Multislice solution is imperfect, but maybe with higher order integra…
DavidLanders95 Nov 21, 2025
65681b5
Ray method still won't converge with trying some new parameters
DavidLanders95 Nov 23, 2025
99a9aee
Added probe input wavefunction
DavidLanders95 Nov 23, 2025
d8095b4
Added heading to aperture probe notebook
DavidLanders95 Nov 24, 2025
f4bd0ef
Tested STEM probe in atomic scattering - found it also does not work
DavidLanders95 Nov 24, 2025
5035c99
Added update to gaussianbeam.derive to include _one
DavidLanders95 Nov 24, 2025
b0b856f
Tested third order gaussian beam but didn't make a difference.
DavidLanders95 Nov 24, 2025
2ff6f7a
Added a random phase sample
DavidLanders95 Dec 1, 2025
4131b98
Added amorphous carbon sample - no tested and verified Contrast Trans…
DavidLanders95 Dec 1, 2025
44141c3
Ran tests, simulation does seem to work for small non-linear phase pl…
DavidLanders95 Dec 5, 2025
13e866d
Measurement of hologram works with ROI usage from Libertem
DavidLanders95 Dec 8, 2025
2a170a6
Can't measure MIP yet - something is wrong with the scale
DavidLanders95 Dec 8, 2025
3b58c68
Can get ball park MIP measurements. Still off by a volt though.
DavidLanders95 Dec 10, 2025
fd3bea6
Removing buggy phase of square
DavidLanders95 Dec 15, 2025
ccb367f
Managed to get a simulation working - Fringe spacing of utmost impor…
DavidLanders95 Dec 22, 2025
f94394d
God single lens optimisation working, but hard to know what loss func…
DavidLanders95 Feb 4, 2026
90b527e
Updated notebook and it seems to converge.
DavidLanders95 Feb 4, 2026
7ab7e63
SSIM with single lens and lbfgs seems to work ok.
DavidLanders95 Feb 5, 2026
a5c0421
Did quick test with simpsons rule, I am on the right track with gauss…
DavidLanders95 Feb 6, 2026
546ee4a
Checkpoint from VS Code for cloud agent session
DavidLanders95 Feb 6, 2026
85b29b4
Create simplified two-lens notebook with Collins FFT and Optuna integ…
Copilot Feb 6, 2026
9f42abb
Add test script and documentation for simplified two-lens notebook
Copilot Feb 6, 2026
74e2fad
Fix code style issues in test script
Copilot Feb 6, 2026
4ddd459
Add comprehensive implementation summary document
Copilot Feb 6, 2026
26bfc8e
Checkpoint from VS Code for cloud agent session
DavidLanders95 Feb 7, 2026
633f330
Completely rewrite two_lenses_simplified.ipynb with JAX and Optuna
Copilot Feb 7, 2026
e6518ba
Add comprehensive documentation and improve optimization bounds
Copilot Feb 7, 2026
b4fef35
Update README_simplified.md with comprehensive documentation
Copilot Feb 7, 2026
9a23193
Add comprehensive test suite for simplified notebook
Copilot Feb 7, 2026
bfe8f70
Add comprehensive summary document for notebook cleanup
Copilot Feb 7, 2026
3799642
Replace Optuna with JAX BFGS and add full image generation pipeline
Copilot Feb 7, 2026
beadb14
Update README to reflect BFGS optimization and image generation approach
Copilot Feb 7, 2026
05259df
Add BFGS implementation summary document
Copilot Feb 7, 2026
cc717a2
Saving lots of generated files from copilot, some of which might be r…
DavidLanders95 Feb 9, 2026
d3e54ab
Made simplified 2 lens notebook that can fit 5 lenses
DavidLanders95 Feb 9, 2026
8d5ef36
invert n_lens system works when column length is known as a constraint
DavidLanders95 Feb 9, 2026
202c170
Seems to work best with no defocused images, and only one image in fo…
DavidLanders95 Feb 9, 2026
d54cd08
started forward model
DavidLanders95 Feb 9, 2026
a8aabe0
Added electron magnetic components with real lens parameters
DavidLanders95 Feb 10, 2026
acc03fb
Added computation of new constants for lens functions
DavidLanders95 Feb 10, 2026
9135423
Tried to jit evaluate_jax_scan, but it was a failure
DavidLanders95 Feb 10, 2026
cf920e3
Added electromagnetic lens to gaussian also
DavidLanders95 Feb 10, 2026
99e44ad
Added rotation matrix to transfer_matrices
DavidLanders95 Feb 10, 2026
6b8f3b3
added test for constant component
DavidLanders95 Feb 10, 2026
5467ad8
tried to get gaussians working for forward model, but no such luck
DavidLanders95 Feb 10, 2026
d52b375
Made fitting of larger As possible
DavidLanders95 Feb 10, 2026
8c99773
improved lens_inversion
DavidLanders95 Feb 10, 2026
810de99
Can fit 5 lenses with no noise and regularisation
DavidLanders95 Feb 11, 2026
66db8c0
Can work somewhat with noise.
DavidLanders95 Feb 11, 2026
1340d87
tried to simplify lens_inversion a little
DavidLanders95 Feb 11, 2026
a768cc1
Cleaned up lens inversion
DavidLanders95 Feb 12, 2026
aeb1a4a
readded reference voltage
DavidLanders95 Feb 12, 2026
2c45e48
tested tie method to measure phase at aperture plane and removed copi…
DavidLanders95 Feb 12, 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
628 changes: 628 additions & 0 deletions archived/aberrated_probe.ipynb

Large diffs are not rendered by default.

346 changes: 346 additions & 0 deletions archived/aberrated_probe_further_testing.ipynb

Large diffs are not rendered by default.

585 changes: 585 additions & 0 deletions archived/aberrations_visualisation.ipynb

Large diffs are not rendered by default.

388 changes: 388 additions & 0 deletions archived/aperture_image.ipynb

Large diffs are not rendered by default.

794 changes: 794 additions & 0 deletions archived/approximating_functions_with_gaussians_example.ipynb

Large diffs are not rendered by default.

389 changes: 389 additions & 0 deletions archived/fit_three_gaussians.ipynb

Large diffs are not rendered by default.

546 changes: 546 additions & 0 deletions archived/local_gaussians_hessian.ipynb

Large diffs are not rendered by default.

463 changes: 463 additions & 0 deletions archived/local_gaussians_parabola.ipynb

Large diffs are not rendered by default.

598 changes: 0 additions & 598 deletions examples/aberrated_probe.ipynb

This file was deleted.

452 changes: 0 additions & 452 deletions examples/aperture_diffraction.ipynb

This file was deleted.

399 changes: 0 additions & 399 deletions examples/aperture_image.ipynb

This file was deleted.

627 changes: 627 additions & 0 deletions examples/atoms/abtem_HRTEM_example.ipynb

Large diffs are not rendered by default.

1,066 changes: 1,066 additions & 0 deletions examples/atoms/glauber_ray_example.ipynb

Large diffs are not rendered by default.

414 changes: 414 additions & 0 deletions examples/atoms/multiple_rays_single_atom.ipynb

Large diffs are not rendered by default.

377 changes: 377 additions & 0 deletions examples/atoms/single_ray_single_atom_baseline.ipynb

Large diffs are not rendered by default.

603 changes: 0 additions & 603 deletions examples/biprism.ipynb

This file was deleted.

314 changes: 0 additions & 314 deletions examples/decompose_image_into_gaussians.ipynb

This file was deleted.

389 changes: 0 additions & 389 deletions examples/fit_three_gaussians.ipynb

This file was deleted.

521 changes: 521 additions & 0 deletions examples/gaussians/aberrated_aperture_probe.ipynb

Large diffs are not rendered by default.

311 changes: 311 additions & 0 deletions examples/gaussians/aberrated_krivanek_image.ipynb

Large diffs are not rendered by default.

496 changes: 496 additions & 0 deletions examples/gaussians/aberrated_krivanek_lens.ipynb

Large diffs are not rendered by default.

291 changes: 291 additions & 0 deletions examples/gaussians/aperture.ipynb

Large diffs are not rendered by default.

374 changes: 374 additions & 0 deletions examples/gaussians/aperture_probe.ipynb

Large diffs are not rendered by default.

374 changes: 374 additions & 0 deletions examples/gaussians/biprism.ipynb

Large diffs are not rendered by default.

175 changes: 175 additions & 0 deletions examples/gaussians/discontinuous_phase_error_demo.ipynb

Large diffs are not rendered by default.

456 changes: 456 additions & 0 deletions examples/gaussians/distorted_projector_lens.ipynb

Large diffs are not rendered by default.

500 changes: 500 additions & 0 deletions examples/gaussians/lens_biprism.ipynb

Large diffs are not rendered by default.

338 changes: 338 additions & 0 deletions examples/gaussians/magnetic_phase_sample.ipynb

Large diffs are not rendered by default.

420 changes: 420 additions & 0 deletions examples/gaussians/sigmoid_aperture.ipynb

Large diffs are not rendered by default.

241 changes: 241 additions & 0 deletions examples/gaussians/single_gaussian.ipynb

Large diffs are not rendered by default.

338 changes: 338 additions & 0 deletions examples/gaussians/two_gaussians_interfering.ipynb

Large diffs are not rendered by default.

286 changes: 286 additions & 0 deletions examples/holography_distortion/3D_sample_phase_shift.ipynb

Large diffs are not rendered by default.

324 changes: 324 additions & 0 deletions examples/holography_distortion/amorphous_carbon.ipynb

Large diffs are not rendered by default.

716 changes: 716 additions & 0 deletions examples/holography_distortion/hologram_aberrations.ipynb

Large diffs are not rendered by default.

550 changes: 550 additions & 0 deletions examples/holography_distortion/libertem_holo_test_verification.ipynb

Large diffs are not rendered by default.

922 changes: 922 additions & 0 deletions examples/holography_distortion/magnetic_sample.ipynb

Large diffs are not rendered by default.

532 changes: 532 additions & 0 deletions examples/holography_distortion/magnetic_sample_hologram.ipynb

Large diffs are not rendered by default.

492 changes: 492 additions & 0 deletions examples/holography_distortion/off_axis_aberrated_hologram.ipynb

Large diffs are not rendered by default.

268 changes: 268 additions & 0 deletions examples/holography_distortion/on_axis_aberrated_hologram.ipynb

Large diffs are not rendered by default.

1,126 changes: 1,126 additions & 0 deletions examples/lens_inversion/n_lens_forward.ipynb

Large diffs are not rendered by default.

800 changes: 800 additions & 0 deletions examples/lens_inversion/n_lens_inversion.ipynb

Large diffs are not rendered by default.

895 changes: 895 additions & 0 deletions examples/lens_inversion/single_lens.ipynb

Large diffs are not rendered by default.

378 changes: 378 additions & 0 deletions examples/lens_inversion/stashed/ANALYSIS_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,378 @@
# Two-Lens Inverse Problem: Complete Analysis and Solution Strategy

**Date:** February 6, 2026
**Context:** Recovering optical system parameters from defocused intensity images in TEM
**Status:** ✓ Problem is SOLVABLE with proposed strategy

---

## Executive Summary

**Question:** Can we recover optical parameters $(f_1, f_2, z_1, z_2, z_3)$ from defocused intensity measurements?

**Answer:** ✓ **YES**, but with important caveats:

1. **Without wobble:** System has 2-10 discrete solutions (degenerate)
2. **With dual lens wobble + Bayesian optimization + priors:** 1-2 candidate solutions → physical solution selected

**Recommended Approach:**
- Apply linear focal length models to **both** lenses: $\frac{1}{f_i(w_i)} = a_i + b_i \cdot w_i$
- Measure $3 \times 3 \times 3 = 27$ images (3 wobble states each lens, 3 defocus planes)
- Use Bayesian optimization with Gaussian priors on nominal focal lengths
- Bound parameters using microscope geometry constraints

**Expected Performance:** 1-5% parameter recovery accuracy, robust to 2-3% intensity noise

---

## Part 1: Problem Formulation

### System Setup

**Unknown parameters (5):** $(z_1, z_2, z_3, f_1, f_2)$
- $z_1$: Distance from source to lens 1
- $z_2$: Distance from lens 1 to lens 2
- $z_3$: Distance from lens 2 to detector
- $f_1$: Focal length of lens 1
- $f_2$: Focal length of lens 2

**Forward propagation:**
$$\text{Parameters} \xrightarrow{\text{ABCD}} (A, B, C, D) \xrightarrow{\text{Collins FFT}} \text{Intensity Image}$$

**Measurements:**
- Magnification $M$ (measured from experimental setup)
- Defocused intensity images at $N \geq 1$ defocus values
- Can apply wobble to one or both lenses

### Constraint Analysis

**Without wobble, single defocus plane:**
- Unknowns: 5 $(z_1, z_2, z_3, f_1, f_2)$
- Constraints: 2 (A, B from ABCD matrix) + pixel grid constraints
- Status: **Severely underdetermined** (3 DOF free)

**With $N = 3$ defocus planes:**
- Unknowns: 5
- Constraints: $2N = 6$ (ABCD at each defocus) + imaging model
- Status: **Slightly overdetermined** but globally degenerate

**With dual wobble, $M_1 = M_2 = 3$, $N = 3$:**
- Unknowns: 7 $(z_1, z_2, z_3, a_1, b_1, a_2, b_2)$
- Constraints: $2M_1 M_2 N = 54$
- Status: **Highly overdetermined** (7.7× redundancy)

---

## Part 2: Critical Physics Discoveries

### Discovery 1: B/A = z_defocus (Magnification Cancellation)

**Key insight:** From ABCD imaging constraints:
$$A = M, \quad B = M \cdot z_{\text{defocus}}$$

Taking the ratio:
$$\frac{B}{A} = z_{\text{defocus}}$$

**Implication:** Magnification $M$ **completely cancels** in the diffraction kernel!

**Fresnel transfer function:**
$$H(f) = \exp\left(-i\pi\lambda \frac{B}{A} f^2\right) = \exp(-i\pi\lambda z_{\text{defocus}} \cdot f^2)$$

**Consequence:** Fringe spacing depends **only** on defocus distance, not magnification. Two systems at different magnifications produce **identical fringe patterns**, just at different pixel scales.

### Discovery 2: Pixelwise Magnification Matching via Zoom

When $A_{\text{fit}} \neq A_{\text{true}}$, the diffraction patterns have correct physics but different pixel scales on the fixed grid.

**Solution:** Apply magnification-aware zoom in forward model:
```python
zoom_factor = A_fit / A_ref
intensity = jax.image.resize(intensity, (new_size, new_size), method='cubic')
# Pad/crop back to original grid
```

This ensures both diffraction physics (via $B/A$) and pixel scales (via magnification zoom) match measurements.

### Discovery 3: The Missing C Element (Fundamental Degeneracy)

The ABCD matrix has 3 independent parameters:
$$M = \begin{bmatrix} A & B \\ C & D \end{bmatrix}, \quad \det(M) = AD - BC = 1$$

**What you measure from intensity:** $(A, B)$ only (2 values)
- $A$ → magnification
- $B$ → defocus distance
- Intensity patterns → $B/A$ (fringe spacing)

**What you DON'T measure:** $C$ (ray angle transformation)
- Requires measuring ray directions, not just positions
- Ray angles lost when taking intensity $|U|^2$

**Analogy:** Determining height and weight from BMI alone
- Multiple (height, weight) pairs → same BMI
- Similarly: Multiple $(z_1, z_2, z_3, f_1, f_2)$ → same $(A, B)$

**Mathematical condition:** You need global injectivity, not just rank condition!

---

## Part 3: Uniqueness Analysis

### Test Results

| Scenario | Unknowns | Constraints | Jacobian Rank | Discrete Solutions | Condition Number |
|----------|----------|-------------|---|---|---|
| Defocus only | 5 | 6 | 5/5 ✓ | ~10 | 9.67×10¹⁶ |
| Single wobble | 6 | 18 | 6/6 ✓ | ~5 | 1.53×10¹⁵ |
| Wobble+fixed z3 | 5 | 18 | 5/5 ✓ | ~2 | 7.62×10¹¹ |
| **Dual wobble** | **7** | **54** | **7/7 ✓** | **~1-2** | **5.98×10¹³** |

### Key Finding: Local ≠ Global Uniqueness

**Full-rank Jacobian** ($\text{rank} = n$) means:
- Infinitesimal parameter perturbations → change observables
- **Locally unique** solution (no neighbors at same loss)

**BUT doesn't prevent:**
- Multiple discrete solutions (far apart)
- Each fitting data equally well
- **NOT globally unique**

**Reason:** Nonlinear systems can have multiple finite-difference solutions even with locally unique structure.

---

## Part 4: Recommended Solution Strategy

### Strategy Comparison

| Criterion | Defocus Only | Wobble | Wobble+z3 | **Dual Wobble** |
|-----------|---|---|---|---|
| Unknowns | 5 | 6 | 5 | **7** |
| Constraints | 6 | 18 | 18 | **54** |
| Overdetermin. | 1.2× | 3× | 3.6× | **7.7×** |
| Solutions | ~10 | ~5 | ~2 | **~1-2** |
| Stability | Poor | Good | Excellent | **Excellent** |
| Priors Needed | Strong | Moderate | Weak | **Weak** |
| **Overall Score** | 18/100 | 44/100 | 60/100 | **73/100** |

### Recommended Implementation

#### 1. Experimental Setup

- **Lens 1 wobble states:** $M_1 = 3-5$ (e.g., voltage settings)
- **Lens 2 wobble states:** $M_2 = 3-5$ (e.g., current settings)
- **Defocus planes:** $N = 3-4$ per wobble combination
- **Total measurements:** $27-100$ images → $54-200$ ABCD constraints

#### 2. Linear Focal Length Models

For each lens, focal length varies linearly with wobble:
$$\frac{1}{f_1(w_1)} = a_1 + b_1 \cdot w_1$$
$$\frac{1}{f_2(w_2)} = a_2 + b_2 \cdot w_2$$

where $w_1, w_2$ are **known** wobble parameters (measured experimental settings).

**Validity:** Linear approximation valid for small wobble ranges (~±10-20% focal length change).

#### 3. Bayesian Optimization Framework

**Why Bayesian over gradient descent?**
- Handles discrete solution modes naturally
- Incorporates priors probabilistically
- Respects bounds automatically
- Provides uncertainty quantification
- More robust to non-convex losses

**Recommended library:** `optuna` (Tree-structured Parzen Estimator)

**Parameter bounds:**
```python
bounds = {
'z1': (10e-6, 100e-6), # 10-100 µm (microscope geometry)
'z2': (200e-6, 1000e-6), # 0.2-1.0 mm
'z3': (0.5, 2.0), # 0.5-2.0 m
'a1': (20000, 60000), # Around 1/f1_nominal
'b1': (100, 1000), # Wobble sensitivity
'a2': (1000, 4000), # Around 1/f2_nominal
'b2': (50, 200), # Wobble sensitivity
}
```

**Gaussian priors on nominal focal lengths:**
```python
priors = {
'a1': NormalDist(1/f1_nominal, 0.1*1/f1_nominal), # ±10% uncertainty
'a2': NormalDist(1/f2_nominal, 0.1*1/f2_nominal), # ±10% uncertainty
}
```

#### 4. Objective Function Structure

```
L = L_data + λ_prior * L_prior
```

Where:
- $L_{\text{data}} = \sum_{\text{images}} ||I_{\text{predicted}} - I_{\text{measured}}||^2$ (L2 intensity loss)
- $L_{\text{prior}} = -\log p(a_1) - \log p(a_2)$ (negative log-likelihood of priors)
- $\lambda_{\text{prior}}$ = prior weight (tune: 0.01-1.0)

#### 5. Solution Selection

After optimization:
1. **Identify top 10 solutions** (lowest loss)
2. **Cluster to find modes** (DBSCAN on normalized parameters)
3. **Evaluate posterior probability** (combining data fit + prior)
4. **Select best mode** (highest posterior probability)
5. **Refine with gradient descent** (optional, for fine-tuning)

---

## Part 5: Mathematical Foundation

### Why Discrete Solutions Exist

**Simple example:** Circle-parabola intersection
$$x^2 + y^2 = 1, \quad y = x^2$$

**Equations:** 2
**Unknowns:** 2
**Solutions:** 2 (at $x = \pm 0.786, y = 0.618$)

Even with "equation count = unknown count", multiple solutions exist!

**Root cause:** Nonlinearity. The observables don't form a **globally injective** map.

### Your Problem: The Observer Equation

The forward map is:
$$F: (z_1, z_2, z_3, f_1, f_2) \mapsto (I_1, I_2, \ldots, I_{27})$$

where $I_j$ is the $j$-th intensity image.

**Key insight:** This map is not injective
$$F(\mathbf{p}_1) = F(\mathbf{p}_2) \neq \text{} \mathbf{p}_1 = \mathbf{p}_2$$

Multiple parameter sets produce **identical** inverse outputs (same $(A,B)$ sequences).

### Global Injectivity Condition

Standard uniqueness requires **local** injectivity:
$$\text{rank}(\nabla F) = n \quad \text{✓ Have this}$$

But also need **global** injectivity:
$$F(\mathbf{p}) \text{ is one-to-one on feasible domain} \quad \text{✗ Don't have this}$$

**Solution:** Add constraints (priors, bounds, wobble diversity) to make the problem **effectively** globally injective.

---

## Part 6: Expected Performance

### Parameter Recovery Accuracy

| Parameter | Without Wobble | With Dual Wobble + Priors |
|-----------|---|---|
| $z_1$ | ±30% | ±2-5% |
| $z_2$ | ±40% | ±2-5% |
| $z_3$ | Not recoverable | ±5-10% |
| $f_1$ | ±50% | ±1-3% |
| $f_2$ | ±25% | ±1-3% |

### Robustness

- **Intensity noise:** ~2-3% before convergence issues
- **Model mismatch:** Recovers parameters corresponding to "best fit" even if model not perfect
- **Wobble nonlinearity:** Use polynomial model if linear invalid
- **Number of solutions:** 1-2 with priors (vs 10+ without)

### Computational Cost

- **Forward evaluations:** ~200 (Bayesian optimization trials)
- **Time per evaluation:** ~0.1-1 second (Collins FFT on GPU)
- **Total optimization time:** 1-3 hours wall-clock
- **Memory:** ~1-2 GB GPU

---

## Part 7: Implementation Checklist

- [ ] **Physics:** Verify Collins FFT with JAX implementation
- [ ] **Forward model:** Add dual wobble capability to forward model
- [ ] **Measurements:** Collect/simulate 27+ images at different wobble/defocus combinations
- [ ] **Installation:** `pip install optuna scipy numpy jax`
- [ ] **Bayesian setup:** Define bounds, priors, objective function
- [ ] **Optimization:** Run for 200-300 trials
- [ ] **Analysis:** Identify modes, compute posteriors
- [ ] **Validation:** Compare recovered vs. true parameters
- [ ] **Refinement:** Fine-tune with gradient descent (optional)

---

## Part 8: Alternative Approaches

### If Wobble Not Available
- **Option 1:** Fix $z_3$ by direct measurement → reduces to 5 unknowns, 18 constraints
- **Option 2:** Use stronger priors on all parameters → Bayesian inference on fewer measurements
- **Option 3:** Measure phase (via holography) → provides C element → uniquely determines system

### If Bayesian Optimization Too Slow
- **Option 1:** Use scikit-optimize (Gaussian Process) for slower but smoother search
- **Option 2:** Train neural network surrogate on synthetic data, use for initialization
- **Option 3:** Use genetic algorithms for global search, refine with BFGS

### If Priors Unavailable
- **Option 1:** Use bounds alone + multi-start gradient descent with clustering
- **Option 2:** Incorporate semi-supervised learning (weak labels)
- **Option 3:** Add geometric constraints from microscope design

---

## Part 9: Key Takeaways

1. **Problem is solvable** with dual wobble + Bayesian optimization
2. **Discrete degeneracy is fundamental** to measuring intensity alone (missing C element)
3. **Priors are essential** to select physical solution from discrete modes
4. **Wobble provides diversity** that breaks degeneracy by varying responses differently
5. **Condition number improves dramatically** with dual wobble (×10³ better)
6. **Nonlinear = subtle pitfalls:** Equation count alone insufficient for uniqueness

---

## References & Further Reading

### Collins Integral & Fresnel Diffraction
- Collins, S. A. (1970). "Lens-system diffraction integral." J. Opt. Soc. Am. 60(9)
- Goodman, J. W. (2005). "Introduction to Fourier Optics" - Chapter 5 on ABCD matrices

### Bayesian Optimization
- Optuna documentation: https://optuna.readthedocs.io/
- Shahriari et al. (2016). "Taking the Human Out of the Loop: A Review of Bayesian Optimization"

### Inverse Problems & Uniqueness
- Vogel, C. R. (2002). "Computational Methods for Inverse Problems"
- Tarantola, A. (2005). "Inverse Problem Theory and Methods for Model Parameter Estimation"

---

## Appendix: Code Structure Summary

### Main Files
- `two_lenses.ipynb` - Full notebook with forward model, optimization, analysis
- `bayesian_dual_wobble_guide.md` - Detailed implementation guide with code examples
- `uniqueness_analysis.py` - Comprehensive uniqueness tests (single, dual wobble)
- `degeneracy_explanation.py` - Demonstrates why degeneracy exists
- `strategy_comparison_plot.py` - Visual comparison of all approaches

### Key Functions
- `collins_propagate_fft()` - Core diffraction calculation
- `forward_intensity_collins_two_lens()` - Full forward model with magnification zoom
- `full_abcd_2lens()` - ABCD matrix for two-lens system
- `test_dual_lens_wobble()` - Uniqueness testing
- `objective_with_priors()` - Bayesian objective function

---

**Last Updated:** February 6, 2026
**Status:** Complete analysis with recommended solution strategy
**Next Step:** Implement Bayesian optimization framework with real measurements
Loading