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

173 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/`](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:
```python
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
```python
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
```bash
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](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