fix(spectrum): lone branch defines endpoint in single-branch mode

When config.branches carries exactly one branch (e.g. after
--intensity-cutoff filtering), the branch endpoint/transition define
the spectrum, energy grid, analyzer unified branch view and CSV
header. The stale top-level endpoint inherited from the parent decay
no longer leaks into physics (proven wrong on Cs137: spectrum
extended to 1176 keV while the lone survivor ends at 514 keV).
This commit is contained in:
2026-10-01 22:04:17 +03:00
parent 6bb7b950c7
commit ee7aedc80a
6 changed files with 179 additions and 10 deletions
+48 -1
View File
@@ -5,6 +5,7 @@ import tempfile
from pathlib import Path
from typing import Any, Dict
import numpy as np
import pytest
# ruff: noqa: E402, ANN201, ANN001
@@ -19,7 +20,7 @@ from beta_spectrum.nuclear_data import ( # noqa: E402
validate_json_input,
_parse_nuclide_symbol,
)
from beta_spectrum.spectrum import SpectrumConfig
from beta_spectrum.spectrum import BetaSpectrum, SpectrumConfig
def _has_paceENSDF() -> bool: # noqa: ANN201
@@ -241,6 +242,52 @@ class TestDecayInfoToConfig:
assert len(config.branches) == 1
assert config.branches[0].intensity == 0.5
def test_cutoff_single_survivor_endpoint_follows_branch(self):
"""A lone surviving branch must define the spectrum, not the stale
top-level endpoint inherited from the parent decay (D1)."""
info = DecayInfo(
parent_symbol="Cs137",
Z_parent=55,
Z_daughter=56,
A_number=137,
endpoint_keV=1176.0,
endpoint_MeV=1.176,
transition_type="F2",
forbiddenness_code="2F",
parent_J=7.0,
parent_pi=1,
half_life="y",
branches=[
BranchInfo(
level_index=0,
level_energy_keV=0.0,
intensity=0.053,
log_ft=5.0,
transition_type="F2",
),
BranchInfo(
level_index=1,
level_energy_keV=661.66,
intensity=0.947,
log_ft=5.0,
transition_type="A",
),
],
)
cfg = decay_info_to_config(info, intensity_cutoff=0.9)
assert cfg.branches is not None
assert len(cfg.branches) == 1
lone_ep = cfg.branches[0].endpoint_MeV
assert lone_ep == pytest.approx(1.176 - 0.66166)
spectrum = BetaSpectrum.from_config(cfg)
assert not spectrum._is_multi
W, E = spectrum.get_energy_grid(cfg)
# Grid capped at the surviving branch endpoint, not 1.176 MeV.
assert float(E.max()) < lone_ep + 1e-12
values = spectrum(W)
assert np.all(np.isfinite(values))
assert np.all(values >= 0.0)
# ---------------------------------------------------------------------------
# get_decay_info_from_paceENSDF