- Remove --mode, --transition-type, and --decay-index CLI flags
(parameters now come from ENSDF data or custom JSON input)
- Clarify energy units in all CLI help text (MeV throughout, keV for detector params)
- Enhance logging verbosity:
- -v (INFO): shows source, component initialization, workflow steps
- -vv (DEBUG): shows detailed internals of all spectrum components
(parameters, evaluation counts, input/output ranges)
- Improve CSV headers with element notation (e.g. Tc99 -> Ru99)
- Add CONVENTIONS.md documenting energy unit and logging conventions
- Update TODO.md with completion status
5.6 KiB
Project Conventions
This file defines the physical, mathematical, and architectural conventions that govern code correctness and consistency across the project.
1. Natural Units System
All internal representations, calculations, and definitions use natural units:
m_e = ℏ = c = 1
where m_e is the electron rest mass. This is the fundamental unit for energy, mass, momentum, and time throughout the codebase.
2. Energy Representation
Core Principle
Internal calculations use natural units (m_e). External interfaces (API signatures, plots, human-readable output) use eV-based units (MeV or keV).
API Signatures (Input)
Use human-readable MeV for parameters that come from databases or literature:
endpoint_MeV— Q-value / endpoint energy in MeVdetector_sigma_a_keV— resolution in keVdetector_tau_keV— tail decay constant in keV
Internal Representation
All internal computations use total energy W in m_e units:
W = T_to_W(T_MeV) # T (kinetic) in MeV → W (total) in m_e
W = T + 1.0 # W = T/m_e + 1 (since m_e = 1 in m_e units)
W = 1.0corresponds to zero kinetic energy (rest mass)W > 1.0corresponds to kinetic energy- All internal functions accept and operate on
W - Endpoint W0 is always
T_to_W(endpoint_MeV)
Output and Display
Convert back to eV units for anything intended for human perception:
- Plots: x-axis in keV or MeV (kinetic energy)
- ASCII output, CSV export: kinetic energy in keV or MeV
- Log messages, error messages: use keV/MeV with context
kinetic_keV = (W - 1.0) * ME_KEV # W in m_e → kinetic energy in keV
kinetic_MeV = (W - 1.0) * ME_ME # W in m_e → kinetic energy in MeV
Conversion Helpers
All conversions and constants must go through the central utilities:
from beta_spectrum.utils import T_to_W, W_to_T
from beta_spectrum.constants import ME_MEV, ME_KEV, ALPHA, MP_MEV
- Never hardcode physical constants — import from
constants.py - Never use manual arithmetic for unit conversion — use
T_to_W(),W_to_T() - Never mix MeV and m_e units in the same calculation
3. Energy Unit Convention
MeV Throughout
All energy parameters in the public API use MeV as the standard unit:
endpoint_MeV— always in MeVe_step_MeV— always in MeVdetector_sigma_a_keV— in keV (detector-specific, exception noted)detector_tau_keV— in keV (detector-specific, exception noted)
Detector parameters use keV because detector resolutions are typically specified in keV in the literature. All other energies use MeV.
CLI Unit Convention
All CLI energy parameters use MeV unless explicitly marked otherwise:
--e-step— MeV (default: 0.001)--sigma— keV (detector resolution, default: 1.0)--tau— keV (tail decay constant, default: 5.0)
Consistency Rule
When reading or writing values, always check the unit suffix in the parameter name:
_MeVsuffix → value is in MeV_keVsuffix → value is in keV- No suffix on energy parameter → value is in m_e units (internal)
4. SpectrumComponent Design
All spectral components (Fermi function, screening, radiative correction, etc.) follow a common interface:
- Stateless or minimally stateful — no mutable state that depends on input
- Vectorized — accept and return
np.ndarray, support array broadcasting - Consistent energy variable — always use
W(total energy in m_e units) internally - Callable interface — implement
__call__(W)for uniform usage - Return correction factor — output is a multiplicative factor, typically ~0.1 to 10
class MyComponent(SpectrumComponent):
def __init__(self, param1: float, param2: float):
self.param1 = param1
self.param2 = param2
def __call__(self, W: np.ndarray) -> np.ndarray:
# All internal computation uses W in m_e units
return ...
5. Logging Convention
Verbosity Levels
- No verbosity (default): Only errors and warnings
-v(INFO): Shows source selection, component initialization, workflow steps, and output locations-vv(DEBUG): Shows all INFO messages plus detailed internals of each spectrum component (parameters, input/output ranges, evaluation counts)
Component Logging
Each SpectrumComponent logs at two levels:
- INFO at initialization: Component name and key parameters
- DEBUG at evaluation: Number of energy points, input/output value ranges
This allows debugging without cluttering normal output.
6. Nuclear Data Notation
Element and Nuclide Notation
- Element symbol:
Tc,Ru,U, etc. (from atomic number) - Nuclide notation:
Tc99,Ru99,U238(element symbol + mass number) - Decay notation:
Tc99 -> Ru99(parent -> daughter)
CSV Header Convention
CSV metadata headers use element notation for readability:
# nuclide: Tc99 -> Ru99 (Z=43->44)
This provides both the human-readable notation and the machine-parseable Z values.
7. Physics-Specific Testing Guidelines
When writing tests for physics components, verify the following:
- Physical constraints — values at thresholds, endpoints, and boundaries must match known physics behavior
- Monotonicity / positivity — spectrum components should not produce unphysical negative values; monotonicity should match physical expectations
- Shape correctness — output shape must match input shape (vectorized operation)
- Type safety — components accept and return
np.ndarray - Numerical stability — no NaN or inf in the physical energy range, except where physically expected (e.g., below kinematic threshold, near soft-photon endpoint divergence)