Commit Graph

66 Commits

Author SHA1 Message Date
lars e5bf7c51cb Fix silent failure modes surfaced by extensive code review
- energy_simplex_encode: warn when clipping post_E to pre_E discards
  recorded edep/e_sec instead of silently zeroing them
- local/inv_local_frame_rotation: validate and normalize pre_dir instead
  of silently assuming unit norm; raise on near-zero-norm rows
- train(): make --lr authoritative on resume instead of being silently
  overwritten by the checkpoint's optimizer/scheduler state; print and
  exit cleanly instead of silently training zero epochs when the
  checkpoint already meets --epochs; truncate metrics.csv on a fresh
  run instead of always appending
- dwarf update-manifest: check file existence for every manifest line,
  not just ones whose gen/schema actually changed
- pyproject.toml: dev extra now pulls in convert+analysis so the
  documented `uv sync --extra cpu --extra dev` + `pytest` actually
  passes collection

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-02 16:54:02 +02:00
lars 857d8b315f Show VERSIONS.md reason extracts in dwarf status
Parses the gen/schema log lines apply_bump() writes to VERSIONS.md and
prints a truncated reason under each gen/schemaN row, so `dwarf status`
answers "why does this version exist" without opening the changelog.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-02 11:13:35 +02:00
lars 57e044e347 Add file counts and reference tracking to dwarf status
Shows per-directory file counts throughout the tree, plus a referenced
count for raw/ (matched against any same-named parquet under processed/)
and each schemaN dir (matched against pools/*.manifest entries).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-02 11:09:47 +02:00
lars 7761cd21b6 Color-code dwarf status output by tree level
Each row (kind header, gen, raw/processed, schema, root totals) gets a
distinct ANSI color so the hierarchy is easier to scan. Disabled when
stdout isn't a TTY or NO_COLOR is set.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-02 10:34:06 +02:00
lars c0746c40e0 Add disk usage summary to dwarf status
Shows per-schema, per-gen (raw/processed split), per-kind, and grand
total sizes so the dataset tree's footprint is visible at a glance.
2026-07-02 10:10:51 +02:00
lars b6e0fa59a4 Merge origin/energy-conservation-poc (--to/--gen flags, train date-prefix)
Both commits' changes were already folded in by hand in the previous
commit; this merge just records the shared history so the branches
reconcile cleanly.
2026-07-02 09:57:20 +02:00
lars 917835e182 Fold --to/--gen dataset-versioning flags into the dwarf CLI
origin/energy-conservation-poc grew bump-gen/bump-schema --to and
update-manifest --gen flags (091b23a) plus a train output-dir date
prefix (305e436) after the dwarf unification was written locally.
Reconcile: bring plan_bump_gen/plan_bump_schema/plan_update_manifest's
target/target_gen support into the plain-function (argparse-free) form,
thread --to/--gen through scripts/dwarf.py's bump-gen/bump-schema/
update-manifest commands, and take giant/cli.py's date-prefix change
and the associated tests as-is.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-02 09:57:17 +02:00
lars d5853d5a75 Unify dataset/tooling scripts into a single dwarf Typer CLI
Replace the five separately-hyphenated uv entry points (steps-to-parquet,
steps-to-parquet-parallel, migrate-geant-steps, bump-dataset-version,
create-root-files) plus the unregistered hparam_scan.py with one `dwarf`
command exposing convert/migrate/bump-gen/bump-schema/status/
update-manifest/create-manifest/make-root/hparam-scan as subcommands.

Each scripts/*.py module now only holds argparse-free business logic;
scripts/dwarf.py wires it up with Typer, matching giant/cli.py's style.
`dwarf convert` merges the old serial/parallel conversion scripts behind
a --jobs flag (default 1: sequential with plain -o; >1: dataset-layout
fan-out via subprocess).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-02 09:52:37 +02:00
lars 305e436783 Prefix default train output dir with current date
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 16:15:19 +02:00
lars 091b23a60f Add --to flag for bump-gen/bump-schema and --gen flag for update-manifest
bump-gen and bump-schema now accept --to genN/schemaN to target a specific
version instead of always auto-incrementing. update-manifest gains --gen genN
to repoint the gen component of manifest paths (combinable with --schema).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 15:58:26 +02:00
lars 7b37b284f8 WIP: energy-conservation PoC analysis/transforms updates 2026-07-01 13:58:44 +02:00
lars c627142135 Route predict output to UUID-named parquet with YAML reference sidecar
When no --out is given, predictions are written to a UUID-named parquet
(/ceph central store for ceph inputs, sibling directory otherwise) and a
YAML reference file is created next to the checkpoint recording the output
path, dataset, checkpoint, and timestamp. Adds pyyaml as a core dependency
and unit tests for the two new helper functions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 09:57:14 +02:00
lars caaf3c6102 Restrict holdout overlap check to holdout vs dev/full only
dev and full are allowed to share files — only holdout must be strictly
isolated. When creating dev or full, only compare against holdout.manifest;
when creating holdout, compare against all other manifests in the dir.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 11:24:05 +02:00
lars f56a45690d Add update-manifest and create-manifest subcommands to bump_dataset_version
update-manifest rewrites the schemaN component in existing manifest files to a
specified or auto-detected highest schema, verifying all target files exist before
writing. create-manifest builds a new manifest from explicit parquet file paths,
supporting --pool/--type (full|holdout|dev) to derive the output path from root,
and enforcing holdout isolation by checking for cross-manifest overlap whenever a
holdout manifest is involved.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 11:03:32 +02:00
lars 6b85e2c90b Add --copy mode to migrate_geant_steps.py
Lets the migration run while another process still has the original files
open for reading: --copy uses shutil.copy2 instead of move, and skips the
now-empty-directory cleanup since the legacy train/ etc. dirs stay populated
by design.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 17:20:13 +02:00
lars 5be91e0d17 Expose dataset/conversion scripts as uv entry points
scripts/ is now a proper package (scripts/__init__.py, added to the wheel's
packages), with each script registered under [project.scripts] using its
bare dashed name (e.g. `uv run migrate-geant-steps`). Tests now import these
modules normally instead of loading them by file path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 16:51:47 +02:00
lars 320365606a Add tooling for a versioned geant_steps dataset layout
Introduces raw/<kind>/<gen>/<detector>/shard-NNN.root and
processed/<kind>/<gen>/<schema>/<detector>/shard-NNN.parquet as the dataset
convention, plus scripts to operate on it: migrate_geant_steps.py for the
one-time move into this layout, bump_dataset_version.py to cut new
gen/schema versions with a logged reason, steps_to_parquet_parallel.py to
convert ROOT shards to parquet in parallel and place them correctly, and
create_root_files.py to generate new ROOT shards via a minicalosim
executable. The loader gains .manifest file support so pools/ (train/dev/
holdout shard lists) can be passed straight to `giant train`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 16:46:48 +02:00
lars 8475199609 Encode edep/secondary/post energy as a conservation-constrained simplex
Replaces the independent log_delta_e/log_edep targets with 2 additive-log-ratio
coordinates over the deposit/secondary/post-energy simplex (fractions of pre_E
summing to 1), so edep + e_sec + post_E == pre_E holds by construction after
decoding (softmax) rather than being learned approximately. Requires e_sec
(secondary energy) as a new conditioning input and a steps_to_parquet.py pass
to derive it from child track first-step energies.
2026-06-25 16:01:13 +02:00
lars 64c6bd1cef Add photon edep export scripts and per-step presentation plots
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 13:36:54 +02:00
lars bdac36b203 Allow steps_to_parquet.py to accept multiple ROOT input files 2026-06-24 19:28:50 +02:00
lars eea9a24d9f Add export script for ETP group-update presentation plots
One-off script (like export_validation_plots.py / export_event_observables.py)
that writes a 3x3 marginals grid, post_dir/travel_dir norm histograms, and
vector-PDF copies of the KL-bars/photon-edep/event-level plots directly into
the thesis-presentations repo's images/ folder.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 18:18:26 +02:00
lars b4ce04e772 Add mean/median deposited energy and step length plots per event
Move ipykernel into the analysis extra instead of a separate
dependency group, since it's needed wherever analysis plotting runs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 12:46:17 +02:00
lars c802a59033 Add export script for Tier 4 event-level/pdg-share plots
One-off script mirroring export_validation_plots.py, used to export the
new event-level and pdg-contribution-share plots into the knowledge-base
attachments folder.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 12:42:49 +02:00
lars 2dba1edda6 Run validation incompletely 2026-06-24 10:53:38 +02:00
lars 139d95631f Add pdg energy/length contribution pie plots
pdg_contribution_table_pl sums real/generated total deposited energy and
total step_length per pdg species over the whole file (pure lazy polars
group_by, no post_pos reconstruction needed for these scalars). Adds
plot_pdg_energy_share/plot_pdg_length_share, each rendering two pies
(real vs generated) so the per-species breakdown can be compared directly,
plus a matching notebook section.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 16:55:51 +02:00
lars 453f9f9e20 Add total length traveled per event to event observables
sum(step_length) per event_id, alongside the existing total deposited
energy, since path length and energy deposit aren't interchangeable once
tracks scatter. Adds plot_total_length and a matching notebook cell.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 16:47:51 +02:00
lars 6d839a983f Rework validation notebook with markdown sections and Tier 4 plots
Adds section headers and explanatory comments throughout the existing
tiers, plus new cells running compute_event_observables_pl and the four
event-level shower plots. Notebook outputs reflect the user's own re-run.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 16:42:03 +02:00
lars f81263fa6e Add event-level shower observables to giant.analysis
Aggregates giant predict --coord local output per event_id into total
deposited energy, longitudinal/transverse shower profiles, and shower-max
depth, reconstructed into world-frame physical units (mm, MeV). Streams the
file in two polars passes rather than building a SampleCollection, since
per-event sums would be corrupted by row subsampling on these large files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 15:52:47 +02:00
lars 6fc68fe1aa Export plots for knowledge base 2026-06-22 14:41:45 +02:00
lars 936249a8a0 Rerun validation 2026-06-22 14:40:58 +02:00
lars ae1b565ca3 Add KL bar plots and sample_frac to load_predicted_local; ignore root parquet scratch files
Adds plot_kl_bars/plot_kl_bars_pl (numpy/polars variants) for ranking which
target dimension or pdg/material stratum drives KL regressions, with the
same kl*n group capping as plot_marginals. Switches existing histogram
plots to step-type/log-scale. Adds sample_frac to load_predicted_local for
subsampling large predict parquets.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 11:52:41 +02:00
lars 9d7b1ca9bb Buffer predict rows across row-group boundaries before inference
Inference batches were capped at the source parquet's row-group size
(e.g. 122,880 rows) because the old loop only sliced within a single
chunk read from disk. --batch-size (including auto) had no effect once
it exceeded that, leaving most estimated GPU memory unused. Accumulate
rows across row groups and files into a buffer and slice exactly
batch-size pieces off it, so inference always uses the requested batch
size regardless of how the file happens to be chunked.
2026-06-22 09:19:56 +02:00
lars 903227d2df Skip rows with unknown PDG codes during predict
Checkpoints have a fixed PDG embedding vocab sized at train time, so a
code unseen during training has no embedding index. Drop those rows
and report a per-code skip count instead of raising a KeyError.
2026-06-22 09:06:05 +02:00
lars c057693d90 Add tqdm progress bar to predict 2026-06-22 08:53:04 +02:00
lars 74012fe049 Calibrate auto batch size separately for inference vs training
Inference has no backward graph or optimizer state, so it has a much
lower per-sample memory footprint than training. estimate_batch_size
now takes a training flag selecting between two calibration points;
predict uses the inference one (hidden_dim=1024, n_blocks=8,
batch_size=65536 measured at ~2037 MiB).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 08:40:38 +02:00
lars 92d38cbed4 Add --batch-size auto to predict, matching train
Estimates batch size from free GPU memory using the checkpoint's
hidden_dim/n_blocks, same as the train command.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 08:23:58 +02:00
lars 46068f356f Add hyperparameter scan 2026-06-22 07:27:02 +02:00
lars aef0a588ce Add --batch-size auto to estimate batch size from free GPU memory
Calibrated against a measured reference point (hidden_dim=512,
n_blocks=6, batch_size=131072 -> ~8 GiB VRAM), assuming activation
memory scales linearly with batch_size * hidden_dim * n_blocks.
CUDA-only for now since it relies on torch.cuda.mem_get_info.
2026-06-19 13:24:42 +02:00
lars 74d0883868 Remove scripts/train.py in favor of the giant train CLI
The Typer-based giant/cli.py train command now has full feature
parity (dropout, warmup-epochs, validate-steps, shorthand flags),
making the standalone argparse script redundant.
2026-06-19 13:17:15 +02:00
lars cf653f7664 Add linear warmup before cosine LR decay
Replaces CosineAnnealingLR with a LambdaLR that linearly ramps the LR
from lr/warmup_epochs to lr over the first warmup_epochs steps, then
applies cosine decay for the remainder. Default warmup_epochs=5;
overridable via --warmup-epochs CLI flag.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 10:43:31 +02:00
lars 7f62141445 Make sampler step count configurable for validation
validate_marginals and collect_samples could already vary flow ODE
steps for inference (giant predict --steps), but training-time
marginal validation and DDIM evaluation were stuck at hardcoded
defaults. Add a validate_steps config/CLI option and forward steps to
sample_ddim consistently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 17:52:14 +02:00
lars e505e2d141 Fix miniCaloSim link in README
The relative path assumed a sibling checkout; point to the actual
GitLab repo instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 17:43:24 +02:00
lars 0cdb5db947 Update README to match current architecture and tooling
Output space is 9D (post_dir + travel_dir), not 6D; documents the
giant CLI, analysis/validate modules, ROOT-to-parquet conversion
script, cpu/cuda install extras, and the ruff/ty dev tooling.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 17:43:04 +02:00
lars 8cebc4809d Apply ruff format and document lint/type tooling in CLAUDE.md
First repo-wide ruff format pass, plus a note in CLAUDE.md to run
ruff and ty periodically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 17:40:27 +02:00
lars 53fd2e4405 Add ruff and ty as dev dependencies, fix lint/type findings
ruff removed unused imports across analysis.py and several test files.
ty caught a wrong dict[int, int] annotation on StreamingStepsDataset's
mat_map (materials are strings) and a real bug in steps_to_parquet.py
where --compression none passed None to polars' write_parquet, which
only accepts the literal "uncompressed". Also narrows a few
Optional-typed attributes (ddpm_schedule, Normalizer.mean/std) with
asserts and aligns __getitem__'s parameter name with torch's Dataset
base class.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 17:38:40 +02:00
lars c1a8a900d3 Split torch into cpu/cuda extras and pin dependency version bounds
Pins torch to 2.3.x via mutually-exclusive cpu/cuda uv extras (newer
torch requires newer NVIDIA drivers), and adds upper bounds to the
other dependencies based on current PyPI releases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 17:30:35 +02:00
lars 80b198c1a5 Add lazy polars I/O and duplicate KL/constraint checks for giant.analysis
load_predicted_local now reads predict parquet via a lazy polars scan with
column projection pushed into the reader, instead of materializing the
whole file as a pandas DataFrame. Also adds marginal_table_pl and
constraint_report_pl, polars-native duplicates that read straight from a
predict parquet path/LazyFrame and stay lazy per (group, dim) pair, so
peak memory is one column slice rather than the whole SampleCollection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 17:06:58 +02:00
lars a867fc4aae Add giant.analysis module for notebook-based model quality diagnostics
Provides stratified marginal comparisons, joint-structure checks (correlation
matrices, physically-coupled pairwise plots, direction alignment), and
physical-constraint validation (unit-norm directions, non-negative raw
targets) for a trained model's generated samples, building on the aggregate
marginal/KL check already in giant.validate.

Supports two entry points: live sampling against a checkpoint + val data
(load_model_bundle/collect_samples), or loading a precomputed
`giant predict --coord local` parquet directly (load_predicted_local) without
needing the checkpoint at all. Predict output is now tagged with parquet
schema metadata so the loader can verify a file's format and reject
coord=global or untagged files with a clear error instead of guessing from
column names.

Also extends the config git-hash mismatch warning (added for --config
loading) to checkpoint loading: both `giant predict` and
analysis.load_model_bundle now look for a config.toml next to the checkpoint
and warn (without failing) if it was generated from a different git commit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 16:36:19 +02:00
lars da84801625 Add configurable dropout to ResBlocks
Wire a dropout hyperparameter (default 0.1) through the config, model,
training pipeline, and CLI. Persisted in saved model_config so checkpoints
reconstruct the architecture correctly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 15:59:20 +02:00
lars 5d161a52b2 Add graceful shutdown on SIGINT/SIGTERM
A Ctrl-C or job-scheduler kill signal during training used to crash with a
raw KeyboardInterrupt mid-batch, abandoning whatever checkpoint state was
in flight. Now a signal sets a flag instead: the loop discards an
in-progress epoch's partial work (since lr_sched hasn't stepped and there's
no validation pass yet for it), but lets an epoch that's already past its
training loop finish normally — checkpoint, metrics row, and all — before
stopping. A second signal force-kills immediately for an unresponsive run.

Verified against a backgrounded run: SIGINT mid-training stopped cleanly
with a consistent last.pt/metrics.csv, and --resume picked up exactly at
the next epoch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 14:00:01 +02:00