scispectrum 0.3.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.
Files changed (52) hide show
  1. scispectrum-0.3.0/LICENSE +21 -0
  2. scispectrum-0.3.0/PKG-INFO +220 -0
  3. scispectrum-0.3.0/README.md +193 -0
  4. scispectrum-0.3.0/pyproject.toml +36 -0
  5. scispectrum-0.3.0/scispectrum/__init__.py +4 -0
  6. scispectrum-0.3.0/scispectrum/background/__init__.py +4 -0
  7. scispectrum-0.3.0/scispectrum/background/als.py +81 -0
  8. scispectrum-0.3.0/scispectrum/background/base.py +31 -0
  9. scispectrum-0.3.0/scispectrum/background/minimum_in_envelope.py +125 -0
  10. scispectrum-0.3.0/scispectrum/background/polynomial.py +165 -0
  11. scispectrum-0.3.0/scispectrum/background/snip.py +65 -0
  12. scispectrum-0.3.0/scispectrum/background/snip_utils.py +10 -0
  13. scispectrum-0.3.0/scispectrum/calibration/__init__.py +7 -0
  14. scispectrum-0.3.0/scispectrum/calibration/axis.py +60 -0
  15. scispectrum-0.3.0/scispectrum/calibration/detector_calibration.py +158 -0
  16. scispectrum-0.3.0/scispectrum/calibration/models/__init__.py +3 -0
  17. scispectrum-0.3.0/scispectrum/calibration/models/base.py +31 -0
  18. scispectrum-0.3.0/scispectrum/calibration/models/energy_poly.py +25 -0
  19. scispectrum-0.3.0/scispectrum/calibration/models/hpge_fwhm_model.py +10 -0
  20. scispectrum-0.3.0/scispectrum/calibration/resolution.py +21 -0
  21. scispectrum-0.3.0/scispectrum/core/__init__.py +2 -0
  22. scispectrum-0.3.0/scispectrum/core/domain.py +198 -0
  23. scispectrum-0.3.0/scispectrum/core/spectrum.py +282 -0
  24. scispectrum-0.3.0/scispectrum/domain_analysis/__init__.py +0 -0
  25. scispectrum-0.3.0/scispectrum/domain_analysis/background.py +63 -0
  26. scispectrum-0.3.0/scispectrum/domain_analysis/find_peaks.py +208 -0
  27. scispectrum-0.3.0/scispectrum/domain_analysis/moment.py +74 -0
  28. scispectrum-0.3.0/scispectrum/domain_analysis/morphology.py +107 -0
  29. scispectrum-0.3.0/scispectrum/domain_analysis/single_peak.py +140 -0
  30. scispectrum-0.3.0/scispectrum/domain_fitting/__init__.py +3 -0
  31. scispectrum-0.3.0/scispectrum/domain_fitting/abstract_fitting_class.py +20 -0
  32. scispectrum-0.3.0/scispectrum/domain_fitting/multi_gaussian_fitter.py +410 -0
  33. scispectrum-0.3.0/scispectrum/identification/__init__.py +3 -0
  34. scispectrum-0.3.0/scispectrum/identification/base.py +18 -0
  35. scispectrum-0.3.0/scispectrum/identification/convolution.py +84 -0
  36. scispectrum-0.3.0/scispectrum/identification/kernels/__init__.py +1 -0
  37. scispectrum-0.3.0/scispectrum/identification/kernels/base.py +42 -0
  38. scispectrum-0.3.0/scispectrum/identification/kernels/mexican_hat.py +24 -0
  39. scispectrum-0.3.0/scispectrum/identification/kernels/utils.py +1 -0
  40. scispectrum-0.3.0/scispectrum/identification/snr.py +192 -0
  41. scispectrum-0.3.0/scispectrum/io/__init__.py +4 -0
  42. scispectrum-0.3.0/scispectrum/io/time_channel.py +175 -0
  43. scispectrum-0.3.0/scispectrum/utils/__init__.py +0 -0
  44. scispectrum-0.3.0/scispectrum/utils/gaussian.py +12 -0
  45. scispectrum-0.3.0/scispectrum/utils/smoothing.py +88 -0
  46. scispectrum-0.3.0/scispectrum.egg-info/PKG-INFO +220 -0
  47. scispectrum-0.3.0/scispectrum.egg-info/SOURCES.txt +50 -0
  48. scispectrum-0.3.0/scispectrum.egg-info/dependency_links.txt +1 -0
  49. scispectrum-0.3.0/scispectrum.egg-info/requires.txt +5 -0
  50. scispectrum-0.3.0/scispectrum.egg-info/top_level.txt +1 -0
  51. scispectrum-0.3.0/setup.cfg +4 -0
  52. scispectrum-0.3.0/tests/test_calibration.py +37 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Achiya Yosef Amrusi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,220 @@
1
+ Metadata-Version: 2.4
2
+ Name: scispectrum
3
+ Version: 0.3.0
4
+ Summary: 1D detector spectrum analysis — energy calibration, background estimation, peak detection and fitting
5
+ Author-email: Achiya Yosef Amrusi <ahia.amrosi@mail.huji.ac.il>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/achiyaAmrusi/scispectrum
8
+ Project-URL: Repository, https://github.com/achiyaAmrusi/scispectrum
9
+ Project-URL: Issues, https://github.com/achiyaAmrusi/scispectrum/issues
10
+ Keywords: gamma-ray spectroscopy,peak fitting,background estimation,detector calibration,nuclear physics
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Scientific/Engineering :: Physics
18
+ Requires-Python: >=3.11
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: numpy<3.0,>=2.0.0
22
+ Requires-Dist: pandas<4.0,>=2.3
23
+ Requires-Dist: scipy>=1.14.0
24
+ Requires-Dist: xarray>=2024.6.0
25
+ Requires-Dist: uncertainties>=3.1
26
+ Dynamic: license-file
27
+
28
+ # scispectrum
29
+
30
+ A Python package for 1D spectrum analysis, designed for physicists and scientists working with detector data such as gamma-ray, X-ray, or particle spectra.
31
+
32
+ scispectrum provides a clean, extensible framework for the full spectrum analysis pipeline — from raw detector output to calibrated, fitted, background-subtracted results — with proper uncertainty propagation throughout.
33
+
34
+ ---
35
+
36
+ ## Features
37
+
38
+ - **Spectrum object** with axis calibration, resolution calibration, and error propagation using the uncertainties package
39
+ - **Domain slicing** by physical axis values (e.g. energy in keV) or channels
40
+ - **List-mode parser** for time-channel detector data, with chunked reading for large files
41
+ - **Domain fitting and analysis** — multiple fitting and analysis methods for a domain including sum of Gaussians fitting, find peaks, centers and fwhm
42
+ - **Background estimation** — multiple global background extimation methods including Asymmetric Least Squares (ALS)
43
+ - **Extensible base classes** — build your own fitting, background, or analysis procedures with a consistent interface
44
+ - **xarray throughout** — labeled, sliceable data with named coordinates
45
+ - **Uncertainty propagation** via the `uncertainties` library
46
+
47
+ ---
48
+
49
+ ## Installation
50
+
51
+ scispectrum is not yet available on PyPI. Install directly from GitHub:
52
+
53
+ ```bash
54
+ git clone https://github.com/achiyaAmrusi/pySpectrum
55
+ cd pySpectrum
56
+ pip install -e .
57
+ ```
58
+ This installs the package in editable mode, so any changes you make to the source are reflected immediately.
59
+
60
+ ---
61
+
62
+ ## Quick Start
63
+
64
+ ### Load a spectrum from a DataFrame
65
+
66
+ ```python
67
+ import pandas as pd
68
+ from scispectrum.core import Spectrum
69
+
70
+ df = pd.read_csv("my_spectrum.csv")
71
+ spectrum = Spectrum.from_dataframe(df, channel_col="channel", counts_col="counts")
72
+ ```
73
+
74
+ ### Apply an energy calibration
75
+
76
+ ```python
77
+ from scispectrum.calibration import AxisCalibration
78
+
79
+ # Linear calibration: energy = 0.5 * channel + 1.2
80
+ calib = AxisCalibration(lambda ch: 0.5 * ch + 1.2, name="energy_keV")
81
+ spectrum.set_axis_calibration(calib)
82
+ ```
83
+
84
+ ### Slice a domain by axis values
85
+
86
+ ```python
87
+ # Select the region between 1460 and 1480 keV
88
+ domain = spectrum.domain(1460, 1480)
89
+ ```
90
+
91
+ ### Fit peaks
92
+
93
+ ```python
94
+ from scispectrum.domain_fitting import SumOfGaussians
95
+
96
+ result = SumOfGaussians.fit(domain)
97
+
98
+ print(result["center"].values) # peak centers in keV
99
+ print(result["fwhm"].values) # peak widths
100
+ print(result["amplitude"].values) # peak amplitudes
101
+ ```
102
+
103
+ ### Estimate and subtract background
104
+
105
+ ```python
106
+ from scispectrum.background import ALSBackground
107
+
108
+ bg_estimator = ALSBackground(lam=1e5, p=0.001, max_iter=50)
109
+ als_bg = bg_estimator.estimate(spectrum.axis, spectrum.counts)
110
+ domain_subtracted = domains.subtract_background(als_bg[domain.indices])
111
+ ```
112
+
113
+ ### Parse raw list-mode data
114
+
115
+ ```python
116
+ from scispectrum.parsers import TimeChannelParser
117
+
118
+ # From a large file — processed in chunks to save memory
119
+ spectrum = TimeChannelParser.from_file(
120
+ "detector_run.csv",
121
+ axis_calib=calib,
122
+ num_of_channels=2**14
123
+ )
124
+
125
+ # From an in-memory DataFrame
126
+ spectrum = TimeChannelParser.from_dataframe(df, axis_calib=calib)
127
+ ```
128
+
129
+ ---
130
+
131
+ ## Uncertainty Propagation
132
+
133
+ scispectrum propagates measurement uncertainties through arithmetic operations using the `uncertainties` library. Poisson errors are assigned automatically when parsing list-mode data.
134
+
135
+ ```python
136
+ # Arithmetic preserves errors
137
+ subtraction = spectrum_a - spectrum_b
138
+ subtraction.counts_err # propagated uncertainties
139
+ ```
140
+
141
+ ---
142
+
143
+ ## Extending scispectrum
144
+
145
+ scispectrum is designed to be extended. Each analysis category has an abstract base class that defines the interface:
146
+
147
+ ### Custom fitting method
148
+
149
+ ```python
150
+ from scispectrum.domain_fitting.abstract_fitting_class import PeakFit
151
+
152
+ class MyFitter(PeakFit):
153
+ @classmethod
154
+ def fit(cls, domain, **kwargs):
155
+ # your fitting logic here
156
+ ...
157
+ ```
158
+
159
+ ### Custom background estimator
160
+
161
+ ```python
162
+ from scispectrum.background.base import BackgroundEstimator
163
+
164
+ class MyBackground(BackgroundEstimator):
165
+ def estimate(self, x, y):
166
+ # your background logic here
167
+ ...
168
+ ```
169
+
170
+ All custom classes integrate seamlessly with `Domain`, `Spectrum`, and the rest of the pipeline.
171
+
172
+ ---
173
+
174
+ ## Examples
175
+
176
+ Full worked examples are available in the [examples directory](https://github.com/achiyaAmrusi/pySpectrum/tree/main/examples):
177
+
178
+ **Core**
179
+ - [Loading a spectrum](./examples/Core/loading_spectrum.ipynb) — reading and constructing a `Spectrum` from data
180
+ - [Calibration](./examples/Core/calibration.ipynb) — applying axis and resolution calibrations
181
+ - [Domain slicing](./examples/Core/domain_example.ipynb) — creating and working with domains
182
+
183
+ **Background Estimation**
184
+ - [Background subtraction](./examples/Background/background_substraction.ipynb) — estimating and subtracting background from a domain
185
+
186
+ **Domain Analysis and Fitting**
187
+ - [Domain fitting](./examples/Domain_Analysis_and_Fitting/domain_fitting.ipynb) — fitting peaks in a single domain
188
+ - [Full spectrum fitting](./examples/Domain_Analysis_and_Fitting/full_sepctrum_fitting.ipynb) — fitting peaks across an entire spectrum
189
+
190
+ **SNR Identification**
191
+ - [Peak domain identification](./examples/SNR%20Identification/peak_domin_identification.ipynb) — identifying signal regions automatically
192
+ - [Complex spectrum domains](./examples/SNR%20Identification/complex_spectrum_domains.ipynb) — handling overlapping and complex peak structures
193
+
194
+ **Library**
195
+ Sample data files for running the examples are provided in the [Library directory](./examples/Library).
196
+
197
+ ---
198
+
199
+ ## Requirements
200
+
201
+ - numpy>=2.0.0,<3.0
202
+ - pandas>=2.3,<4.0
203
+ - scipy>=1.14.0
204
+ - xarray>=2024.6.0
205
+ - uncertainties>=3.1
206
+
207
+ ---
208
+
209
+ ## License
210
+
211
+ MIT License. See [LICENSE](LICENSE) for details.
212
+
213
+ ---
214
+
215
+ ## Author
216
+
217
+ Achiya Yosef Amrusi — [GitHub](https://github.com/achiyaAmrusi/pySpectrum)
218
+
219
+ Contributions and feedback are welcome.
220
+
@@ -0,0 +1,193 @@
1
+ # scispectrum
2
+
3
+ A Python package for 1D spectrum analysis, designed for physicists and scientists working with detector data such as gamma-ray, X-ray, or particle spectra.
4
+
5
+ scispectrum provides a clean, extensible framework for the full spectrum analysis pipeline — from raw detector output to calibrated, fitted, background-subtracted results — with proper uncertainty propagation throughout.
6
+
7
+ ---
8
+
9
+ ## Features
10
+
11
+ - **Spectrum object** with axis calibration, resolution calibration, and error propagation using the uncertainties package
12
+ - **Domain slicing** by physical axis values (e.g. energy in keV) or channels
13
+ - **List-mode parser** for time-channel detector data, with chunked reading for large files
14
+ - **Domain fitting and analysis** — multiple fitting and analysis methods for a domain including sum of Gaussians fitting, find peaks, centers and fwhm
15
+ - **Background estimation** — multiple global background extimation methods including Asymmetric Least Squares (ALS)
16
+ - **Extensible base classes** — build your own fitting, background, or analysis procedures with a consistent interface
17
+ - **xarray throughout** — labeled, sliceable data with named coordinates
18
+ - **Uncertainty propagation** via the `uncertainties` library
19
+
20
+ ---
21
+
22
+ ## Installation
23
+
24
+ scispectrum is not yet available on PyPI. Install directly from GitHub:
25
+
26
+ ```bash
27
+ git clone https://github.com/achiyaAmrusi/pySpectrum
28
+ cd pySpectrum
29
+ pip install -e .
30
+ ```
31
+ This installs the package in editable mode, so any changes you make to the source are reflected immediately.
32
+
33
+ ---
34
+
35
+ ## Quick Start
36
+
37
+ ### Load a spectrum from a DataFrame
38
+
39
+ ```python
40
+ import pandas as pd
41
+ from scispectrum.core import Spectrum
42
+
43
+ df = pd.read_csv("my_spectrum.csv")
44
+ spectrum = Spectrum.from_dataframe(df, channel_col="channel", counts_col="counts")
45
+ ```
46
+
47
+ ### Apply an energy calibration
48
+
49
+ ```python
50
+ from scispectrum.calibration import AxisCalibration
51
+
52
+ # Linear calibration: energy = 0.5 * channel + 1.2
53
+ calib = AxisCalibration(lambda ch: 0.5 * ch + 1.2, name="energy_keV")
54
+ spectrum.set_axis_calibration(calib)
55
+ ```
56
+
57
+ ### Slice a domain by axis values
58
+
59
+ ```python
60
+ # Select the region between 1460 and 1480 keV
61
+ domain = spectrum.domain(1460, 1480)
62
+ ```
63
+
64
+ ### Fit peaks
65
+
66
+ ```python
67
+ from scispectrum.domain_fitting import SumOfGaussians
68
+
69
+ result = SumOfGaussians.fit(domain)
70
+
71
+ print(result["center"].values) # peak centers in keV
72
+ print(result["fwhm"].values) # peak widths
73
+ print(result["amplitude"].values) # peak amplitudes
74
+ ```
75
+
76
+ ### Estimate and subtract background
77
+
78
+ ```python
79
+ from scispectrum.background import ALSBackground
80
+
81
+ bg_estimator = ALSBackground(lam=1e5, p=0.001, max_iter=50)
82
+ als_bg = bg_estimator.estimate(spectrum.axis, spectrum.counts)
83
+ domain_subtracted = domains.subtract_background(als_bg[domain.indices])
84
+ ```
85
+
86
+ ### Parse raw list-mode data
87
+
88
+ ```python
89
+ from scispectrum.parsers import TimeChannelParser
90
+
91
+ # From a large file — processed in chunks to save memory
92
+ spectrum = TimeChannelParser.from_file(
93
+ "detector_run.csv",
94
+ axis_calib=calib,
95
+ num_of_channels=2**14
96
+ )
97
+
98
+ # From an in-memory DataFrame
99
+ spectrum = TimeChannelParser.from_dataframe(df, axis_calib=calib)
100
+ ```
101
+
102
+ ---
103
+
104
+ ## Uncertainty Propagation
105
+
106
+ scispectrum propagates measurement uncertainties through arithmetic operations using the `uncertainties` library. Poisson errors are assigned automatically when parsing list-mode data.
107
+
108
+ ```python
109
+ # Arithmetic preserves errors
110
+ subtraction = spectrum_a - spectrum_b
111
+ subtraction.counts_err # propagated uncertainties
112
+ ```
113
+
114
+ ---
115
+
116
+ ## Extending scispectrum
117
+
118
+ scispectrum is designed to be extended. Each analysis category has an abstract base class that defines the interface:
119
+
120
+ ### Custom fitting method
121
+
122
+ ```python
123
+ from scispectrum.domain_fitting.abstract_fitting_class import PeakFit
124
+
125
+ class MyFitter(PeakFit):
126
+ @classmethod
127
+ def fit(cls, domain, **kwargs):
128
+ # your fitting logic here
129
+ ...
130
+ ```
131
+
132
+ ### Custom background estimator
133
+
134
+ ```python
135
+ from scispectrum.background.base import BackgroundEstimator
136
+
137
+ class MyBackground(BackgroundEstimator):
138
+ def estimate(self, x, y):
139
+ # your background logic here
140
+ ...
141
+ ```
142
+
143
+ All custom classes integrate seamlessly with `Domain`, `Spectrum`, and the rest of the pipeline.
144
+
145
+ ---
146
+
147
+ ## Examples
148
+
149
+ Full worked examples are available in the [examples directory](https://github.com/achiyaAmrusi/pySpectrum/tree/main/examples):
150
+
151
+ **Core**
152
+ - [Loading a spectrum](./examples/Core/loading_spectrum.ipynb) — reading and constructing a `Spectrum` from data
153
+ - [Calibration](./examples/Core/calibration.ipynb) — applying axis and resolution calibrations
154
+ - [Domain slicing](./examples/Core/domain_example.ipynb) — creating and working with domains
155
+
156
+ **Background Estimation**
157
+ - [Background subtraction](./examples/Background/background_substraction.ipynb) — estimating and subtracting background from a domain
158
+
159
+ **Domain Analysis and Fitting**
160
+ - [Domain fitting](./examples/Domain_Analysis_and_Fitting/domain_fitting.ipynb) — fitting peaks in a single domain
161
+ - [Full spectrum fitting](./examples/Domain_Analysis_and_Fitting/full_sepctrum_fitting.ipynb) — fitting peaks across an entire spectrum
162
+
163
+ **SNR Identification**
164
+ - [Peak domain identification](./examples/SNR%20Identification/peak_domin_identification.ipynb) — identifying signal regions automatically
165
+ - [Complex spectrum domains](./examples/SNR%20Identification/complex_spectrum_domains.ipynb) — handling overlapping and complex peak structures
166
+
167
+ **Library**
168
+ Sample data files for running the examples are provided in the [Library directory](./examples/Library).
169
+
170
+ ---
171
+
172
+ ## Requirements
173
+
174
+ - numpy>=2.0.0,<3.0
175
+ - pandas>=2.3,<4.0
176
+ - scipy>=1.14.0
177
+ - xarray>=2024.6.0
178
+ - uncertainties>=3.1
179
+
180
+ ---
181
+
182
+ ## License
183
+
184
+ MIT License. See [LICENSE](LICENSE) for details.
185
+
186
+ ---
187
+
188
+ ## Author
189
+
190
+ Achiya Yosef Amrusi — [GitHub](https://github.com/achiyaAmrusi/pySpectrum)
191
+
192
+ Contributions and feedback are welcome.
193
+
@@ -0,0 +1,36 @@
1
+ [build-system]
2
+ requires = ["setuptools>=74.1.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "scispectrum"
7
+ version = "0.3.0"
8
+ description = "1D detector spectrum analysis — energy calibration, background estimation, peak detection and fitting"
9
+ authors = [
10
+ { name = "Achiya Yosef Amrusi", email = "ahia.amrosi@mail.huji.ac.il" }
11
+ ]
12
+ license = { text = "MIT" }
13
+ readme = "README.md"
14
+ requires-python = ">=3.11"
15
+ keywords = ["gamma-ray spectroscopy", "peak fitting", "background estimation", "detector calibration", "nuclear physics"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Science/Research",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Topic :: Scientific/Engineering :: Physics",
24
+ ]
25
+ dependencies = [
26
+ "numpy>=2.0.0,<3.0",
27
+ "pandas>=2.3,<4.0",
28
+ "scipy>=1.14.0",
29
+ "xarray>=2024.6.0",
30
+ "uncertainties>=3.1",
31
+ ]
32
+
33
+ [project.urls]
34
+ Homepage = "https://github.com/achiyaAmrusi/scispectrum"
35
+ Repository = "https://github.com/achiyaAmrusi/scispectrum"
36
+ Issues = "https://github.com/achiyaAmrusi/scispectrum/issues"
@@ -0,0 +1,4 @@
1
+ from .core import Spectrum, Domain
2
+ from .io import TimeChannelParser
3
+ from .calibration import ResolutionCalibration, AxisCalibration
4
+
@@ -0,0 +1,4 @@
1
+ from .als import ALSBackground
2
+ from .snip import SNIPBackground
3
+ from .polynomial import IterativePolyFit, IterativePolyFitWithMinimum
4
+ from .minimum_in_envelope import MinimaEnvelopeBackground
@@ -0,0 +1,81 @@
1
+ import numpy as np
2
+ from scipy import sparse
3
+ from scipy.sparse.linalg import spsolve
4
+ from scispectrum.background.base import BackgroundEstimator
5
+
6
+
7
+ class ALSBackground(BackgroundEstimator):
8
+ """
9
+ Asymmetric Least Squares (ALS) background estimator.
10
+
11
+ Estimates a smooth background by iteratively fitting a weighted
12
+ smoothing spline, penalizing points above the current estimate
13
+ more lightly than points below it. This asymmetry drives the
14
+ baseline to sit beneath the signal peaks.
15
+
16
+ Parameters
17
+ ----------
18
+ lam : float
19
+ Smoothness penalty. Larger values produce a smoother background.
20
+ Typical range: 1e3 to 1e7. Default is 1e5.
21
+ p : float
22
+ Asymmetry parameter. Controls the weight given to points above
23
+ the current estimate. Should be small (e.g. 0.001 to 0.1) so
24
+ the baseline stays below peaks. Default is 0.01.
25
+ max_iter : int
26
+ Number of reweighting iterations. More iterations refine the
27
+ baseline but increase compute time. Default is 20.
28
+
29
+ References
30
+ ----------
31
+ Eilers, P.H.C. and Boelens, H.F.M. (2005).
32
+ "Baseline correction with asymmetric least squares smoothing."
33
+ """
34
+
35
+ def __init__(self, lam=1e5, p=0.01, max_iter=20):
36
+ self.lam = lam
37
+ self.p = p
38
+ self.max_iter = max_iter
39
+
40
+ def estimate(self, axis: np.ndarray, counts: np.ndarray) -> np.ndarray:
41
+ """
42
+ Estimate the background of a spectrum using ALS.
43
+
44
+ Parameters
45
+ ----------
46
+ axis : np.ndarray
47
+ Axis values (not used by ALS, required by the interface).
48
+ counts : np.ndarray
49
+ Spectrum counts.
50
+
51
+ Returns
52
+ -------
53
+ np.ndarray
54
+ Estimated background, same shape as counts.
55
+ """
56
+ y = counts
57
+ n = len(y)
58
+
59
+ # Second-order difference matrix (n-2 x n) — penalizes curvature
60
+ # in the background estimate. D.T @ D appears in the smoothness term.
61
+ D = sparse.diags([1, -2, 1], [0, 1, 2], shape=(n - 2, n), dtype=float)
62
+ DTD = D.T @ D
63
+
64
+ # Initialize weights uniformly — all points treated equally
65
+ w = np.ones(n)
66
+
67
+ for _ in range(self.max_iter):
68
+ # Diagonal weight matrix for the current iteration
69
+ W = sparse.diags(w, 0)
70
+
71
+ # Solve the weighted penalized least squares system:
72
+ # (W + lam * D'D) z = W y
73
+ Z = W + self.lam * DTD
74
+ z = spsolve(Z.tocsc(), w * y)
75
+
76
+ # Asymmetric reweighting: points above the baseline get weight p,
77
+ # points below get weight 1-p. This pulls the baseline downward
78
+ # toward the true background, away from peaks.
79
+ w = np.where(y > z, self.p, 1 - self.p)
80
+
81
+ return z
@@ -0,0 +1,31 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ import numpy as np
4
+
5
+
6
+ class BackgroundEstimator(ABC):
7
+ """
8
+ Abstract base class for background estimation algorithms.
9
+
10
+ All auxiliary inputs (resolution calibration, convolution objects, etc.)
11
+ must be passed at construction time, not to estimate().
12
+ """
13
+
14
+ @abstractmethod
15
+ def estimate(self, axis: np.ndarray, counts: np.ndarray) -> np.ndarray:
16
+ """
17
+ Estimate background for a 1D spectrum.
18
+
19
+ Parameters
20
+ ----------
21
+ axis : np.ndarray
22
+ Axis values (e.g. energy in keV).
23
+ counts : np.ndarray
24
+ Spectrum counts.
25
+
26
+ Returns
27
+ -------
28
+ np.ndarray
29
+ Estimated background, same shape as counts.
30
+ """
31
+ pass