refactor: restructure metadata files for context efficiency
- Shrink global AGENTS.md: 153 → 56 lines (−63%) Removed: git workflow, TDD, overthinking guards, code style, reasoning protocol Kept: personality, git basics, thinking levels, general principles, backend - Create project AGENTS.md: 71 lines Added: stack/commands, GitHub Flow git workflow, Conventional Commits, TDD (Python-specific), quality gates, debug verification - Trim CONVENTIONS.md: 161 → 68 lines (−58%) Removed: verbose examples, redundant unit convention section, lengthy SpectrumComponent code example - Delete DEVELOPMENT.md: 238 lines → 0 (migrated to AGENTS.md) Setup/release checklist removed (not agent concerns) Git workflow, TDD, quality gates, notebook QC, debug verification all migrated to AGENTS.md - Update README.md project structure Total per-session metadata: 552 → 195 lines (−65%)
This commit is contained in:
+36
-129
@@ -1,161 +1,68 @@
|
||||
# Project Conventions
|
||||
|
||||
This file defines the physical, mathematical, and architectural conventions that govern code correctness and consistency across the project.
|
||||
Physical, mathematical, and architectural conventions governing code correctness.
|
||||
|
||||
## 1. Natural Units System
|
||||
## 1. Natural Units
|
||||
|
||||
All internal representations, calculations, and definitions use natural units:
|
||||
All internal calculations 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.
|
||||
`m_e` is the electron rest mass. Fundamental unit for energy, mass, momentum, and time.
|
||||
|
||||
## 2. Energy Representation
|
||||
|
||||
### Core Principle
|
||||
**Internal:** total energy `W` in m_e units (`W = 1.0` = rest mass, `W > 1.0` = kinetic).
|
||||
|
||||
Internal calculations use natural units (m_e). External interfaces (API signatures, plots, human-readable output) use eV-based units (MeV or keV).
|
||||
**External API:** human-readable MeV/keV. Check the unit suffix in parameter names:
|
||||
- `_MeV` suffix → value is in MeV
|
||||
- `_keV` suffix → value is in keV (detector params only)
|
||||
- No suffix on energy → value is in m_e units (internal)
|
||||
|
||||
### API Signatures (Input)
|
||||
### Conversion
|
||||
|
||||
Use human-readable MeV for parameters that come from databases or literature:
|
||||
|
||||
- `endpoint_MeV` — Q-value / endpoint energy in MeV
|
||||
- `detector_sigma_a_keV` — resolution in keV
|
||||
- `detector_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.0` corresponds to zero kinetic energy (rest mass)
|
||||
- `W > 1.0` corresponds 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
|
||||
|
||||
```python
|
||||
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:
|
||||
Always use central utilities — never hardcode constants or manual arithmetic:
|
||||
|
||||
```python
|
||||
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. SpectrumComponent Design
|
||||
|
||||
## 3. Energy Unit Convention
|
||||
All spectral components follow a common interface:
|
||||
|
||||
### MeV Throughout
|
||||
|
||||
All energy parameters in the public API use **MeV** as the standard unit:
|
||||
|
||||
- `endpoint_MeV` — always in MeV
|
||||
- `e_step_MeV` — always in MeV
|
||||
- `detector_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:
|
||||
- `_MeV` suffix → value is in MeV
|
||||
- `_keV` suffix → 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
|
||||
- **Stateless or minimally stateful** — no mutable state depending on input
|
||||
- **Vectorized** — accept/return `np.ndarray`, support broadcasting
|
||||
- **Consistent energy variable** — always `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
|
||||
- **Return correction factor** — multiplicative factor, typically ~0.1 to 10
|
||||
|
||||
```python
|
||||
class MyComponent(SpectrumComponent):
|
||||
def __init__(self, param1: float, param2: float):
|
||||
self.param1 = param1
|
||||
self.param2 = param2
|
||||
## 4. Logging
|
||||
|
||||
def __call__(self, W: np.ndarray) -> np.ndarray:
|
||||
# All internal computation uses W in m_e units
|
||||
return ...
|
||||
```
|
||||
- **No verbosity (default):** errors and warnings only
|
||||
- **`-v` (INFO):** source selection, component init, workflow steps, output locations
|
||||
- **`-vv` (DEBUG):** all INFO + detailed internals (parameters, ranges, evaluation counts)
|
||||
|
||||
## 5. Logging Convention
|
||||
Each `SpectrumComponent` logs:
|
||||
- **INFO** at init: component name + key parameters
|
||||
- **DEBUG** at evaluation: energy point count, input/output ranges
|
||||
|
||||
### Verbosity Levels
|
||||
## 5. Nuclear Data Notation
|
||||
|
||||
- **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)
|
||||
- Element: `Tc`, `Ru`, `U`
|
||||
- Nuclide: `Tc99`, `Ru99`, `U238`
|
||||
- Decay: `Tc99 -> Ru99` (parent → daughter)
|
||||
- CSV headers use element notation: `# nuclide: Tc99 -> Ru99 (Z=43->44)`
|
||||
|
||||
### Component Logging
|
||||
## 6. Physics Testing Guidelines
|
||||
|
||||
Each `SpectrumComponent` logs at two levels:
|
||||
When testing physics components, verify:
|
||||
|
||||
- **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)
|
||||
- **Physical constraints** — values at thresholds, endpoints, boundaries match known physics
|
||||
- **Positivity** — no unphysical negative values
|
||||
- **Shape correctness** — output shape matches input (vectorized)
|
||||
- **Type safety** — components accept/return `np.ndarray`
|
||||
- **Numerical stability** — no NaN/inf in physical range (except where physically expected)
|
||||
|
||||
Reference in New Issue
Block a user