fitPALSpectra is an open-source Python workflow for simulating, fitting, plotting, and reporting positron annihilation lifetime spectroscopy (PALS) spectra. It fits multi-component lifetime models convolved with a Gaussian detector-resolution function, supports source corrections and constrained optimization, and exports machine-readable results for reproducible downstream analysis.
The project is configuration-driven: users edit the working configuration files in configs/, run the scripts in scripts/, and inspect timestamped outputs in outputs/.
- Analytic channel-integrated exponential--Gaussian response model.
- Configurable source, sample, detector-resolution, background, and fitting-window parameters.
- Local and global optimization through Nelder--Mead, Powell, and dual annealing.
- Optional augmented-Lagrangian equality constraints for normalized intensities, source/sample fractions, and Gaussian IRF weights.
- Optional bounded trust-region-reflective least-squares refinement with covariance and correlation exports.
- Static plots, interactive HTML plots, text reports, CSV summaries, and JSON outputs.
- Synthetic spectrum generation with Poisson or noiseless count models.
fitPALSpectra/
├── configs/
│ ├── pals.ini # working configuration for fitting
│ └── simulate.ini # working configuration for simulation
├── data/ # spectra read by scripts/run_fit.py
├── outputs/ # timestamped fit and simulation outputs
├── scripts/
│ ├── run_fit.py # main fitting workflow
│ └── run_simulation.py # synthetic spectrum generator
├── src/pals/ # library code
├── requirements.txt
├── README.md
└── LICENSE.txt
Use Python 3 with NumPy, SciPy, Matplotlib, pandas, Plotly, and seaborn installed. From the repository root, install the listed requirements with:
python -m pip install -r requirements.txtThe scripts add src/ to sys.path at runtime, so the package does not need to be installed before running the bundled workflows.
The workflow uses fixed working configuration filenames:
configs/pals.inifor fitting.configs/simulate.inifor simulation.
These files are edited in place for the run being prepared. Reproducibility is preserved by copying the exact configuration used for each run into the timestamped output directory:
- Fitting runs save
pals_used.ini. - Simulation runs save
simulate_used.ini.
For an archived result, the corresponding pals_used.ini or simulate_used.ini is the authoritative record of the parameters used in that run. To rerun an archived case, copy the saved configuration back to the fixed working filename, or reproduce its settings manually in the fixed working configuration file.
Example:
cp outputs/simulated_spectrum_1_20260606_221015/pals_used.ini configs/pals.ini
python scripts/run_fit.pyBecause some optimization workflows use stochastic global search, reruns can produce small numerical differences unless all random choices and software versions are controlled. Archived output directories contain the exact results reported for those runs.
- Put the spectrum file in
data/. - Edit
configs/pals.ini. - Set
general.data_fileto the spectrum filename, for example:
[general]
data_file = simulated_spectrum_1.txt- Select the fitting window, model components, active parameters, bounds, constraints, and optimizer settings in
configs/pals.ini. - Run:
python scripts/run_fit.pyEach fit creates a timestamped directory in outputs/, named from the input spectrum and run time.
A fitting run writes files such as:
pals_used.ini: exact fitting configuration used for the run.fit.txt: human-readable fit report.fit.json: structured parameter values, uncertainties, fit flags, and chi-square values.curve.txtandcurve.json: fitted curve and normalized residuals.covariance.txtandcovariance.json: covariance matrix, when least-squares refinement is enabled.correlation.txtandcorrelation.json: correlation matrix, when least-squares refinement is enabled.correlation_heatmap_active.pngandcorrelation_heatmap_active.pdf: active-parameter correlation heat map.full.pngandfull.pdf: full input spectrum.extracted.pngandextracted.pdf: selected fitting window.fit.pngandfit.pdf: fitted spectrum.fit_interactive_linear.htmlandfit_interactive_log.html: interactive fit plots.
The file outputs/all_fits_summary.csv is also appended with one row per fit.
- Edit
configs/simulate.ini. - Set the simulation name, number of channels, channel width, total signal counts, background, source/sample components, detector-resolution parameters, and noise model.
- Run:
python scripts/run_simulation.pyThe simulator writes a timestamped directory under outputs/ containing:
<simulation_name>.txt: spectrometer-style synthetic spectrum.truth.json: exact simulation parameters and derived quantities.simulate_used.ini: exact simulation configuration used for the run.<simulation_name>.png: plot of the simulated spectrum.
To fit a newly simulated spectrum with scripts/run_fit.py, copy the generated spectrum into data/ or otherwise place the spectrum where configs/pals.ini can reference it through general.data_file.
The repository includes the two synthetic spectra and archived fit-output directories used for the manuscript tables and figures:
- Generic synthetic benchmark:
- Spectrum:
data/simulated_spectrum_1.txt - Archived fit output:
outputs/simulated_spectrum_1_20260606_221015/ - Authoritative fit configuration:
outputs/simulated_spectrum_1_20260606_221015/pals_used.ini
- Spectrum:
- Tungsten-like synthetic benchmark:
- Spectrum:
data/simulated_spectrum_W.txt - Archived fit output:
outputs/simulated_spectrum_W_20260607_024532/ - Authoritative fit configuration:
outputs/simulated_spectrum_W_20260607_024532/pals_used.ini
- Spectrum:
To rerun one of these fits, copy the corresponding pals_used.ini into configs/pals.ini and run python scripts/run_fit.py. A new timestamped output directory will be created; the existing archived directory should be treated as the record of the reported manuscript run.
The reported reduced chi-square is computed from the data residuals using the active-parameter reporting convention implemented in the fitting script. When least-squares refinement is enabled with constraints, the covariance and correlation matrices are computed from the least-squares Jacobian used in that refinement. If constraints are enabled, that residual vector includes both data residuals and scaled equality-constraint residuals.
The resulting uncertainties describe local sensitivity for the selected model, fitting window, weights, bounds, and configuration. They do not include systematic uncertainty from model choice, calibration, source-correction assumptions, or external software comparisons.
If you use fitPALSpectra in published work, please cite the associated preprint and the software repository:
\bibitem{Pavlou2026fitPALSpectra}
G.~E. Pavlou,
``fitPALSpectra: Python fitting of positron annihilation lifetime spectra,''
arXiv:2606.12157 [physics.comp-ph], 2026.
doi:10.48550/arXiv.2606.12157.
@misc{Pavlou2026fitPALSpectra,
author = {Pavlou, Georgios E.},
title = {{fitPALSpectra}: Python fitting of positron annihilation lifetime spectra},
year = {2026},
eprint = {2606.12157},
archivePrefix = {arXiv},
primaryClass = {physics.comp-ph},
doi = {10.48550/arXiv.2606.12157},
url = {https://arxiv.org/abs/2606.12157}
}This project is distributed under the MIT License. See LICENSE.txt.