Files
beta_shape_pnpi/README.md
T
unzhakov 6aced1d8ac docs: rewrite README, TODO, AGENTS and CONVENTIONS to theory-only scope
Compactify the descriptive markdown: scope statement replaces the
g_V-extraction goal, package architecture describes the single
theory-only distributable, roadmap keeps calculator capabilities
(C1-C8) and drops the analysis tracks, structure trees match the
actual file layout, the bs_exp debug step and detector-parameter
convention wording are dropped.
2026-10-05 17:20:27 +03:00

9.8 KiB
Raw Blame History

Beta Spectrum Calculation Toolkit

A modular Python package for calculating high-precision beta decay energy spectra. It models the spectral shape of nuclear transitions by combining well-established physical corrections into a coherent, configurable pipeline.

Since v0.5.0 the project scope is the spectrum-shape calculation alone: detector response modeling, data calibration and fitting/extraction live in separate, dedicated projects.

Features:

  • Numerical evaluation from near-zero kinetic energies up to the endpoint
  • Selective inclusion of higher-order corrections via SpectrumConfig toggles
  • Clean, composable component architecture
  • Built-in visualization and CSV export via BetaSpectrumAnalyzer
    • Normal mode: single spectrum plot with nuclear data header
    • Debug mode (-vv): 4-panel view with all correction factors
    • All plots include commit hash and UTC timestamp for traceability
  • Multi-branch decays with intensity weighting and per-branch endpoints
  • Nuclear data retrieval from ENSDF via paceENSDF (bs_pnpi --nuclide Tc99)
  • Comprehensive scientific reference in docs/
  • Debug verification workflow: bs_pnpi -vv validates all parameters end-to-end

Core Concept

The beta spectrum is constructed as a product of independent correction factors:

N(W) \\propto p W (W_0 - W)^2 \\times \\prod_i C_i(W)

Each C_i(W) is an independently implemented and toggleable component. The phase space and the Fermi function are the unconditional core: every spectrum carries their product, and the higher-order corrections multiply on top of it.


Project Structure

beta_shape_pnpi/
├── pyproject.toml
├── docs/                          ← Obsidian knowledge base (physics theory)
│   ├── README.md                  ← Vault overview + navigation index
│   ├── 00-beta-spectrum-overview.md
│   ├── 02-phase-space.md
│   └── corrections/               ← One note per correction component
├── beta_spectrum/                 ← theory-only core package
│   ├── __init__.py                ← Public API
│   ├── base.py                    ← Abstract SpectrumComponent base class
│   ├── constants.py               ← Physical constants (natural units, m_e = 1)
│   ├── utils.py                   ← T<->W conversion, momentum, nuclear radius
│   ├── spectrum.py                ← BetaSpectrum + SpectrumConfig + BranchConfig
│   ├── nuclear_data.py            ← paceENSDF integration + JSON input support
│   ├── cli.py                     ← Command-line interface (bs_pnpi)
│   ├── logging_utils.py           ← Structured logging helpers
│   ├── components/
│   │   ├── phase_space.py         ← Phase space shape (p·W·(W₀−W)²)
│   │   ├── fermi.py               ← Coulomb correction (loggamma for stability)
│   │   ├── finite_size.py         ← L0 expansion + charge distribution U term
│   │   ├── screening.py           ← Atomic electron screening (ratio method)
│   │   ├── exchange.py            ← Hayen-2018 empirical fit coefficients
│   │   └── radiative.py           ← Outer radiative corrections, soft-photon resummation
│   ├── data/
│   │   └── exchange_coeff.csv     ← Tabulated coefficients for X(Z,W), Z=2..120
│   └── output/                    ← visualization, CSV export
│       ├── core.py                ← BetaSpectrumAnalyzer
│       ├── csv_export.py          ← CSV export
│       └── visualization.py       ← Plotting built from exported CSV
├── data/
│   └── custom_input_example.json  ← Sample JSON input file
├── notebooks/                     ← Calculator notebook + nbmake conftest
├── output/                        ← Test run outputs (gitignored except .gitkeep)
├── tests/
│   ├── physics/                   ← Physics component tests
│   ├── quality/                   ← Code quality tests (logging, API, nuclear data)
│   ├── integration/               ← CLI and pipeline integration tests
│   └── common/                    ← Shared hypothesis + property tests
├── scripts/                       ← docs_check.py, notebook runners
├── AGENTS.md                      ← Agent instructions: stack, git workflow, TDD, quality gates
├── CONVENTIONS.md                 ← Physics conventions: natural units, energy representation, component design
├── TODO.md                        ← Development roadmap

Architecture

SpectrumComponent (base class)

Defined in beta_spectrum/base.py. All physics corrections inherit from this abstract base and implement:

def __call__(self, W: np.ndarray) -> np.ndarray

This makes every component stateless (or minimally stateful), vectorized, and composable.

BetaSpectrum

Defined in beta_spectrum/spectrum.py. Orchestrates the calculation:

  • Combines components multiplicatively via __call__(W)
  • Factory method from_config(config) for declarative setup
  • Generates energy grids with get_energy_grid(config)
  • Returns individual component values via calculate_components(W)

BetaSpectrumAnalyzer

In beta_spectrum.output. Provides debugging and visualization tools:

  • total_spectrum(normalize=True/False) — computed spectrum array; raises ValueError when every branch is degenerate (non-positive integral)
  • physical_branch_spectrum(i) — physical spectrum of branch i: the core (phase space × Fermi function) times every enabled higher-order correction, clamped beyond the branch endpoint (unnormalized)
  • universal_factor() — product of the components shared across all branches (Fermi function and the universal higher-order corrections)
  • plot_analysis(save_path=None, show_components=True) — plot with two modes:
    • show_components=True (debug mode): 4-panel figure (spectrum, components, cumulative effect, deviations)
    • show_components=False (normal mode): single spectrum plot with nuclear data header
    • All plots include commit hash and UTC timestamp for traceability
    • Plots are built from the exported CSV file (temporary full-verbosity export), so a plot always shows exactly the bytes the CSV export produces
  • export_to_csv(filename) — export via pandas DataFrame with YAML-style metadata header:
    • the basic spectrum is always the core phase_space × fermi (the header carries a # core: line); finite size, charge distribution, screening, exchange and radiative are higher-order corrections
    • branch_{i}_spectrum columns contain the physical branch spectra weighted by intensity and normalized so that the sum of branch columns equals total_spectrum
    • with separate_branches=True (CLI --separate-branches) each branch column integrates to 1 (intensity ignored, no total_spectrum column)
  • parse_spectrum_csv(path) — read an exported CSV and its metadata header (module function in beta_spectrum.output.visualization)
  • get_data() — return all numerical data for downstream analysis

Quick Start

from beta_spectrum import SpectrumConfig, BetaSpectrum
from beta_spectrum.output import BetaSpectrumAnalyzer

config = SpectrumConfig(
    Z_parent=90,       # Thorium-232 (example)
    Z_daughter=91,
    A_number=232,
    endpoint_MeV=4.8,  # Q-value
    transition_type="A",  # Allowed transition (default)
)

spectrum = BetaSpectrum.from_config(config)
W, E_MeV = spectrum.get_energy_grid(config)
values = spectrum(W)

analyzer = BetaSpectrumAnalyzer(spectrum, config)
analyzer.plot_analysis("analysis.png")          # Normal mode (single spectrum plot)
analyzer.plot_analysis("debug.png", show_components=True)  # Debug mode (4-panel)
analyzer.export_to_csv("spectrum.csv")   # Export data to CSV

From the command line

bs_pnpi --nuclide Tc99 -vv --output spectrum.csv   # ENSDF lookup + debug export
bs_pnpi --input data/custom_input_example.json     # JSON-driven configuration

CLI flags (--e-step, --neutrino-mass, --intensity-cutoff, --csv-separator, --separate-branches) override JSON input values only when explicitly given; every long option has a single-letter alias.


Nuclear Data (paceENSDF)

beta_spectrum.nuclear_data retrieves decay data automatically: get_decay_info_from_paceENSDF(), decay_info_to_config(), and create_config_from_source("paceENSDF", nuclide="Tc99"). Z, A, endpoint energies, half-life, spin/parity, branch intensities, log*ft and forbiddenness are populated from ENSDF; per-branch endpoints are the measured transition endpoint energies (max endpoint across branches defines the spectrum endpoint). paceENSDF is an optional extra: pip install ".[ensdf]".


Implementation Status

For a complete list of implemented and planned features, see TODO.md. Key highlights:

  • Physics corrections: phase space, Fermi function, finite size, screening, exchange, radiative (with delta_cut resummation)
  • Multi-branch decay: intensity-weighted sum of branch spectra, per-branch calculators with branch-specific endpoint, transition type (from ENSDF), and --intensity-cutoff CLI filter
  • CLI: bs_pnpi with full paceENSDF integration, structured logging (-v/-vv/-q), --dry-run, --version, --log-file
  • CSV metadata headers with nuclide, decay and calculation parameters plus software version and git commit hash