Add massive neutrino support and improve CSV/CLI output

- Add neutrino mass parameter to SpectrumConfig and CLI interface
- Update PhaseSpace component to handle neutrino mass effects properly
- Update CSV headers to show basic endpoint and all transition types
- Add --csv-verbosity option to CLI with 'full' and 'concise' options
- Fix comparison plots to properly show linear scale variations
- Add comprehensive tests for neutrino mass functionality
This commit is contained in:
2026-07-02 10:33:28 +03:00
parent 406fd57bcd
commit 876e1e3ab8
48 changed files with 5213 additions and 97 deletions
+20 -1
View File
@@ -85,6 +85,12 @@ def _build_parser() -> argparse.ArgumentParser:
default=0.001,
help="Energy step size in MeV (default: 0.001). All energies are in MeV throughout the toolkit.",
)
parser.add_argument(
"--neutrino-mass",
type=float,
default=0.0,
help="Neutrino mass in MeV (default: 0.0). Set to non-zero value to include neutrino mass effects in phase space calculation.",
)
# Output
parser.add_argument(
@@ -139,6 +145,13 @@ def _build_parser() -> argparse.ArgumentParser:
"(default: 0.0 = include all branches). "
"Branches below this threshold are excluded from the calculation and plots.",
)
log_group.add_argument(
"--csv-verbosity",
type=str,
default="full",
choices=["full", "concise"],
help="CSV output verbosity: 'full' (all components) or 'concise' (total spectrum and normalized branch components only) (default: full)",
)
return parser
@@ -237,6 +250,7 @@ def _run(args: argparse.Namespace) -> None:
endpoint_MeV=decay_info.endpoint_MeV,
transition_type=decay_info.transition_type,
e_step_MeV=args.e_step,
neutrino_mass_MeV=args.neutrino_mass,
branches=branches,
intensity_cutoff=args.intensity_cutoff,
)
@@ -246,6 +260,7 @@ def _run(args: argparse.Namespace) -> None:
nuclide=source_value,
e_step_MeV=args.e_step,
intensity_cutoff=args.intensity_cutoff,
neutrino_mass_MeV=args.neutrino_mass,
)
else:
config = create_config_from_source(
@@ -253,6 +268,7 @@ def _run(args: argparse.Namespace) -> None:
nuclide=source_value,
e_step_MeV=args.e_step,
intensity_cutoff=args.intensity_cutoff,
neutrino_mass_MeV=args.neutrino_mass,
)
else:
logger.info("Source: JSON file=%s", source_value)
@@ -288,7 +304,9 @@ def _run(args: argparse.Namespace) -> None:
# Export to CSV
if args.output:
analyzer = BetaSpectrumAnalyzer(spectrum, config, logger=logger)
analyzer.export_to_csv(args.output, source_type=source_type)
analyzer.export_to_csv(
args.output, source_type=source_type, csv_verbosity=args.csv_verbosity
)
logger.info("Spectrum exported to %s", args.output)
# Generate plot
@@ -333,6 +351,7 @@ def _print_dry_run_output(config, source_type: str) -> None:
print(f"Endpoint: {config.endpoint_MeV * 1000:.1f} keV")
print(f"Transition: {config.transition_type}")
print(f"e_step: {config.e_step_MeV:.4f} MeV")
print(f"neutrino_mass_MeV: {config.neutrino_mass_MeV:.6f}")
print(f"Corrections: {', '.join(enabled) if enabled else 'none'}")
if config.branches and len(config.branches) > 1: