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.
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.
- Spectrum object with axis calibration, resolution calibration, and error propagation using the uncertainties package
- Domain slicing by physical axis values (e.g. energy in keV) or channels
- List-mode parser for time-channel detector data, with chunked reading for large files
- Domain fitting and analysis — multiple fitting and analysis methods for a domain including sum of Gaussians fitting, find peaks, centers and fwhm
- Background estimation — multiple global background extimation methods including Asymmetric Least Squares (ALS)
- Extensible base classes — build your own fitting, background, or analysis procedures with a consistent interface
- xarray throughout — labeled, sliceable data with named coordinates
- Uncertainty propagation via the
uncertaintieslibrary
scispectrum is not yet available on PyPI. Install directly from GitHub:
git clone https://github.com/achiyaAmrusi/pySpectrum
cd pySpectrum
pip install -e .This installs the package in editable mode, so any changes you make to the source are reflected immediately.
import pandas as pd
from scispectrum.core import Spectrum
df = pd.read_csv("my_spectrum.csv")
spectrum = Spectrum.from_dataframe(df, channel_col="channel", counts_col="counts")from scispectrum.calibration import AxisCalibration
# Linear calibration: energy = 0.5 * channel + 1.2
calib = AxisCalibration(lambda ch: 0.5 * ch + 1.2, name="energy_keV")
spectrum.set_axis_calibration(calib)# Select the region between 1460 and 1480 keV
domain = spectrum.domain(1460, 1480)from scispectrum.domain_fitting import SumOfGaussians
result = SumOfGaussians.fit(domain)
print(result["center"].values) # peak centers in keV
print(result["fwhm"].values) # peak widths
print(result["amplitude"].values) # peak amplitudesfrom scispectrum.background import ALSBackground
bg_estimator = ALSBackground(lam=1e5, p=0.001, max_iter=50)
als_bg = bg_estimator.estimate(spectrum.axis, spectrum.counts)
domain_subtracted = domains.subtract_background(als_bg[domain.indices])from scispectrum.parsers import TimeChannelParser
# From a large file — processed in chunks to save memory
spectrum = TimeChannelParser.from_file(
"detector_run.csv",
axis_calib=calib,
num_of_channels=2**14
)
# From an in-memory DataFrame
spectrum = TimeChannelParser.from_dataframe(df, axis_calib=calib)scispectrum propagates measurement uncertainties through arithmetic operations using the uncertainties library. Poisson errors are assigned automatically when parsing list-mode data.
# Arithmetic preserves errors
subtraction = spectrum_a - spectrum_b
subtraction.counts_err # propagated uncertaintiesscispectrum is designed to be extended. Each analysis category has an abstract base class that defines the interface:
from scispectrum.domain_fitting.abstract_fitting_class import PeakFit
class MyFitter(PeakFit):
@classmethod
def fit(cls, domain, **kwargs):
# your fitting logic here
...from scispectrum.background.base import BackgroundEstimator
class MyBackground(BackgroundEstimator):
def estimate(self, x, y):
# your background logic here
...All custom classes integrate seamlessly with Domain, Spectrum, and the rest of the pipeline.
Full worked examples are available in the examples directory:
Core
- Loading a spectrum — reading and constructing a
Spectrumfrom data - Calibration — applying axis and resolution calibrations
- Domain slicing — creating and working with domains
Background Estimation
- Background subtraction — estimating and subtracting background from a domain
Domain Analysis and Fitting
- Domain fitting — fitting peaks in a single domain
- Full spectrum fitting — fitting peaks across an entire spectrum
SNR Identification
- Peak domain identification — identifying signal regions automatically
- Complex spectrum domains — handling overlapping and complex peak structures
Library Sample data files for running the examples are provided in the Library directory.
- numpy>=2.0.0,<3.0
- pandas>=2.3,<4.0
- scipy>=1.14.0
- xarray>=2024.6.0
- uncertainties>=3.1
MIT License. See LICENSE for details.
Achiya Yosef Amrusi — GitHub
Contributions and feedback are welcome.