100 Commits
Author SHA1 Message Date
unzhakov 410e8b6524 style: apply black formatting after cleanup 2026-10-05 23:27:24 +03:00
unzhakov dc8e26403b docs: prune research vault to theory-only scope
Remove gA-extraction notes, nuclear-structure notes, paper-summary
refs, detector-response correction note and the finished test
migration checklist. Rewrite the vault index for the single-package
theory calculator; repoint dangling wiki-links in surviving notes to
inline citations; refresh docs_check.py (drop bs_exp CLI check,
register removed files).

Literature and nuclear-structure research resumes in dedicated
projects; the removed notes are recoverable from history.
2026-10-05 22:53:47 +03:00
unzhakov 6aced1d8ac docs: rewrite README, TODO, AGENTS and CONVENTIONS to theory-only scope
Compactify the descriptive markdown: scope statement replaces the
g_V-extraction goal, package architecture describes the single
theory-only distributable, roadmap keeps calculator capabilities
(C1-C8) and drops the analysis tracks, structure trees match the
actual file layout, the bs_exp debug step and detector-parameter
convention wording are dropped.
2026-10-05 17:20:27 +03:00
unzhakov e8b73eb20f test: check CSV header version against package version, not a literal 2026-10-05 15:14:57 +03:00
unzhakov 62042ae92a build: drop bs_exp entry point and root extra, bump version to 0.5.0
The experimental CLI and the PyROOT extra existed only for the
removed analysis packages. Version bump reflects the scope reduction
to theory-only spectrum calculation; calculation logic is unchanged.
2026-10-05 14:52:30 +03:00
unzhakov bc287e42a6 chore: remove local copies of raw detector data
Raw Tc99/A-major runs, Am-241 calibration files and the ROOT
histogram macro were measurement inputs for the analysis track that
left the project scope; the canonical copies live on the experiment
storage. Also removes scripts/analyze_raw.py, a rate-stability
analysis utility built on the exp_data reader.
2026-10-05 14:43:11 +03:00
unzhakov 57d5c7334a refactor: remove fitter analysis framework
Spectrum model, convolution, chi2 fit engine, C(W) and g_V/g_A
extractors and result containers are analysis code outside the
theory-only scope. Removes the package and its test suites.
2026-10-05 14:35:44 +03:00
unzhakov abde581146 refactor: remove exp_data experimental data package
Detector data handling, energy calibration, peak fitting and
instrumental corrections leave the project scope (theory-only
spectrum shape calculation). Removes the package, its tests, the
exp pipeline integration test, the calibration notebook, and the
ExpSpectrum fixtures from the shared conftest.
2026-10-05 14:31:56 +03:00
unzhakov 67de4e3baa style: canonicalize black formatting on test files 2026-10-03 01:31:35 +03:00
unzhakov 2788ea0683 feat(cli): separate-branches rename, short aliases, clean dry-run
- --normalize-to-one renamed to --separate-branches (no alias; the
  name now describes the output choice: total spectrum with
  intensity-normalized branches vs separate branches, each
  normalized to unit area with intensities left to the data user).
  SpectrumConfig.normalize_to_one -> separate_branches, CSV header
  word to_one -> separate.
- every long option gains a single-letter alias: -N -i -s -m -o -p
  -L -d -c -V -S -b (only -v/-q existed before)
- dry-run drops the top-level Transition: line — the per-branch
  list below already reports each branch's transition type
- version bumped to 0.4.1 (pyproject, __version__, CSV semantics
  docstring, TODO roadmap entry)
2026-10-03 01:08:51 +03:00
unzhakov 7f47a876ae style: apply black formatting to test files 2026-10-02 14:32:04 +03:00
unzhakov 7e31ac4b4e docs: reflect normalization fixes, detector cleanup and CLI overrides
- README: remove stale detector_response.py tree entry and the
  detector-models highlight (module removed); document per-branch
  measured transition endpoints from paceENSDF and JSON-flow CLI
  override semantics
- TODO: drop the DEFAULT_JSON_SCHEMA detector-keys clause (removed)
- data/custom_input_example.json: strip dead detector_* keys
2026-10-02 12:01:45 +03:00
unzhakov 36174b5d25 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
2026-10-02 10:21:07 +03:00
unzhakov 3590ca91a1 fix(nuclear_data): use measured transition endpoints per branch
paceENSDF stores the measured beta endpoint energy of each transition
(ENSDF column 7). The parser instead derived branch endpoints as
base-endpoint minus level energy with the base taken from an arbitrary
first-listed branch, so Co60 produced negative branch endpoints and a
hard ValueError (bs_pnpi Co60 exited 1 regardless of cutoff).

- BranchInfo carries the measured endpoint_MeV
- overall endpoint = max measured endpoint over all branches
- decay_info_to_config prefers measured endpoints; the subtraction is
  retained only as a legacy fallback for hand-built DecayInfo objects
- Co60/Tc99/Cs137 endpoint tests + CLI dry-run/export tests (D3)
2026-10-02 08:42:51 +03:00
unzhakov 9c3dd80b5c refactor(cli): delegate paceENSDF config building to library
Remove the duplicated inline paceENSDF config builder in the CLI.
It renormalized branch intensities before filtering, diverging from
the library decay_info_to_config path that library callers use
(audit finding D5). CLI paceENSDF configs now come from
create_config_from_source exactly once per run.

Regression test spies on create_config_from_source during a CLI run.
2026-10-02 07:13:14 +03:00
unzhakov d166532779 test: cover to_one/concise/single/plot normalization combinations 2026-10-02 06:31:38 +03:00
unzhakov 18a46ad02f feat(cli): propagate export options through JSON/paceENSDF flows
- main(argv) signature enables in-process CLI invocation and testing
- parser defaults for --e-step/--neutrino-mass/--intensity-cutoff/
  --csv-separator/--normalize-to-one now None = 'not provided'
- JSON flow applies file values by default and CLI flags as overrides
  (previously these five options were silently discarded)
- paceENSDF flow resolves None flags to literal defaults
- new tests/integration/test_cli_flows.py: JSON propagation,
  degenerate-mode non-zero exit with no file (JSON + paceENSDF)
- adapted two neutrino-mass default tests to None-parsing semantics
2026-10-02 05:46:08 +03:00
unzhakov 62bf7fdac2 fix(output): apply positive-integral export guard to to_one mode
CSVEmitter.export_to_csv raised ValueError only in intensity mode;
degenerate exports with --normalize-to-one silently wrote all-zero
CSV files. The guard now runs before the mode split and no file is
written in either mode.
2026-10-01 23:02:33 +03:00
unzhakov ee7aedc80a 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).
2026-10-01 22:04:17 +03:00
unzhakov 6bb7b950c7 style: apply black formatting to pending files 2026-09-30 10:41:28 +03:00
unzhakov ea4b652ccb chore: ignore ROOT data files produced by notebooks 2026-09-30 03:16:45 +03:00
unzhakov 40d0836056 docs: document core spectrum, physical branch columns, CSV-driven plots 2026-09-30 03:11:05 +03:00
unzhakov f5b79000a4 fix(scripts): list min/max calls, typed mains, drop unused header reads 2026-09-30 03:11:05 +03:00
unzhakov dc350aacfc fix(fitter): stop referencing removed detector_response module 2026-09-30 03:08:13 +03:00
unzhakov 8172ba2541 test: adapt existing suites to unconditional core, drop dead detector tests 2026-09-30 03:08:13 +03:00
unzhakov 7dc2ec79d1 feat(cli): report core in dry-run, build plots from exported CSV 2026-09-30 03:04:18 +03:00
unzhakov afb7afc5b7 feat(output): physical branch spectra, universal factor, CSV-driven plotting 2026-09-30 03:04:18 +03:00
unzhakov bab19de458 feat: make phase space and Fermi function unconditional core components 2026-09-30 03:04:18 +03:00
unzhakov 8bc9b0fd87 test: pin core-spectrum invariant (phase_space x fermi always included) 2026-09-30 03:04:18 +03:00
unzhakov 687e05cbe2 style: reformat assertion blocks in test files 2026-09-29 13:06:22 +03:00
unzhakov be3e288e0d docs: update documentation files and fix linting issues 2026-07-07 13:32:48 +03:00
unzhakov 9bf1e1333e refactor: rename visualize module to output module and separate concerns into core, csv_export, and visualization modules 2026-07-07 12:59:11 +03:00
unzhakov 6dc1e3924d feat: add CLI options for custom CSV separator and normalize-to-one branch normalization 2026-07-06 17:32:56 +03:00
unzhakov 1b4d418b5f feat: change CSV output format to use tab delimiters instead of comma delimiters 2026-07-03 18:01:39 +03:00
unzhakov 643e035c54 feat: update CSV headers and plot titles to show active/excluded branches and intensity cutoff exclusions 2026-07-03 17:45:35 +03:00
unzhakov c6aaf3b76a fix: use underscores in branch names for CSV headers in concise mode 2026-07-03 15:21:44 +03:00
unzhakov c2795bf86e fix: use underscores in branch names for CSV headers 2026-07-03 15:10:10 +03:00
unzhakov a7eef7bc20 feat: polish CSV header format with improved metadata and column naming 2026-07-03 14:58:19 +03:00
unzhakov 876e1e3ab8 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
2026-07-02 10:33:28 +03:00
unzhakov 406fd57bcd chore: add .pi-lens/ to .gitignore 2026-05-26 15:01:17 +03:00
unzhakov 8b0ced4b65 fix: resolve 4 fatal bugs — json_to_config, create_config_from_source, Am-241 constant, CLI positional args 2026-05-26 14:57:35 +03:00
unzhakov 38e97213c5 Remove root output 2026-05-22 18:25:57 +03:00
unzhakov 8599574723 docs: fix stale file references in TODO.md structure and completions 2026-05-22 15:18:17 +03:00
unzhakov 2fedd03d92 fix: bump __version__ to 0.4.0 to match pyproject.toml 2026-05-22 15:18:09 +03:00
unzhakov fd76eff109 docs: add docs_check.py to quality gates, add bs_exp CLI, document pytest markers 2026-05-22 15:18:00 +03:00
unzhakov 5dd9c7977a feat: add docs_check.py for automated documentation consistency checks 2026-05-22 15:17:52 +03:00
unzhakov d8838d19f4 chore: remove obsolete notebooks and add uv.lock 2026-05-22 12:20:36 +03:00
unzhakov ab164fbf98 fix: robust Am-241 calibration with width-constrained peak detection
- Use find_peaks width=(5,50) to reject noise bumps
- Simplify peak matching: find two strongest peaks with largest
  channel separation, assign min/max known energies
- Require absolute threshold of 400 counts to avoid noise peaks
- Calibration now correctly maps: ch 97→13.0 keV, ch 537→59.54 keV
- Tc-99 endpoint at ch 2750 → 293.6 keV (expected ~294)
- Add .rpiv/ to .gitignore
2026-05-21 18:21:51 +03:00
unzhakov 8952d0f789 fix: robust Am-241 peak detection for energy calibration
- Search full spectrum (exclude pulser region) instead of just low-energy
- Include 59.54 keV line in known Am-241 energies
- Brute-force peak-to-energy matching with physical gain constraint
  (3-40 ch/keV) to reject spurious fits
- Fixed find_peaks parameters: height=100, distance=5 for accurate
  peak detection
- Calibration now correctly maps: ch 97→13 keV, ch 134→17.4 keV,
  ch 537→59.6 keV, giving Tc-99 endpoint at ch 2750→291.6 keV
- Add .rpiv/ to .gitignore
2026-05-21 16:43:10 +03:00
unzhakov 5ec6305e09 fix: conditional matplotlib backend for interactive + headless use 2026-05-21 16:05:58 +03:00
unzhakov fa4e61a9f6 chore: add .rpiv/ to .gitignore 2026-05-21 16:03:20 +03:00
unzhakov 5c2b12c0e6 feat: experimental data calibration pipeline with ROOT I/O
- Fix chi2 calculation bug in calibration.py (remove incorrect
  coeffs[::-1] reversal in np.polyval)
- Fix broken beta_spectrum/cli.py (remove orphaned detector response
  add_argument calls and unused imports)
- Add ExpSpectrum.apply_calibration() and EnergyCalibrator.from_am241_spectrum()
- Add LivetimeDetermination class for pulser-based livetime
- Add SpectrumPipeline orchestration (read→subtract→calibrate→livetime→validate)
- Add ROOT I/O with PyROOT primary + uproot fallback
- Add bs_exp CLI with process, livetime, export subcommands
- Add exp_calibration notebook with pre-calibration visualization
- Add comprehensive tests (73 passing)
- Add bs_exp console script and [root] extra to pyproject.toml
- Remove obsolete detector_response module and unused notebooks
2026-05-21 16:01:25 +03:00
unzhakov caa4a77ebd fix: correct energy calibration from Am-241 peaks
- Am-241 peaks at ch 134=13.8, ch 163=17.8, ch 218=26.3 keV
- Calibration: E = 0.397 + 0.0995 × ch (previously wrong)
- Kurie fit endpoint 425 keV vs Q=297.5 keV — spectrum extends
  beyond MCA range (407 keV), simple extrapolation unreliable
- Proper endpoint extraction requires theory model + detector
  convolution (fitter module), not simple Kurie plot
2026-05-18 00:01:28 +03:00
unzhakov 42dcad56a2 fix: add data/raw/ to .gitignore 2026-05-17 22:57:19 +03:00
unzhakov 5f70e3a15a feat: add raw binary spectrum reader and data quality analysis
- exp_data/raw_reader.py: read binary MCA spectra (128-byte header,
  int32 counts), subtract cumulative spectra, Am-241 calibration
- exp_data/spectrum.py: allow negative counts for difference spectra
- scripts/analyze_raw.py: analyze 236 individual runs from cumulative
  data, compute rates and endpoint drift
- Am-241 calibration: E = -0.96 + 0.451 * ch (CAM1),
  E = 0.75 + 0.442 * ch (CAM2)
- Results: stable rate ~2M counts/run, stable endpoint ~374 keV
  (smeared Q-value), spike at runs 214-219 (acquisition glitch)
2026-05-17 22:55:52 +03:00
unzhakov 3c0a43ad4d docs: update TODO and AGENTS for v0.4.0 completion
- Mark v0.4.0 as complete in TODO.md with all phases checked
- Update Phase 4 items with actual outcomes
- Next step: Track A 99Tc spectrum-shape analysis
- Add AGENTS instruction to update project metadata on significant
  structural changes (package additions, version bumps, etc.)
2026-05-17 19:31:39 +03:00
unzhakov 38b44b56e6 feat: v0.4.0 package restructuring — split into 4 modules
Separate monolithic beta_spectrum package into:
  beta_spectrum   — pure theory (components, spectrum, CLI, visualize)
  exp_data        — experimental data handling (spectrum, calibration,
                    fitters, corrections)
  fitter          — analysis framework (model, fit_engine, extractor,
                    result)
  beta_spectrum.visualize — plotting (BetaSpectrumAnalyzer)

Phase 1 — exp_data module:
  ExpSpectrum dataclass with metadata, normalization, serialization
  EnergyCalibrator (linear/quadratic calibration)
  GaussianFitter + PeakFitter for calibration sources
  DeadTimeCorrection, PileUpCorrection, BackgroundSubtractor
  43 new tests, ruff + mypy clean

Phase 2 — fitter module:
  SpectrumModel wraps BetaSpectrum + DetectorResponse with convolution
  SpectrumFitter with χ² minimization, covariance, profile likelihood,
  confidence intervals, robust loss functions
  CWExtractor + GVAExtractor for C(W) and g_V/g_A extraction
  AnalysisResult + FitSummary for physics-specific results
  CurveFitter general-purpose callable model fitter
  34 new tests, ruff + mypy clean

Phase 3 — clean up beta_spectrum:
  Remove cw_extractor.py and fitter.py (moved to fitter/)
  Clean __init__.py to export only theory classes
  Add backward-compat methods to CWExtractor
  Fix BetaSpectrumAnalyzer._get_branch_spectrum returning BetaSpectrum
  objects instead of numpy arrays (plot fix)

Phase 4 — package structure:
  Auto-discovered by setuptools (4 packages)
  All imports updated across 26 source files
  Black formatting applied
  322 tests pass (262 original + 60 new)
  ruff + mypy clean on all source files

Bug fixes:
  - Fix multi-branch spectrum plotting: universal component keys
    (Fermi, Screening, etc.) don't have per-branch prefix; fixed
    fallback lookup.
  - Fix negative phase space beyond endpoint: BetaSpectrum returns
    negative values for W > W0; clamp branch spectra to zero.
2026-05-17 18:58:04 +03:00
unzhakov 745bbae4cd refactor: rename 'analyzer' to 'visualize' — analysis belongs to fitter module 2026-05-17 01:33:13 +03:00
unzhakov 10ad3a867b docs: restructure TODO.md with v0.4.0 package architecture plan 2026-05-17 00:34:16 +03:00
unzhakov 64785f4aa9 style: remove transition type from plot header — shown in branch legends instead 2026-05-16 23:24:33 +03:00
unzhakov 55cfb30b2b refactor: unify plotting — single-branch treated as multi-branch with one branch; remove old single-branch methods 2026-05-16 22:59:48 +03:00
unzhakov b3d6abb4d5 polish: unify plot output — external headers, compact legends, consistent titles 2026-05-16 21:21:28 +03:00
unzhakov f05a2de1b8 refactor: move BetaSpectrumAnalyzer to separate analyzer module 2026-05-16 20:41:58 +03:00
unzhakov 8314cee29c 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%)
2026-05-16 19:51:37 +03:00
unzhakov 1a23283cf1 fix: decay_info_to_config() now passes branches to SpectrumConfig; update docs for paceENSDF completion
- Fixed bug: decay_info_to_config() was dropping branches, causing
  create_config_from_source('paceENSDF') to return single-branch config
- Added BranchConfig import to nuclear_data.py
- Marked B1 (paceENSDF integration) as complete in TODO.md
- Updated README.md with paceENSDF details in Implementation Status
- Updated TODO.md Current Status with v0.3.1 notes
2026-05-16 18:50:06 +03:00
unzhakov 5276dcc851 docs: mark all migration phases complete in TODO 2026-05-15 16:54:45 +03:00
unzhakov 76d183b913 test: Phase 5 — advanced improvements
1. pytest-timeout (30s, thread-based) added to pyproject.toml
   - Prevents hangs in CI
   - timeout_method='thread' for clean cancellation

2. hypothesis added for property-based edge case discovery
   - tests/common/test_hypothesis_tests.py: 5 tests
   - Fermi: random Z, A, W — checks stability, monotonicity
   - Phase space: random W0, W — checks threshold/endpoint properties
   - Hypothesis already found real bugs:
     * Fermi monotonicity fails for Z < 10 (expected — finite-size dominates)
     * Phase space negative when W > W0 (test constrains W < W0)

3. pytest.mark.requires_ensdf marker added to TestPaceENSDFIntegration
   - Replaces bare @pytest.mark.skipif with documented marker
   - Allows running only ENSDF tests: pytest -m requires_ensdf

4. Updated test-migration-todo.md: Phase 5 complete

Final state: 256 tests passing (250 regular + 6 hypothesis + 6 skipped ENSDF)
2026-05-15 16:48:46 +03:00
unzhakov c96fb6175a test: add .gitkeep files and update TODO with phase 1-4 complete
- Add .gitkeep to tests/common/ and tests/integration/ directories
- Mark phases 1-4 as complete in test-migration-todo.md
- All migration work done: 251 tests passing
- Final structure:
  - tests/common/ — 3 files (shared helpers)
  - tests/physics/ — 10 files (physics behavior)
  - tests/quality/ — 8 files (API contracts)
  - tests/integration/ — 2 files (end-to-end)
2026-05-15 15:56:28 +03:00
unzhakov c78d0655a0 test: complete migration to structured test suite
Phase 1: Removed 6 duplicate old test files (fermi, finite_size, screening,
exchange, radiative, phase_space) — their tests are now in physics/ and quality/
using shared helpers from common/.

Phase 2: Migrated remaining 7 old test files:
- test_spectrum.py → integration/test_spectrum_pipeline.py (integration tests)
- test_fitter.py → physics/test_fitter.py (fit quality tests)
- test_cw_extractor.py → physics/test_cw_extractor.py (extraction accuracy)
- test_multi_branch.py → physics/test_multi_branch.py (branching physics)
- test_detector_response.py → physics/ + quality/ (split into physics + API)
- test_nuclear_data.py → quality/test_nuclear_data.py (parsing/API)
- test_logging_utils.py → quality/test_logging_utils.py (API tests)

Removed 12 old flat files, created 4 new files.
Total: 251 tests passing (6 skipped), down from 230 → 251 (net +21
from better coverage, not duplicates).

Test structure:
- tests/common/ — shared property/API helpers (eliminates ~18 duplicates)
- tests/physics/ — 10 files, unique physics behavior tests
- tests/quality/ — 8 files, API contract + parsing tests
- tests/integration/ — 1 file, end-to-end pipeline tests
2026-05-15 15:52:50 +03:00
unzhakov fea151d8d7 docs: add test migration TODO with 5-phase plan
- Phase 1: Remove duplicate old tests (6 files)
- Phase 2: Migrate remaining 7 old test files to new structure
- Phase 3: Create integration tests
- Phase 4: Clean up and verify
- Phase 5: Advanced improvements (slow markers, hypothesis, CI)
- Total: from 230 flat tests → ~240 organized tests in 3 directories
2026-05-15 15:09:13 +03:00
unzhakov 4b08df3873 test: create new test architecture with shared property/API tests
- Add tests/common/ with parametrized property tests (positivity, shape, NaN, stability)
- Add tests/physics/ with unique physics behavior tests for 6 correction components
- Add tests/quality/ with API contract tests for 6 correction components
- Add pytest markers in pyproject.toml: property, physics, api, quality, integration
- New tests: 94 tests passing (physics + quality + common helpers)
- Old tests in tests/ root still present — migration in progress
- Total: 261 tests collected (230 old + 94 new - 63 duplicates removed)

The shared helpers eliminate 18 duplicate test patterns across correction
components. Each component now has:
  - tests/physics/test_<name>.py — unique physics behavior
  - tests/quality/test_api_<name>.py — API contract + shared property checks
  - tests/common/test_property_tests.py — shared helpers (imported, not duplicated)
2026-05-15 15:04:52 +03:00
unzhakov bd14e3bb7a docs: add test architecture documentation
- Document current test suite state (230 tests, 79 CQT + 151 PT)
- Propose new directory structure: tests/{common,physics,quality,integration}
- Identify 18 duplicate test patterns across correction components
- Define pytest markers for test categorization
- Create implementation plan with 5 phases
2026-05-15 14:29:53 +03:00
unzhakov 4fb52fce2f docs/refs: flatten directory structure — move summary.md to parent folder
- Rename all summary.md files to YEAR_Author_Title.md in their parent folder
- Remove 2017_Hayen_analytical_beta_shape/references.bib
- Remove 2024_Paulsen_T99_beta_spectrum/img/ directory
- Eliminate one level of directory nesting for cleaner refs layout
2026-05-15 13:55:16 +03:00
unzhakov 030ae3e4b9 docs: restructure knowledge base into tree layout + gA extraction module
- Organize into tree structure: corrections/, nuclear-structure/, gA-extraction/, refs/
- Move all correction notes to corrections/ (01-09)
- Move nuclear structure to nuclear-structure/ with index
- Add gA-extraction/ with SSM algorithm, sNME/ESSM formalism, Tc99 case study, and implementation TODO
- Reorganize refs by topic (electromagnetic/, forbidden-decay/)
- Update all wikilinks to new paths
- Remove radiative_spec.md (code algorithm, not reference)
- Lint: all wikilinks verified valid
- Comprehensive gA extraction research based on Paulsen et al. (2024) and Song et al. (2025)
2026-05-14 19:46:39 +03:00
unzhakov 3acb23987a docs: add gA-driven shape factor parameterization (SSM) note
Comprehensive documentation on parameterizing the shape factor C(Z,W)
via g_A for forbidden nonunique beta decays, based on:
- Kostensalo et al. PRC 95, 044313 (2017) - SSM introduction
- Kostensalo & Suhonen PRC 96, 024317 (2017) - gA-driven evolution
- Paulsen et al. PRC 110, 055503 (2024) - 99Tc high-precision MMC measurement

Covers: shape factor decomposition, fitting algorithm, uncertainty budget,
implementation plan for ShapeFactorGA module, and literature summary.
2026-05-13 14:46:58 +03:00
unzhakov 984c4f6884 Add regression test for Tc99 ENSDF intensity values 2026-05-08 16:11:06 +03:00
unzhakov 620488860b Fix Tc99 branch intensity from paceENSDF
paceENSDF returns intensity at state[9] (percent), not state[8] (ENSDF
normalization field, ~1.0 for all branches). This was causing ~50/50
split for Tc99 instead of the correct 99.9984%/0.0016%.
2026-05-08 16:08:41 +03:00
unzhakov c404d83418 Remove 'universal_' prefix from CSV column names in multi-branch mode
Universal components (Fermi, Screening, etc.) are exported under their
plain names — no redundant prefix needed.
2026-05-08 15:54:13 +03:00
unzhakov a5144f2c33 Merge branch 'pi-dev/csv-branch-info-in-header' 2026-05-08 15:41:16 +03:00
unzhakov b02159ba5c Remove repeated per-branch metadata columns from CSV export
Branch intensity, endpoint, and transition are constant per branch and
already documented in the CSV header. No need to repeat them as columns
for every energy row.
2026-05-08 15:41:10 +03:00
unzhakov 9eb58bf101 feat: multi-branch decay support (B3) — per-branch transition types, intensity cutoff, raw-value plotting
- Extract per-branch forbiddenness codes from ENSDF (not defaulting to 'A')
- BranchConfig dataclass with endpoint, transition type, intensity validation
- Multi-branch BetaSpectrum with per-branch calculators and universal components
- Raw (un-normalized) plotting so total = arithmetic sum of branches
- --intensity-cutoff CLI option to filter negligible branches
- Branch-aware CSV export with per-branch spectra and components
- 30 comprehensive tests covering validation, calculation, export, edge cases
2026-05-08 08:36:29 +03:00
unzhakov ef337073d6 docs: update TODO and README for B3 completion and BranchConfig export
- Cross out B3 in TODO.md with completion details
- Export BranchConfig in __init__.py public API
- Update README to mention per-branch transition types and intensity cutoff
2026-05-08 08:35:01 +03:00
unzhakov 69eca97736 test: comprehensive multi-branch decay test suite (30 tests)
- BranchConfig validation (intensity bounds, positive endpoint)
- Single-branch via multi-branch path compatibility
- Multi-branch spectrum calculation and intensity weighting
- Per-branch spectra with correct endpoint and transition type
- Component extraction (universal vs branch-dependent)
- CSV export with total, per-branch, and universal components
- Transition type propagation from BranchInfo
- Branch values <= total spectrum verification
- Branch integral proportionality to intensity
- High-Z multi-branch stability
- No-branches defaults to single-branch mode
2026-05-08 08:34:30 +03:00
unzhakov 6293710089 feat: multi-branch CLI with intensity cutoff and per-branch info
- Add --intensity-cutoff CLI option to filter negligible branches
- Fetch DecayInfo from paceENSDF and construct SpectrumConfig with
  branches including per-branch transition types
- Normalize branch intensities to sum to 1.0, filter by cutoff
- Display branch info in dry-run output and logging
- Add intensity_cutoff to SpectrumConfig
2026-05-08 08:33:39 +03:00
unzhakov 3216c50943 feat: per-branch transition types from ENSDF and raw-value plotting
- Add transition_type field to BranchInfo and extract per-branch
  forbiddenness codes from paceENSDF (not defaulting all to 'A')
- Fix _multi_branch_call to use np.maximum instead of np.where mask
  so branches smoothly approach zero at endpoint
- Rewrite _plot_multi_branch_spectra and _plot_multi_branch_debug Panel 1
  to plot raw (un-normalized) branch contributions so total = sum of branches
- Remove independent unit-area normalization that made small branches
  appear larger than total
2026-05-08 08:33:12 +03:00
unzhakov 572e222c78 Merge dev/cli-logging-refinement to main
- Fix paceENSDF Q-value extraction (was reading half-life as Q-value)
- Fix RadiativeCorrection Z/A parameters
- Add debug verification workflow (bs_pnpi -vv)
- Add plot output with ID tracking and two display modes
- Fix pyright/mypy type errors across codebase
- Add ./output/ directory for test artifacts
- Update docs and development workflow
2026-05-05 14:35:36 +03:00
unzhakov 4a3d31de83 Update docs and TODOs for CLI & plot improvements
- README.md: Add features for plot modes, traceability, debug workflow
- README.md: Update BetaSpectrumAnalyzer docs with show_components param
- README.md: Update Quick Start with both plot modes
- README.md: Add output/ to project structure
- TODO.md: Mark B8.4 plot output as completed
- TODO.md: Update Current Status with B8.4
2026-05-05 14:35:11 +03:00
unzhakov 5ac004352b Fix mypy type errors and black formatting
- spectrum.py: Use Axes from TYPE_CHECKING instead of plt.Axes
- fitter.py: Remove unused type: ignore comment
- phase_space.py: Black formatting
2026-05-05 14:01:28 +03:00
unzhakov d6328d4b24 Enhance plot output with ID tracking and two display modes
- Add commit hash (6 chars) and UTC timestamp to all plots via text boxes
- Add nuclear data header (nuclide, endpoint, transition, corrections) to plots
- Two display modes:
  - DEBUG (-vv): 4-panel debug view with all correction factors
  - Normal (default): single spectrum plot with nuclear data header
- CLI: --plot now passes show_components=(args.verbose >= 2)
2026-05-05 13:33:46 +03:00
unzhakov 3749220efc Fix pyright type errors and correct paceENSDF Q-value extraction
- nuclear_data.py: Extract Q-value from ground state branch state[7] instead of
  halflife_data (was reading half-life seconds as Q-value)
- nuclear_data.py: Use ground state branch for forbiddenness code, with fallback
- nuclear_data.py: Add None guards for beta_data and pairs
- spectrum.py: Pass Z=config.Z_daughter, A=config.A_number to RadiativeCorrection
- phase_space.py: Add __init__ debug logging (W0, transition_type, m_e, m_nu)
- phase_space.py: Add output range logging in __call__
- phase_space.py: Fix possibly unbound forbid_factor variable
- logging_utils.py: Fix broken get_git_short_hash indentation
- cli.py: Add explicit SpectrumConfig annotation to fix pyright type identity
- cw_extractor.py: Fix T_to_W ndarray→float conversions (6 locations)
- cw_extractor.py: Fix FermiFunction() calls — was passing Z as __call__ arg
- fitter.py: Add explicit dict type annotation for least_squares kwargs
2026-05-05 12:43:43 +03:00
unzhakov 297778d780 Add ./output/ directory for debug verification artifacts and update development workflow
- Create ./output/ with .gitkeep for test run outputs
- Add output/* to .gitignore (negated .gitkeep)
- Add §4.5 Debug Verification to DEVELOPMENT.md: final step of each dev iteration
  - Run bs_pnpi -vv with full parameter consistency checks
  - Required debug logging per component documented
  - Example commands and success criteria
- Update Agent Instructions and Release Checklist
- Mark B8.3 debug verification framework as completed in TODO.md
2026-05-05 10:48:53 +03:00
unzhakov 330ebddaef refactor: refine CLI options and enhance debug logging
- 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
2026-05-05 09:08:08 +03:00
unzhakov eb52c3b918 Merge dev/update-b2-status: cross out B2 (Input Flexibility) as implemented
- JSON input fully implemented: load_json_input(), json_to_config(),
  DEFAULT_JSON_SCHEMA with full detector params, CLI --input flag
- ENSDF auto-population fully implemented: get_decay_info_from_paceENSDF()
  returns DecayInfo with Z_parent, Z_daughter, A_number, endpoint_MeV,
  transition_type, forbiddenness_code, half_life, branches;
  CLI --nuclide uses this automatically
- Update Current Status to reflect B2 completion
2026-05-04 17:36:45 +03:00
unzhakov 7a925725ad docs: cross out B2 (Input Flexibility) as implemented
- JSON input fully implemented: load_json_input(), json_to_config(),
  DEFAULT_JSON_SCHEMA with full detector params, CLI --input flag
- ENSDF auto-population fully implemented: get_decay_info_from_paceENSDF()
  returns DecayInfo with Z_parent, Z_daughter, A_number, endpoint_MeV,
  transition_type, forbiddenness_code, half_life, branches;
  CLI --nuclide uses this automatically
- Update Current Status to reflect B2 completion
2026-05-04 17:06:47 +03:00
unzhakov 0b5fe88f7b docs: remove stale checkboxes, consolidate README vs TODO
- TODO.md: cross out completed A2 (detector response) and A4 (fitter/CW extraction) items with strikethrough and implementation notes
- README.md: replace redundant Components and Additional Modules tables with Implementation Status section referencing TODO.md
- Eliminates duplicate status tracking between README and TODO
2026-05-04 16:01:54 +03:00
unzhakov 3182ceb675 Merge dev/logging-infrastructure: structured logging, CSV headers, CLI improvements
- New logging infrastructure (beta_spectrum/logging_utils.py)
- CLI flags: -v/-vv/-q, --log-file, --dry-run, --version
- CSV metadata headers with version, timestamp, nuclide info, git hash
- Opt-in logging design (zero overhead for library users)
- 28 new tests, 195 total tests passing
2026-05-04 15:46:29 +03:00
unzhakov 9050019ddd feat: add structured logging, CSV metadata headers, and CLI improvements
- New module: beta_spectrum/logging_utils.py
  - LoggingConfig dataclass with level, log_file, format options
  - setup_logging() one-shot configuration (opt-in for library use)
  - get_logger() for named child loggers
  - get_git_short_hash() for commit identification
  - _find_git_root() for repo detection

- CLI enhancements (beta_spectrum/cli.py):
  - --verbose/-v (repeatable): -v=INFO, -vv=DEBUG
  - --quiet/-q: suppress all terminal output
  - --log-file PATH: append log to file
  - --dry-run: validate input, display resolved config, exit
  - --version: show package version
  - Replace print() with structured logging throughout
  - Handle KeyboardInterrupt gracefully

- CSV metadata headers (BetaSpectrumAnalyzer.export_to_csv):
  - YAML-style # comments with version, timestamp, source, nuclide info
  - Corrections enabled, e_step, detector settings, git commit hash

- Base class integration (SpectrumComponent):
  - Optional logger parameter for debug/info output (opt-in)

- BetaSpectrum integration:
  - Optional logger parameter passed through from_config()
  - Detector logging in create_detector_from_config()
  - Convolution logging in convolve_with_detector()

- Tests: tests/test_logging_utils.py (28 tests)
  - LoggingConfig, setup_logging, get_logger, git hash, CSV headers, CLI flags

- Update TODO.md: mark B8 as complete, update Current Status
2026-05-04 15:11:01 +03:00
unzhakov 1a0754be5f docs: remove empty recoil.py stub, update README and TODO to reflect actual state
- Remove empty beta_spectrum/components/recoil.py (0-line stub)
- Remove recoil.py from README.md project tree and components table
- Update TODO.md: replace specific recoil section with generic 'Additional
  Corrections' deferred item, update Current Status to 0.3.0 with actual
  implementation list, mark A4 as complete, set A3 as next step
2026-05-04 11:56:41 +03:00
unzhakov 4ceaa32ed1 Add some sanyty testing ipynb notebooks 2026-05-04 10:55:30 +03:00
unzhakov 1ebf95de60 fix/Slight fix to DEVELOPMENT.md 2026-05-04 07:34:19 +03:00