beam-infer 1.0.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.
@@ -0,0 +1,24 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Joel Henriksson, Hugo Valim
4
+
5
+ Original work by Joel Henriksson (Lund University, LTH)
6
+ Package integration by Hugo Valim (ESS)
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to deal
10
+ in the Software without restriction, including without limitation the rights
11
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ copies of the Software, and to permit persons to whom the Software is
13
+ furnished to do so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in all
16
+ copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ SOFTWARE.
@@ -0,0 +1,364 @@
1
+ Metadata-Version: 2.4
2
+ Name: beam-infer
3
+ Version: 1.0.0
4
+ Summary: A Python package for beam simulation and parameter inference using raster scanning models
5
+ Author-email: Joel Henriksson <carljoelhenriksson@gmail.com>, Hugo Valim <hugo.valim@ess.eu>
6
+ License: MIT
7
+ Project-URL: Original_Work, https://github.com/juhelh/ess-beam-imaging-inverse-problems
8
+ Keywords: beam,simulation,raster,mcmc,inference,optimization,fitting
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Scientific/Engineering
17
+ Classifier: Topic :: Scientific/Engineering :: Physics
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: numpy>=1.20.0
22
+ Requires-Dist: jax>=0.4.0
23
+ Requires-Dist: jaxlib>=0.4.0
24
+ Requires-Dist: scipy>=1.7.0
25
+ Provides-Extra: gpu
26
+ Requires-Dist: jax[cuda12]>=0.4.0; extra == "gpu"
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
29
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
30
+ Requires-Dist: matplotlib>=3.5.0; extra == "dev"
31
+ Requires-Dist: tqdm>=4.60.0; extra == "dev"
32
+ Requires-Dist: black>=22.0.0; extra == "dev"
33
+ Requires-Dist: flake8>=5.0.0; extra == "dev"
34
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ # Beam-Infer
38
+
39
+ **Beam-Infer** is a Python library for beam parameter inference from raster-scanned images. It provides three high-level wrappers for parameter estimation using optimization and MCMC methods, with full control over configuration while maintaining a simple, stable API.
40
+
41
+ > **Note:** This package is based on the original work by **Joel Henriksson** (Lund University, LTH) from his master's thesis *"Inverse Problems in Proton Beam Imaging at ESS: Analysis and Numerical Methods"*. The core calculation base and algorithms were implemented by Joel Henriksson. This package integrates that work into ESS systems.
42
+ >
43
+ > **Original Repository:** [ess-beam-imaging-inverse-problems](https://github.com/juhelh/ess-beam-imaging-inverse-problems)
44
+
45
+ **Numerical equivalence** to the legacy base implementation (forward model, loss, optimizer pipeline, Poisson MCMC) is tested and documented; see [docs/EQUIVALENCE.md](docs/EQUIVALENCE.md). This package focuses on the calculation layer only; EPICS integration and I/O are handled elsewhere.
46
+
47
+ ## Features
48
+
49
+ - **Complete Pipeline**: `estimate_with_optimizer` handles preprocessing, grid construction, initialization, and optimization
50
+ - **Multistart Optimization**: `run_multistart_minimization` for robust parameter recovery
51
+ - **MCMC Sampling**: `run_mcmc_inference` for Bayesian parameter estimation with uncertainty quantification
52
+ - **Flexible Configuration**: Rich configuration via dataclasses for all inference methods
53
+ - **JAX-based**: Fast, GPU-accelerated computations using JAX
54
+ - **Reproducible**: Optional random seeds for deterministic multistart runs
55
+
56
+ ## Installation
57
+
58
+ ### From Source
59
+
60
+ ```bash
61
+ git clone https://gitlab.esss.lu.se/hugovalim/beam-infer.git
62
+ cd beam-infer
63
+ pip install -e .
64
+ ```
65
+
66
+ ### Development Installation
67
+
68
+ ```bash
69
+ pip install -e ".[dev]"
70
+ ```
71
+
72
+ ## Quick Start
73
+
74
+ ### Full Pipeline (Recommended)
75
+
76
+ The `estimate_with_optimizer` function provides a complete pipeline from raw camera image to estimated parameters:
77
+
78
+ ```python
79
+ import numpy as np
80
+ import beam_infer
81
+
82
+ # Raw camera image (2D numpy array)
83
+ raw_image = np.array(...) # Your image data
84
+
85
+ # Metadata (known quantities)
86
+ meta = beam_infer.Metadata(
87
+ pulse_duration_ms=0.05, # Pulse duration in milliseconds
88
+ fx=39.55, # Horizontal scan frequency (kHz) - optional, fixes if provided
89
+ fy=29.05, # Vertical scan frequency (kHz) - optional, fixes if provided
90
+ )
91
+
92
+ # Configuration
93
+ config = beam_infer.OptimizerConfig(
94
+ max_iterations=100, # Maximum L-BFGS-B iterations per run
95
+ multistart={"n_starts": 5, "type": "uniform"}, # Multistart configuration
96
+ regularization={"params": {"sigx": 0.1, "sigy": 0.1}}, # Optional regularization
97
+ random_seed=42, # Optional: for reproducible multistart runs
98
+ verbose=False, # Print iteration details
99
+ )
100
+
101
+ # Run estimation
102
+ result = beam_infer.estimate_with_optimizer(raw_image, meta=meta, config=config)
103
+
104
+ # Access results
105
+ print(f"Estimated parameters: {result.estimated_parameters}")
106
+ print(f"Final loss: {result.objective_value:.6e}")
107
+ print(f"Success: {result.success}")
108
+ print(f"Crop bounds: {result.crop_bounds}")
109
+ ```
110
+
111
+ ### Multistart Minimization
112
+
113
+ For more control over the optimization process:
114
+
115
+ ```python
116
+ import numpy as np
117
+ import jax.numpy as jnp
118
+ import beam_infer
119
+
120
+ # Preprocessed image and grids (you handle preprocessing)
121
+ observed_image = np.array(...) # Already preprocessed
122
+ X, Y = ... # 2D coordinate grids matching image shape
123
+ t_vals = ... # 1D time array
124
+
125
+ # Initial guess (10 parameters)
126
+ k0 = jnp.array([60.0, 20.0, 13.5, 5.05, 0.0, 0.0, 39.55, 29.05, 0.0, 0.0])
127
+
128
+ # Bounds (optional)
129
+ lower = jnp.array([0.0, 0.0, 2.0, 2.0, -20.0, -20.0, 20.0, 20.0, -np.pi, -np.pi])
130
+ upper = jnp.array([100.0, 50.0, 20.0, 20.0, 20.0, 20.0, 50.0, 50.0, np.pi, np.pi])
131
+
132
+ # Configuration
133
+ config = beam_infer.MinimizationConfig(
134
+ initial_guess=k0,
135
+ bounds=(lower, upper),
136
+ max_iterations=100,
137
+ verbose=False,
138
+ )
139
+
140
+ # Run multistart optimization
141
+ result = beam_infer.run_multistart_minimization(
142
+ observed_image,
143
+ X, Y, t_vals,
144
+ config,
145
+ num_starts=10,
146
+ random_seed=42, # For reproducibility
147
+ )
148
+
149
+ # Access best result
150
+ best = result.best_result
151
+ print(f"Best parameters: {best.estimated_parameters}")
152
+ print(f"Best loss: {best.objective_value:.6e}")
153
+
154
+ # Access all results (sorted by loss)
155
+ for i, r in enumerate(result.results):
156
+ print(f"Run {i}: loss = {r.objective_value:.6e}")
157
+ ```
158
+
159
+ ### MCMC Inference
160
+
161
+ For Bayesian parameter estimation with uncertainty quantification:
162
+
163
+ ```python
164
+ import numpy as np
165
+ import beam_infer
166
+
167
+ # Observed image (counts or normalized intensity)
168
+ observed_image = np.array(...) # 2D image
169
+ X, Y = ... # 2D coordinate grids
170
+ t_vals = ... # 1D time array
171
+
172
+ # Bounds
173
+ lower = np.array([0.0, 0.0, 2.0, 2.0, -20.0, -20.0, 20.0, 20.0, -np.pi, -np.pi])
174
+ upper = np.array([100.0, 50.0, 20.0, 20.0, 20.0, 20.0, 50.0, 50.0, np.pi, np.pi])
175
+
176
+ # MCMC configuration
177
+ config = beam_infer.MCMCConfig(
178
+ lower_bounds=lower,
179
+ upper_bounds=upper,
180
+ num_samples=4000, # Number of samples to collect
181
+ burn_in=1000, # Burn-in period
182
+ thin=2, # Thinning (keep every Nth sample)
183
+ prior_type="uniform", # or "gaussian"
184
+ seed=42, # Random seed
185
+ )
186
+
187
+ # Run MCMC
188
+ result = beam_infer.run_mcmc_inference(observed_image, X, Y, t_vals, config)
189
+
190
+ # Access results
191
+ print(f"Posterior mean: {result.posterior_mean}")
192
+ print(f"Posterior std: {result.posterior_std}")
193
+ print(f"Acceptance rate: {result.acceptance_rate:.2%}")
194
+ print(f"Samples shape: {result.samples.shape}") # (num_samples, 10)
195
+ ```
196
+
197
+ ## Supported Public API
198
+
199
+ The library exposes three main entrypoints plus parallel tempering helpers:
200
+
201
+ 1. **`estimate_with_optimizer`** — Complete pipeline (preprocessing + optimization)
202
+ 2. **`run_multistart_minimization`** — Multistart L-BFGS-B optimization
203
+ 3. **`run_mcmc_inference`** — Metropolis-Hastings MCMC sampling
204
+ 4. **Parallel tempering** — `build_beta_ladder`, `sample_from_prior`, `run_parallel_tempering` for replica-exchange MCMC (see [API Reference](docs/API.md))
205
+
206
+ Each entrypoint has corresponding configuration and result dataclasses. See the [API Reference](docs/API.md) for complete documentation.
207
+
208
+ ## Parameters
209
+
210
+ The beam model uses 10 parameters (in order):
211
+
212
+ | Index | Name | Description | Units |
213
+ |-------|------|-------------|-------|
214
+ | 0 | `Ax` | Horizontal raster amplitude | mm |
215
+ | 1 | `Ay` | Vertical raster amplitude | mm |
216
+ | 2 | `sigx` | Horizontal beam width (std dev) | mm |
217
+ | 3 | `sigy` | Vertical beam width (std dev) | mm |
218
+ | 4 | `cx` | Horizontal center offset | mm |
219
+ | 5 | `cy` | Vertical center offset | mm |
220
+ | 6 | `fx` | Horizontal scan frequency | kHz |
221
+ | 7 | `fy` | Vertical scan frequency | kHz |
222
+ | 8 | `phix` | Horizontal phase offset | radians |
223
+ | 9 | `phiy` | Vertical phase offset | radians |
224
+
225
+ ## Configuration Guide
226
+
227
+ ### OptimizerConfig
228
+
229
+ Controls the full pipeline (`estimate_with_optimizer`):
230
+
231
+ ```python
232
+ config = beam_infer.OptimizerConfig(
233
+ max_iterations=100, # Max L-BFGS-B iterations per run
234
+ multistart={"n_starts": 5, "type": "uniform"}, # Multistart config
235
+ regularization={"params": {"sigx": 0.1}}, # Regularization strengths
236
+ random_seed=42, # Optional: for reproducible multistart
237
+ verbose=False, # Print iteration details
238
+ debug=False, # Return intermediate results
239
+ )
240
+ ```
241
+
242
+ **Multistart options:**
243
+ - `"type": "uniform"` - Uniform random sampling within bounds
244
+ - `"type": "gaussian"` - Gaussian sampling around initial guess
245
+
246
+ **Regularization:**
247
+ - Dictionary mapping parameter names to penalty strengths
248
+ - Penalizes deviation from initial guess: `lambda * (param - param0)^2`
249
+
250
+ ### MinimizationConfig
251
+
252
+ Controls single/multistart optimization:
253
+
254
+ ```python
255
+ config = beam_infer.MinimizationConfig(
256
+ initial_guess=k0, # Initial parameter vector (10-D)
257
+ bounds=(lower, upper), # Optional: parameter bounds
258
+ max_iterations=100, # Max L-BFGS-B iterations
259
+ verbose=False, # Print iteration details
260
+ regularization={"sigx": 0.1}, # Optional: regularization strengths
261
+ )
262
+ ```
263
+
264
+ ### MCMCConfig
265
+
266
+ Controls MCMC sampling:
267
+
268
+ ```python
269
+ config = beam_infer.MCMCConfig(
270
+ lower_bounds=lower, # Lower bounds (10-D array)
271
+ upper_bounds=upper, # Upper bounds (10-D array)
272
+ num_samples=4000, # Number of samples to collect
273
+ burn_in=1000, # Burn-in period
274
+ thin=2, # Thinning interval
275
+ prior_type="uniform", # "uniform" or "gaussian"
276
+ prior_mean=None, # Required for Gaussian prior
277
+ prior_std=None, # Required for Gaussian prior
278
+ proposal_std=None, # Optional: custom proposal std dev
279
+ seed=42, # Random seed
280
+ use_scan=True, # Use lax.scan (faster, default)
281
+ )
282
+ ```
283
+
284
+ ## When to Use Which Method?
285
+
286
+ - **`estimate_with_optimizer`**: Use when you have a raw camera image and want a complete pipeline. Handles preprocessing, grid construction, and optimization automatically.
287
+
288
+ - **`run_multistart_minimization`**: Use when you need more control over preprocessing/grids, or want to run optimization from multiple starting points for robustness.
289
+
290
+ - **`run_mcmc_inference`**: Use when you need uncertainty quantification, want to explore the posterior distribution, or need Bayesian inference.
291
+
292
+ ## Examples
293
+
294
+ See the `examples/` directory for complete examples:
295
+
296
+ - `simple_estimation.py` ⭐ - **Simplest example using only public API** (recommended for beginners)
297
+ - `basic_simulation.py` - Basic beam image generation
298
+ - `parameter_variations.py` - Effects of different parameters
299
+ - `raster_pattern.py` - Visualize raster scanning patterns
300
+ - `inference_example.py` - Parameter recovery from synthetic data
301
+ - `real_image_estimation.py` - **Real snapshot: optimizer + MCMC with comparison**
302
+ - `comprehensive_example.py` - Complete workflow demonstration
303
+
304
+ Run examples:
305
+
306
+ ```bash
307
+ # Simplest example (public API only)
308
+ python -m examples.simple_estimation
309
+
310
+ # Real image: optimizer vs MCMC (requires beam snapshot NPZ in examples/)
311
+ python -m examples.real_image_estimation
312
+
313
+ # Comprehensive example (recommended)
314
+ python -m examples.comprehensive_example
315
+ ```
316
+
317
+ See [examples/README.md](examples/README.md) for detailed documentation on all examples.
318
+
319
+ ## Requirements
320
+
321
+ - Python >= 3.10
322
+ - numpy >= 1.20.0
323
+ - jax >= 0.4.0
324
+ - jaxlib >= 0.4.0
325
+ - scipy >= 1.7.0
326
+
327
+ ### GPU Support (Optional)
328
+
329
+ For GPU acceleration, install JAX with CUDA support:
330
+
331
+ ```bash
332
+ # For CUDA 12.x
333
+ pip install --upgrade "jax[cuda12]" -f https://storage.googleapis.com/jax-releases/jax_cuda_release
334
+
335
+ # Verify GPU detection
336
+ python -c "import jax; print(jax.devices())"
337
+ ```
338
+
339
+ ## Development
340
+
341
+ ### Running Tests
342
+
343
+ ```bash
344
+ # After clone, fetch the reference implementation submodule (for equivalence tests)
345
+ git submodule update --init --recursive
346
+
347
+ pytest tests/
348
+ ```
349
+
350
+ ### Code Formatting
351
+
352
+ ```bash
353
+ black beam_infer/ tests/ examples/
354
+ ```
355
+
356
+ ### Type Checking
357
+
358
+ ```bash
359
+ mypy beam_infer/
360
+ ```
361
+
362
+ ## License
363
+
364
+ MIT License - see LICENSE file for details.