refactor: remove stale detector schema keys and single-mode duplicates
- DEFAULT_JSON_SCHEMA: drop the 8 detector_* keys left over from the removed detector_response module; CLI dry-run drops the dead 'Detector: not configured (Phase 4)' line - CSV export: single-mode no longer writes branch_1_PhaseSpace / branch_1_Radiative duplicates next to the bare PhaseSpace/Radiative columns; per-branch core factors only in multi-branch mode - Visualizer: debug panels fall back to the unprefixed core-factor columns for single-mode CSVs instead of skipping them - Spectrum ylabel now states the actual units: normalized spectrum [MeV^-1], not 'Normalized Counts / keV' - tests: defaults assert detector keys gone; column layout pinned for single vs multi; panel and ylabel assertions
This commit is contained in:
@@ -372,8 +372,6 @@ def _print_dry_run_output(config, source_type: str) -> None:
|
||||
else:
|
||||
print("Mode: single-branch")
|
||||
|
||||
# Detector response is a Phase 4 feature — not yet implemented
|
||||
print("Detector: not configured (Phase 4)")
|
||||
print("========================================")
|
||||
|
||||
|
||||
|
||||
@@ -554,14 +554,6 @@ DEFAULT_JSON_SCHEMA = {
|
||||
"transition_type": "F2",
|
||||
"e_step_MeV": 0.001,
|
||||
"neutrino_mass_MeV": 0.0,
|
||||
"detector_model": "gaussian",
|
||||
"detector_sigma_a_keV": 1.0,
|
||||
"detector_sigma_b": 0.0,
|
||||
"detector_tail_fraction": 0.0,
|
||||
"detector_tau_keV": 5.0,
|
||||
"detector_fano_factor": 0.12,
|
||||
"detector_n_channels": 4096,
|
||||
"detector_channel_energy_range": [0.0, 0.35],
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -211,14 +211,20 @@ class CSVEmitter:
|
||||
|
||||
if csv_verbosity == "full":
|
||||
# Per-branch component columns (factorized ingredients).
|
||||
for i in range(n_branches):
|
||||
for comp_name in ["PhaseSpace", "Radiative"]:
|
||||
key = analyzer._get_component_key(i, comp_name)
|
||||
if key in components:
|
||||
data[f"branch_{i + 1}_{comp_name}"] = components[key]
|
||||
# Only multi-branch mode carries per-branch factors: in single
|
||||
# mode the bare PhaseSpace/Radiative columns below already
|
||||
# describe the single spectrum, and prefixed duplicates would
|
||||
# silently disagree with them once renamed.
|
||||
if analyzer._is_multi:
|
||||
for i in range(n_branches):
|
||||
for comp_name in ["PhaseSpace", "Radiative"]:
|
||||
key = analyzer._get_component_key(i, comp_name)
|
||||
if key in components:
|
||||
data[f"branch_{i + 1}_{comp_name}"] = components[key]
|
||||
|
||||
# Universal components (no prefix): Fermi plus universal
|
||||
# higher-order corrections.
|
||||
# higher-order corrections. In single mode the core factors
|
||||
# (PhaseSpace, Radiative) also appear here unprefixed.
|
||||
for name, values in components.items():
|
||||
if not name.startswith("branch_"):
|
||||
data[name] = values
|
||||
|
||||
@@ -235,7 +235,6 @@ def _plot_spectra_view_from_df(
|
||||
) -> Figure:
|
||||
"""Plot total spectrum and per-branch spectra from CSV columns."""
|
||||
energies = df["energy_MeV"].to_numpy()
|
||||
e_step_keV = (meta["e_step_MeV"] or 0.0) * 1000.0
|
||||
|
||||
fig, ax = plt.subplots(figsize=(12, 7))
|
||||
|
||||
@@ -266,7 +265,7 @@ def _plot_spectra_view_from_df(
|
||||
)
|
||||
|
||||
ax.set_xlabel(r"Electron kinetic energy $E$ [MeV]", fontsize=12)
|
||||
ax.set_ylabel(f"Normalized Counts / {e_step_keV:.1f} keV", fontsize=12)
|
||||
ax.set_ylabel(r"Normalized spectrum [MeV$^{-1}$]", fontsize=12)
|
||||
fig.suptitle(_spectrum_title(meta), fontsize=14, fontweight="bold")
|
||||
ax.set_yscale("log")
|
||||
ax.grid(True, alpha=0.3)
|
||||
@@ -288,7 +287,6 @@ def _plot_debug_view_from_df(
|
||||
) -> Figure:
|
||||
"""Debug view (4 panels) built entirely from CSV columns."""
|
||||
energies = df["energy_MeV"].to_numpy()
|
||||
e_step_keV = (meta["e_step_MeV"] or 0.0) * 1000.0
|
||||
active = _active_branches(meta)
|
||||
|
||||
fig, axes = plt.subplots(4, 1, figsize=(12, 16), sharex=True)
|
||||
@@ -318,7 +316,7 @@ def _plot_debug_view_from_df(
|
||||
label=f"Br. {b['index']} ({b['intensity'] * 100:.1f}%)",
|
||||
)
|
||||
ax.set_yscale("log")
|
||||
ax.set_ylabel(f"Normalized Counts / {e_step_keV:.1f} keV", fontsize=10)
|
||||
ax.set_ylabel(r"Normalized spectrum [MeV$^{-1}$]", fontsize=10)
|
||||
ax.set_title("Spectrum", fontsize=11)
|
||||
ax.grid(True, alpha=0.3)
|
||||
ax.legend(fontsize=8, loc="best", ncol=2)
|
||||
@@ -331,6 +329,9 @@ def _plot_debug_view_from_df(
|
||||
ax.plot(energies, fermi_scaled, "r-", lw=1.5, label="Fermi", alpha=0.8)
|
||||
for color_i, b in enumerate(active):
|
||||
col = f"branch_{b['index']}_PhaseSpace"
|
||||
if col not in df.columns:
|
||||
# Single-branch CSVs carry the core factors unprefixed.
|
||||
col = "PhaseSpace"
|
||||
if col not in df.columns:
|
||||
continue
|
||||
ps_vals = df[col].to_numpy()
|
||||
@@ -374,6 +375,9 @@ def _plot_debug_view_from_df(
|
||||
ax = axes[3]
|
||||
for color_i, b in enumerate(active):
|
||||
col = f"branch_{b['index']}_Radiative"
|
||||
if col not in df.columns:
|
||||
# Single-branch CSVs carry the core factors unprefixed.
|
||||
col = "Radiative"
|
||||
if col not in df.columns:
|
||||
continue
|
||||
ax.plot(
|
||||
|
||||
Reference in New Issue
Block a user