diff --git a/README.md b/README.md index cfd4c52..6aab848 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,77 @@ -[![Documentation](https://img.shields.io/badge/docs-latest-blue.svg)](https://dosimetry.pages.psi.ch/tracketch/) +[![Documentation](https://img.shields.io/badge/docs-latest-blue.svg)](https://jbrage.github.io/tracketch/) [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) [![Python](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/) [![Tests](https://img.shields.io/badge/tests-pytest-brightgreen.svg)](tests/) -[![HitCount](https://hits.dwyl.com/jbrage/tracketch.svg?style=flat-square&show=unique)](http://hits.dwyl.com/jbrage/tracketch) - - # tracketch A Python toolkit for simulating ion tracks in CR-39 plastic nuclear track -detectors. Given an ion species, energy, and etching conditions, **tracketch** -predicts the track countours, diameter, and depth that would be observed under an -optical microscope after chemical etching. - -

- tracketch logo -

+detectors. Given an ion species, energy, and etching conditions, `tracketch` +predicts the track countours, diameter and length for a given etching duration. +The work is published in the article +[A unified model for etched-track formation in CR-39 detectors using amorphous +track structure theory](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6469212) +by Jeppe Brage Christensen. > **Note** - due to its dependency on -> [libamtrack](https://libamtrack.github.io/), **tracketch** currently runs on +> [libamtrack](https://libamtrack.github.io/), `tracketch` currently runs on > **Linux only**. Most Windows installations support WSL installations. + + + + +
+ tracketch logo +
+ + +Cite as +```bibtex +@article{christensen2026unified, + title={A unified model for etched-track formation in CR-39 detectors using amorphous track structure theory}, + author={Christensen, Jeppe Brage}, + journal={SSRN preprint http://dx.doi.org/10.2139/ssrn.6469212}, + year={2026} +} +``` -> **Note** - This version only supports simulations of ion impinging perpendicular to the CR39 detector surface. Support for 3D track geometries and non-axisymmetric effects is planned for future releases. -> Furthermore, this etch-rate model is calibrated to the detector type and etching conditions used in [Dörschel et al (2003)](https://www.sciencedirect.com/science/article/abs/pii/S1350448702000471). For other detector types and etching conditions, the calibration workflow described in the documentation can be used to re-calibrate the model against experimental data. +> **Note** - This version only supports simulations of ion impinging +> perpendicular to the CR39 detector surface. Support for 3D track geometries +> and non-axisymmetric effects is planned for future releases. +> Furthermore, this etch-rate model is calibrated to the detector type and +> etching conditions used in +> [Dörschel et al (2003)](https://www.sciencedirect.com/science/article/abs/pii/S1350448702000471). +> For other detector types and etching conditions, the calibration workflow +> described in the documentation can be used to re-calibrate the model against +> experimental data. ## Documentation -The documentation is hosted online and includes user guides, API references, and examples: -[Online documentation](https://dosimetry.pages.psi.ch/tracketch/) +The documentation is hosted online and includes user guides, API references, +and examples: [Documentation](https://jbrage.github.io/tracketch/) +A PDF version of the documentation is also available in the `docs/` directory: [tracketch_docs.pdf](docs/tracketch.pdf) ## How it works The simulation follows the same physics chain as the real experiment: -1. **Radial dose distribution (RDD)**: the ion deposits energy radially via - delta-electrons. tracketch computes the 2-D dose map along the ion path using - models from libamtrack (e.g. Cucinotta) and SRIM stopping-power tables. +1. **Dose maps**: the ion deposits energy radially via delta-electrons. + `tracketch` computes the dose map along the ion path using amorphous track + structure models from `libamtrack` (e.g. Cucinotta) and slows down the ion + in the CR-39 detector using `SRIM` stopping-power tables. 2. **Etch-rate model**: a calibrated function converts local dose to local - etch velocity *V(D)*. The bulk (undamaged) material etches at a slower - constant rate *V_bulk*. -3. **Wavefront propagation**: the etchant front is propagated from the - detector surface into the bulk using shortest-path algorithms (Dijkstra or - Fast Marching). The result is an *arrival-time map*. + etch velocity $v_d$. The bulk (undamaged) material etches at a slower + constant rate $v_\text{bulk}$. +3. **Wavefront propagation**: the etchant front is propagated from the detector + surface into the bulk using shortest-path algorithms (Dijkstra or Fast + Marching), analogous to the propagation of a wavefront. The result is an + *arrival-time map*. 4. **Track observables**: iso-time contours of the arrival-time map give the etched track shape at any desired etching duration. -## Etch-rate model selection - -tracketch uses a single default calibration model for all particles: -`"Doerschel_etching"`. - -- The etch-rate model is not selected by `particle_name`. -- Particle selection affects stopping-power and dose physics, not which - etch-rate model file is loaded. -- Users can still load a different etch-rate model explicitly (for example, - a custom re-calibrated model). - -```python -from tracketch import TrackSimulator, load_etchrate_model - -# Explicitly load a custom calibration model if needed. -etch_model = load_etchrate_model("my_custom_model") - -sim = TrackSimulator( - particle_name="12C", - start_energy_MeV_u=270.0, - etch_model=etch_model, -) -``` ## Installation @@ -79,13 +80,14 @@ sim = TrackSimulator( git clone /tracketch cd tracketch -# create a virtual environment and install +# create a virtual environment and install; change "all" to "numba" or "cpp" +# to only install one backend or to skip testing/docs dependencies python3 -m venv .venv source .venv/bin/activate -pip install -e ".[numba]" +pip install -e ".[all]" ``` -This installs tracketch with the Numba-accelerated Dijkstra backend, which +This installs `tracketch` with the Numba-accelerated Dijkstra backend, which works out of the box on any Linux machine. ### Optional: C++ Dijkstra backend @@ -94,11 +96,10 @@ To also install the faster CPP backend, use pip install -e ".[numba,cpp]" cd tracketch/wavefront/dijkstra/cpp python setup_dijkstra.py build_ext --inplace -cd - ``` ## Minimal working example -Check out the tracketch examples in the [`examples/`](examples/) directory. +Check out the `tracketch` examples in the [`examples/`](examples/) directory. ```python import matplotlib.pyplot as plt from tracketch import TrackSimulator @@ -142,7 +143,7 @@ and `symbol` is the element symbol: The available ions depend on the **stopping-power source**: -- **`stopping_power_source="SRIM"` (default)** - uses tabulated SRIM data. +- **`stopping_power_source="SRIM"` (default)** - uses tabulated `SRIM` data. Only the following particles are supported: ```python import tracketch @@ -152,8 +153,8 @@ The available ions depend on the **stopping-power source**: Attempting any other particle raises a `ValueError` with a suggestion to switch source. -- **`stopping_power_source="libamtrack"`** - uses the libamtrack/PSTAR - parametrisation. Accepts any nuclide name recognised by libamtrack, e.g. +- **`stopping_power_source="libamtrack"`** - uses the `libamtrack` + parametrisation. Accepts any nuclide name recognised by `libamtrack`, e.g. `"56Fe"`, `"238U"`, `"28Si"`. ```python @@ -180,7 +181,7 @@ Pass them as `material_name="CR39"` (default) or `material_name="water"`. ## Simulation grid -The simulation operates on a 2D cylindrical grid (*r*, *z*) with these defaults: +The simulation operates on a cylindrical grid (*r*, *z*) with these defaults: | Parameter | Default | Description | |-----------|---------|-------------| @@ -214,11 +215,16 @@ publication-quality results consider doubling `n_points_r` and `n_points_z`. Full API reference and usage guides can be re-built with Sphinx: ```bash +pip install -e ".[docs]" cd docs make html ``` - Then open `docs/_build/html/index.html` in your browser. +Or +```bash +make pdlatex +``` +to build the PDF version of the documentation. ## Project layout @@ -229,7 +235,8 @@ Then open `docs/_build/html/index.html` in your browser. │ │ └── stopping_power/ SRIM data tables and parsing │ ├── etching/ EtchRateModel -- dose -> etch velocity │ ├── simulation/ TrackSimulator -- full model -│ └── wavefront/ Track contour calculation through arrival-time solvers (Dijkstra, FMM) +│ └── wavefront/ Track contour calculation through arrival-time +│ solvers (Dijkstra, FMM) ├── calibration/ Etch-model calibration against experimental data ├── examples/ Runnable example scripts ├── tests/ pytest test suite diff --git a/calibration/benchmark_bragg_corrections.py b/calibration/benchmark_bragg_corrections.py index baa2f97..fe1fee7 100644 --- a/calibration/benchmark_bragg_corrections.py +++ b/calibration/benchmark_bragg_corrections.py @@ -44,7 +44,7 @@ PARTICLES = ["1H", "4He", "7Li", "12C"] SEEDS = [11, 22] POPSIZE = 50 - MAXITER = 300 + MAXITER = 50 TOL = 1e-6 OUTPUT_DIR_NAME = "bragg_benchmark" else: @@ -60,18 +60,14 @@ SMOOTHNESS_WEIGHT = 0.001 -# More general seeded initialization for V(d): -# - build a broader log-dose anchor grid -# - perturb log-velocity increments per seed -ANCHOR_MIN_DOSE_GY = 1e2 -ANCHOR_MAX_DOSE_GY = 1e9 -# Piecewise anchor placement with highest density in 1e5..1e7 Gy. -ANCHOR_MID_MIN_DOSE_GY = 1e4 -ANCHOR_DENSE_MIN_DOSE_GY = 1e5 -ANCHOR_DENSE_MAX_DOSE_GY = 1e8 -ANCHOR_DENSITY_WEIGHTS = (2.0, 3.0, 30.0, 5.0) -# Run one or multiple anchor-count configurations. -ANCHOR_COUNT_USER_OPTIONS = [40] +# Match run_Vd_calibration.py anchor buckets exactly. +# d_Gy = concat([ +# logspace(2, 4, endpoint=False, num=1), +# logspace(4, 5, endpoint=False, num=2), +# logspace(5, 8, endpoint=False, num=8), +# logspace(8, 9, endpoint=True, num=2), +# ]) +ANCHOR_COUNT_USER_OPTIONS = [13] INIT_LOG_INCREMENT_NOISE_STD = 0.08 # Run debris damping in separate configurations. @@ -123,52 +119,24 @@ def _save_track_shape_pngs(models_dict: dict, run_dir: Path) -> list[str]: def _build_user_anchor_dose_grid(anchor_count_user: int) -> np.ndarray: - """Build piecewise log-dose anchors with dense spacing in 1e5..1e8 Gy.""" - if anchor_count_user < 4: - return np.logspace( - np.log10(ANCHOR_MIN_DOSE_GY), - np.log10(ANCHOR_MAX_DOSE_GY), - anchor_count_user, - ) - - dose_edges = np.asarray( + """Build the same anchor-dose grid as run_Vd_calibration.py.""" + user_doses = np.concatenate( [ - ANCHOR_MIN_DOSE_GY, - ANCHOR_MID_MIN_DOSE_GY, - ANCHOR_DENSE_MIN_DOSE_GY, - ANCHOR_DENSE_MAX_DOSE_GY, - ANCHOR_MAX_DOSE_GY, - ], - dtype=float, + np.logspace(2, 4, endpoint=False, num=1), + np.logspace(4, 5, endpoint=False, num=2), + np.logspace(5, 8, endpoint=False, num=8), + np.logspace(8, 9, endpoint=True, num=2), + ] ) - weights = np.asarray(ANCHOR_DENSITY_WEIGHTS, dtype=float) + user_doses = np.unique(user_doses) + user_doses = np.sort(user_doses) - seg_counts = np.maximum( - 1, np.floor(anchor_count_user * weights / weights.sum()).astype(int) - ) - while int(seg_counts.sum()) < anchor_count_user: - seg_counts[int(np.argmax(weights))] += 1 - while int(seg_counts.sum()) > anchor_count_user: - reducible = np.where(seg_counts > 1)[0] - if reducible.size == 0: - break - seg_counts[int(reducible[np.argmin(weights[reducible])])] -= 1 - - segments: list[np.ndarray] = [] - for i, n_pts in enumerate(seg_counts): - seg = np.logspace( - np.log10(dose_edges[i]), - np.log10(dose_edges[i + 1]), - int(n_pts), - endpoint=(i == len(seg_counts) - 1), + if anchor_count_user != len(user_doses): + raise ValueError( + "anchor_count_user must match run_Vd_calibration anchor count " + f"({len(user_doses)}), got {anchor_count_user}" ) - segments.append(seg) - - user_doses = np.sort(np.concatenate(segments)) - # Enforce exact endpoints for reproducibility and requested full range. - user_doses[0] = ANCHOR_MIN_DOSE_GY - user_doses[-1] = ANCHOR_MAX_DOSE_GY return user_doses diff --git a/calibration/figures_calibration/debris_comparison_12C.png b/calibration/figures_calibration/debris_comparison_12C.png new file mode 100644 index 0000000..bdca3a7 Binary files /dev/null and b/calibration/figures_calibration/debris_comparison_12C.png differ diff --git a/calibration/figures_calibration/debris_comparison_1H.png b/calibration/figures_calibration/debris_comparison_1H.png new file mode 100644 index 0000000..b5603bd Binary files /dev/null and b/calibration/figures_calibration/debris_comparison_1H.png differ diff --git a/calibration/figures_calibration/debris_comparison_4He.png b/calibration/figures_calibration/debris_comparison_4He.png new file mode 100644 index 0000000..039520d Binary files /dev/null and b/calibration/figures_calibration/debris_comparison_4He.png differ diff --git a/calibration/figures_calibration/debris_comparison_7Li.png b/calibration/figures_calibration/debris_comparison_7Li.png new file mode 100644 index 0000000..cd542a6 Binary files /dev/null and b/calibration/figures_calibration/debris_comparison_7Li.png differ diff --git a/calibration/figures_calibration/track_shape_12C.png b/calibration/figures_calibration/track_shape_12C.png new file mode 100644 index 0000000..7c23449 Binary files /dev/null and b/calibration/figures_calibration/track_shape_12C.png differ diff --git a/calibration/figures_calibration/track_shape_1H.png b/calibration/figures_calibration/track_shape_1H.png new file mode 100644 index 0000000..435c6a5 Binary files /dev/null and b/calibration/figures_calibration/track_shape_1H.png differ diff --git a/calibration/figures_calibration/track_shape_4He.png b/calibration/figures_calibration/track_shape_4He.png new file mode 100644 index 0000000..27878b3 Binary files /dev/null and b/calibration/figures_calibration/track_shape_4He.png differ diff --git a/calibration/figures_calibration/track_shape_7Li.png b/calibration/figures_calibration/track_shape_7Li.png new file mode 100644 index 0000000..b63a563 Binary files /dev/null and b/calibration/figures_calibration/track_shape_7Li.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_11/track_shape_12C.png b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_11/track_shape_12C.png new file mode 100644 index 0000000..69d906d Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_11/track_shape_12C.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_11/track_shape_1H.png b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_11/track_shape_1H.png new file mode 100644 index 0000000..0e5510d Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_11/track_shape_1H.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_11/track_shape_4He.png b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_11/track_shape_4He.png new file mode 100644 index 0000000..26d2377 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_11/track_shape_4He.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_11/track_shape_7Li.png b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_11/track_shape_7Li.png new file mode 100644 index 0000000..e5123b3 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_11/track_shape_7Li.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_22/track_shape_12C.png b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_22/track_shape_12C.png new file mode 100644 index 0000000..d102230 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_22/track_shape_12C.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_22/track_shape_1H.png b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_22/track_shape_1H.png new file mode 100644 index 0000000..43521d5 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_22/track_shape_1H.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_22/track_shape_4He.png b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_22/track_shape_4He.png new file mode 100644 index 0000000..9b2cdf4 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_22/track_shape_4He.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_22/track_shape_7Li.png b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_22/track_shape_7Li.png new file mode 100644 index 0000000..bc52b3a Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_fit/anchors_13/seed_22/track_shape_7Li.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_11/track_shape_12C.png b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_11/track_shape_12C.png new file mode 100644 index 0000000..24a96b0 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_11/track_shape_12C.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_11/track_shape_1H.png b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_11/track_shape_1H.png new file mode 100644 index 0000000..3be1713 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_11/track_shape_1H.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_11/track_shape_4He.png b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_11/track_shape_4He.png new file mode 100644 index 0000000..455f235 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_11/track_shape_4He.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_11/track_shape_7Li.png b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_11/track_shape_7Li.png new file mode 100644 index 0000000..130021f Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_11/track_shape_7Li.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_22/track_shape_12C.png b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_22/track_shape_12C.png new file mode 100644 index 0000000..d59860b Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_22/track_shape_12C.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_22/track_shape_1H.png b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_22/track_shape_1H.png new file mode 100644 index 0000000..acb3eef Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_22/track_shape_1H.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_22/track_shape_4He.png b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_22/track_shape_4He.png new file mode 100644 index 0000000..0716070 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_22/track_shape_4He.png differ diff --git a/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_22/track_shape_7Li.png b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_22/track_shape_7Li.png new file mode 100644 index 0000000..363ee64 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_0/debris_without/anchors_13/seed_22/track_shape_7Li.png differ diff --git a/calibration/results/bragg_benchmark/bragg_3/debris_fit/anchors_13/seed_11/track_shape_12C.png b/calibration/results/bragg_benchmark/bragg_3/debris_fit/anchors_13/seed_11/track_shape_12C.png new file mode 100644 index 0000000..0c03404 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_3/debris_fit/anchors_13/seed_11/track_shape_12C.png differ diff --git a/calibration/results/bragg_benchmark/bragg_3/debris_fit/anchors_13/seed_11/track_shape_1H.png b/calibration/results/bragg_benchmark/bragg_3/debris_fit/anchors_13/seed_11/track_shape_1H.png new file mode 100644 index 0000000..96dffcf Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_3/debris_fit/anchors_13/seed_11/track_shape_1H.png differ diff --git a/calibration/results/bragg_benchmark/bragg_3/debris_fit/anchors_13/seed_11/track_shape_4He.png b/calibration/results/bragg_benchmark/bragg_3/debris_fit/anchors_13/seed_11/track_shape_4He.png new file mode 100644 index 0000000..024d7ed Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_3/debris_fit/anchors_13/seed_11/track_shape_4He.png differ diff --git a/calibration/results/bragg_benchmark/bragg_3/debris_fit/anchors_13/seed_11/track_shape_7Li.png b/calibration/results/bragg_benchmark/bragg_3/debris_fit/anchors_13/seed_11/track_shape_7Li.png new file mode 100644 index 0000000..c5cd3df Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_3/debris_fit/anchors_13/seed_11/track_shape_7Li.png differ diff --git a/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_11/track_shape_12C.png b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_11/track_shape_12C.png new file mode 100644 index 0000000..946d7a7 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_11/track_shape_12C.png differ diff --git a/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_11/track_shape_1H.png b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_11/track_shape_1H.png new file mode 100644 index 0000000..2c11d68 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_11/track_shape_1H.png differ diff --git a/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_11/track_shape_4He.png b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_11/track_shape_4He.png new file mode 100644 index 0000000..1a7cca3 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_11/track_shape_4He.png differ diff --git a/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_11/track_shape_7Li.png b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_11/track_shape_7Li.png new file mode 100644 index 0000000..0bf960b Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_11/track_shape_7Li.png differ diff --git a/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_22/track_shape_12C.png b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_22/track_shape_12C.png new file mode 100644 index 0000000..1bdbfe1 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_22/track_shape_12C.png differ diff --git a/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_22/track_shape_1H.png b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_22/track_shape_1H.png new file mode 100644 index 0000000..8e9d4bf Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_22/track_shape_1H.png differ diff --git a/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_22/track_shape_4He.png b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_22/track_shape_4He.png new file mode 100644 index 0000000..74e106a Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_22/track_shape_4He.png differ diff --git a/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_22/track_shape_7Li.png b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_22/track_shape_7Li.png new file mode 100644 index 0000000..1daf6df Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_3/debris_without/anchors_13/seed_22/track_shape_7Li.png differ diff --git a/calibration/results/bragg_benchmark/bragg_5/debris_without/anchors_13/seed_11/track_shape_12C.png b/calibration/results/bragg_benchmark/bragg_5/debris_without/anchors_13/seed_11/track_shape_12C.png new file mode 100644 index 0000000..a7d5acd Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_5/debris_without/anchors_13/seed_11/track_shape_12C.png differ diff --git a/calibration/results/bragg_benchmark/bragg_5/debris_without/anchors_13/seed_11/track_shape_1H.png b/calibration/results/bragg_benchmark/bragg_5/debris_without/anchors_13/seed_11/track_shape_1H.png new file mode 100644 index 0000000..0519755 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_5/debris_without/anchors_13/seed_11/track_shape_1H.png differ diff --git a/calibration/results/bragg_benchmark/bragg_5/debris_without/anchors_13/seed_11/track_shape_4He.png b/calibration/results/bragg_benchmark/bragg_5/debris_without/anchors_13/seed_11/track_shape_4He.png new file mode 100644 index 0000000..321e689 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_5/debris_without/anchors_13/seed_11/track_shape_4He.png differ diff --git a/calibration/results/bragg_benchmark/bragg_5/debris_without/anchors_13/seed_11/track_shape_7Li.png b/calibration/results/bragg_benchmark/bragg_5/debris_without/anchors_13/seed_11/track_shape_7Li.png new file mode 100644 index 0000000..4a01f63 Binary files /dev/null and b/calibration/results/bragg_benchmark/bragg_5/debris_without/anchors_13/seed_11/track_shape_7Li.png differ diff --git a/calibration/run_Vd_calibration.py b/calibration/run_Vd_calibration.py index 4a98e58..fd07992 100644 --- a/calibration/run_Vd_calibration.py +++ b/calibration/run_Vd_calibration.py @@ -71,8 +71,8 @@ def starting_guess_v_um_h( if final_fit: # Final-fit profile aligned with benchmark settings - de_popsize = 50 - de_maxiter = 50 + de_popsize = 60 + de_maxiter = 200 de_tol = 1e-6 de_mutation = (0.5, 1.4) de_recombination = 0.9 @@ -100,10 +100,10 @@ def starting_guess_v_um_h( d_Gy = np.concatenate( [ # Match benchmark anchor buckets exactly. - np.logspace(2, 4, endpoint=False, num=1), - np.logspace(4, 5, endpoint=False, num=2), - np.logspace(5, 8, endpoint=False, num=10), - np.logspace(8, 9, endpoint=True, num=3), + np.logspace(2, 4, endpoint=False, num=2), + np.logspace(4, 5, endpoint=False, num=3), + np.logspace(5, 8, endpoint=False, num=9), + np.logspace(8, 9, endpoint=True, num=2), ] ) d_Gy = np.unique(d_Gy) # Remove duplicates @@ -208,9 +208,7 @@ def starting_guess_v_um_h( # uncertainty: when anchors saturate at V_max, this is the most relevant # constraint on the saturation velocity. if np.isfinite(etch_model.V_max_um_h): - etch_model.V_max_uncertainty_um_h = float( - unc["velocity_uncertainties_um_h"][-1] - ) + etch_model.V_max_uncertainty_um_h = float(unc["velocity_uncertainties_um_h"][-1]) # Save results etch_model.name = CALIBRATED_MODEL_NAME @@ -222,11 +220,14 @@ def starting_guess_v_um_h( for entry in sub_dict.values(): entry["simulator"].recalculate_from_current_etch_model() +folder_name = "figures_calibration" if final_fit else "figures_calibration_dev" +os.makedirs(folder_name, exist_ok=True) + if objective_mode in ["both", "shape"]: figs = plot_track_shapes(models_dict["track_shape"], xscale="linear") shape_keys = list(models_dict["track_shape"].keys()) for i, particle in enumerate(shape_keys): - figs[i].savefig(f"figures/track_shape_{particle}.png", dpi=300) + figs[i].savefig(f"{folder_name}/track_shape_{particle}.png", dpi=300) # Debris comparison: contours with vs without damping debris_figs = plot_track_shapes_debris_comparison( @@ -234,15 +235,13 @@ def starting_guess_v_um_h( ) for i, particle in enumerate(shape_keys): debris_figs[i].savefig( - f"figures/debris_comparison_{particle}.png", + f"{folder_name}/debris_comparison_{particle}.png", dpi=300, ) if objective_mode in ["both", "length"]: figs_by_ion = plot_track_length(models_dict["track_length"]) for ion, fig in figs_by_ion.items(): - folder_name = "figures_calibration" if final_fit else "figures_calibration_dev" - os.makedirs(folder_name, exist_ok=True) fig.savefig(f"{folder_name}/track_length_{ion}.png", dpi=300) # %% diff --git a/docs/index.rst b/docs/index.rst index 2587a58..2b90b2c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -4,6 +4,19 @@ tracketch A Python toolkit for simulating track formation in CR-39 nuclear track detectors irradiation with ions. +The work is published in the article +`A unified model for etched-track formation in CR-39 detectors using amorphous +track structure theory +`_ +by Jeppe Brage Christensen. + +.. note:: + + Due to its dependency on `libamtrack `_, + **tracketch** currently runs on **Linux only**. Most Windows installations + support WSL installations. + + .. toctree:: :maxdepth: 2 :caption: User Guide diff --git a/docs/tracketch.pdf b/docs/tracketch.pdf new file mode 100644 index 0000000..c76ac16 Binary files /dev/null and b/docs/tracketch.pdf differ diff --git a/examples/plot_deuteron_etching.py b/examples/plot_deuteron_etching.py index 953b2ae..2d067ba 100644 --- a/examples/plot_deuteron_etching.py +++ b/examples/plot_deuteron_etching.py @@ -19,7 +19,6 @@ result_df = pd.DataFrame() # iterate through combinations and calculate track radius for each for energy_MeV_u in tqdm.tqdm(energies_MeV_u, total=len(energies_MeV_u)): - # create simulator sim = TrackSimulator( particle_name=particle, @@ -60,4 +59,4 @@ ax.set_xlabel("Removed layer / um") ax.set_ylabel("Track radius / um") ax.legend(title="Energy (MeV/u)") -plt.show() \ No newline at end of file +plt.show() diff --git a/pyproject.toml b/pyproject.toml index e9a7556..98e8f82 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,6 +29,7 @@ dependencies = [ cpp = [ "pybind11>=2.6", + "setuptools", ] numba = [ @@ -58,6 +59,22 @@ dev = [ "sphinx-rtd-theme>=3.0", ] +all = [ + "pybind11>=2.6", + "setuptools", + "numba>=0.57", + "numpy<=2.2", + "scikit-optimize", + "lmfit", + "tqdm", + "sphinx>=8,<9", + "sphinx-rtd-theme>=3.0", + "pytest", + "pytest-xdist", + "ruff", + "scikit-image", +] + [tool.setuptools.packages.find] include = ["tracketch*", "calibration*"] diff --git a/tracketch/etching/models/Doerschel_etching.json b/tracketch/etching/models/Doerschel_etching.json index 227f350..6f7c340 100644 --- a/tracketch/etching/models/Doerschel_etching.json +++ b/tracketch/etching/models/Doerschel_etching.json @@ -2,137 +2,56 @@ "name": "Doerschel_etching", "V_bulk_um_h": 1.73, "V_max_um_h": 100.0, - "V_max_uncertainty_um_h": 1.855967250581455, + "V_max_uncertainty_um_h": 8.322281692861123, "anchor_doses_Gy": [ 0.001, 100.0, - 1000.0, 10000.0, - 21544.346900318822, - 46415.88833612782, + 31622.776601683792, 100000.0, - 125892.54117941661, - 158489.3192461114, - 199526.2314968879, - 251188.6431509582, - 316227.7660168379, - 398107.1705534969, - 501187.2336272725, - 630957.344480193, - 794328.2347242822, - 1000000.0, - 1258925.411794166, - 1584893.1924611141, - 1995262.3149688789, - 2511886.4315095823, + 237137.37056616554, + 562341.3251903491, + 1333521.432163324, 3162277.6601683795, - 3981071.7055349695, - 5011872.336272725, - 6309573.44480193, - 7943282.347242822, - 10000000.0, - 12589254.117941663, - 15848931.924611142, - 19952623.14968883, - 25118864.315095823, - 31622776.60168379, - 39810717.05534969, - 50118723.36272725, - 63095734.44801943, - 79432823.47242822, + 7498942.093324558, + 17782794.100389227, + 42169650.342858225, 100000000.0, - 177827941.00389227, - 316227766.01683795, - 562341325.1903491, 1000000000.0 ], "anchor_velocities_um_h": [ 1.73, - 1.7328702687405895, - 1.7339645047692596, - 1.7434761767490754, - 1.7631598574129839, - 1.7643176104694462, - 1.7780496930911076, - 1.7806528988258397, - 1.7851436631237203, - 1.7876655107836708, - 1.791528192730173, - 1.793108339985454, - 1.7961450647151571, - 1.7991232866984443, - 1.8022065126715152, - 1.8042895810027408, - 1.8081014113861895, - 1.811758097472675, - 1.8393955885972841, - 1.9885271674586098, - 2.095255470776105, - 2.167915479463624, - 2.1773756306992986, - 2.2309518905994334, - 2.5710230326271355, - 2.6221005697701965, - 2.8288816068936566, - 2.8288981331652168, - 2.8289188931525406, - 2.8289541196038814, - 3.66997910674418, - 5.026232991955743, - 6.548875722414821, - 6.549381868529469, - 6.549453800231048, - 6.5496211075632305, - 15.725688123505902, - 20.37687937413121, - 33.896825754897975, - 92.79377175559397, - 92.79836252907275 + 1.7722745958779738, + 1.8055135419252157, + 1.934337911217451, + 1.9429304969587473, + 2.18881199713672, + 2.199057329524819, + 2.3626080097098825, + 2.439817422350564, + 2.5871586093465084, + 2.954025314321479, + 5.75319577937238, + 10.089309684704848, + 88.30593825964475 ], "anchor_velocity_uncertainties_um_h": [ 0.0346, - 0.03465740537481179, - 0.034679290095385194, - 0.03486952353498151, - 0.4236927643630203, - 0.4522786840030905, - 0.9634295927493558, - 0.9678707649233952, - 1.22766385536739, - 1.5674501747298224, - 2.518978708480592, - 2.5620093352059774, - 2.1485475754631698, - 1.676162425232142, - 1.5321786404157156, - 1.401143470715636, - 1.2163614155059967, - 1.1815597218571379, - 2.2719109434863456, - 2.222032170214383, - 1.1415288618649497, - 1.1313512558166554, - 0.6798563035643918, - 0.7186825560412243, - 0.12637033201257614, - 0.05244201139540393, - 0.12492740467004745, - 0.12493335631253878, - 0.12501051993511508, - 0.12531035574406074, - 0.7863491122359768, - 0.7919221978061346, - 0.13097751444829642, - 0.13098763737058938, - 0.13098907600462098, - 0.1309924221512646, - 0.31451376247011803, - 0.5970276096218552, - 3.7413647489837474, - 1.8558754351118794, - 1.855967250581455 + 0.4670112122185652, + 5.088253928348727, + 6.265837626654851, + 6.199807196196782, + 3.378839880422098, + 3.1014721779715413, + 0.04725216019419765, + 0.23512886353977802, + 0.05174317218693017, + 0.47407857540789694, + 0.1150639155874476, + 0.40138504004371267, + 8.322281692861123 ], "extrapolation_mode": "pchip", - "debris_alpha": 10.488453298894855, - "debris_beta": 1.1733910537622545 + "debris_alpha": 699.833485055439, + "debris_beta": 1.5103813534152948 } \ No newline at end of file