ac01966a1f
CI / Sync project version with tag (hand-pushed tags only) (pull_request) Has been skipped
CI / Publish package to Gitea package registry (pull_request) Has been skipped
CI / Lint (ruff check) (pull_request) Successful in 29s
CI / Format (ruff format) (pull_request) Successful in 48s
CI / Type check (ty) (pull_request) Successful in 49s
CI / Tests (pull_request) Failing after 3m5s
CI / Release (bump, changelog, badges, tag) on merge to master (pull_request) Has been skipped
Adds a `prediction` plot family to `giant analyze`, alongside the existing rollout-vs-reference comparison, and extends `giant predict` to make it possible: - `giant predict --coord global` gains schema v3 (`--truth/--no-truth`, default on): writes true_* physical columns and true secondary lists alongside the predictions, so the output is fully paired. - New `giant/analysis/prediction.py` builds one canonical true/pred frame (`paired_frame`) from either predict coord mode. - `catalog.py` gains 35 `pred_*` specs: marginals, 2D truth-vs-pred scatter (new `heatmap2d` kind), residuals/relative-residuals/calibration profiles, KS/bias/RMSE scorecards, n_sec + secondary-species confusion matrices, direction-alignment and constraint-violation checks, and a correlation delta. Two new Reduced kinds (`paired_hist`, `heatmap2d`) get renderers. Every spec degrades to kind="unavailable" with no --prediction given. - `condor.py`/`cli.py`: `--prediction`/`--prediction-label` on `analyze prep`/`submit`, threaded through RunMeta and every compute job. Full test suite (1162 tests), ruff, and ty all pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PpxE9nij3ujg9XcuzvQ26q
87 lines
3.4 KiB
Python
87 lines
3.4 KiB
Python
X_DIM = 9
|
|
|
|
# Original Phase-2 continuous conditioning: pre_pos(3), log(pre_E)(1),
|
|
# pre_dir(3), layer_id(1). This is the slice ConditionEncoder's "embedding"
|
|
# mode reads from cond_cont (see giant/model/network.py); n_sec and
|
|
# log(e_sec) are not part of it — they are *outputs* predicted by Stage 1,
|
|
# not conditioning inputs.
|
|
COND_DIM_BASE = 8
|
|
|
|
# Particle physical-property conditioning: log(mass)(1), charge(1). See
|
|
# giant/particles.py.
|
|
PARTICLE_PHYS_DIM = 2
|
|
|
|
# Material physical-property conditioning: Z_eff(1), A_eff(1),
|
|
# log(density)(1), log(X0)(1), log(lambda_int)(1). See giant/materials.py.
|
|
MATERIAL_PHYS_DIM = 5
|
|
|
|
# Conditioning continuous-feature width. cond_cont is unconditionally this
|
|
# wide regardless of model_config["conditioning"]: "physical" mode computes
|
|
# the trailing PARTICLE_PHYS_DIM + MATERIAL_PHYS_DIM columns for real,
|
|
# "embedding" mode zero-fills them (and never reads them) — see
|
|
# giant.data.transforms.build_features/build_cond_features. Bumped 8->15 for
|
|
# physical-property conditioning, the same kind of breaking bump as Phase 1
|
|
# (10) -> Phase 2 (8).
|
|
COND_DIM = COND_DIM_BASE + PARTICLE_PHYS_DIM + MATERIAL_PHYS_DIM # 15
|
|
|
|
# Maximum number of secondary slots. From data: max(n_sec)=14 in PbWO4 dataset;
|
|
# K_MAX=15 covers it with one spare slot.
|
|
K_MAX = 15
|
|
|
|
# Per-slot continuous width: stick-breaking logit(1) + local dir(3).
|
|
CONT_SLOT_DIM = 4
|
|
|
|
# Per-slot secondary target dimension: CONT_SLOT_DIM (stick-breaking logit +
|
|
# local dir) + PARTICLE_PHYS_DIM (log(mass), charge — the secondary's
|
|
# predicted physical identity, regressed directly against real physics
|
|
# targets rather than a learned/snapped embedding).
|
|
SEC_SLOT_DIM = CONT_SLOT_DIM + PARTICLE_PHYS_DIM # 6
|
|
|
|
# ConditionEncoder's physical-property sub-MLP output width (see
|
|
# giant/model/network.py) and "embedding" mode's pdg_emb/mat_emb width.
|
|
# Independent of SEC_SLOT_DIM — unlike Phase 2, Stage 2's per-slot physical
|
|
# output width is fixed by PARTICLE_PHYS_DIM, not by this.
|
|
EMB_DIM = 16
|
|
|
|
# Flattened Stage-2 target dimension
|
|
SEC_DIM = K_MAX * SEC_SLOT_DIM # 15 * 6 = 90
|
|
|
|
# Stage-1 9D target names (unchanged from energy-conservation PoC)
|
|
LOCAL_TARGET_NAMES = [
|
|
"log_step_length",
|
|
"edep_logit",
|
|
"sec_logit",
|
|
"post_dx",
|
|
"post_dy",
|
|
"post_dz",
|
|
"travel_dx",
|
|
"travel_dy",
|
|
"travel_dz",
|
|
]
|
|
|
|
# Parquet schema metadata written by `giant predict` and checked by
|
|
# giant.analysis loaders, so a file's format can be verified without
|
|
# guessing from its column names.
|
|
PREDICT_COORD_METADATA_KEY = "giant.predict.coord"
|
|
PREDICT_SCHEMA_VERSION_KEY = "giant.predict.schema_version"
|
|
PREDICT_SCHEMA_VERSION = "3"
|
|
|
|
# Whether a --coord global predict parquet also carries true_* / true_sec_*
|
|
# columns (v3+; "1"/"0"). Lets analysis code tell a paired prediction file
|
|
# apart from a --no-truth one without sniffing for column presence.
|
|
PREDICT_TRUTH_METADATA_KEY = "giant.predict.has_truth"
|
|
|
|
# Coord-metadata value tagging a `giant rollout` steps parquet (world frame,
|
|
# autoregressive shower output). Distinct from predict's "global"/"local".
|
|
ROLLOUT_COORD_VALUE = "rollout"
|
|
|
|
# Per-track termination reasons recorded by the rollout driver. "escaped"
|
|
# energy is treated as leakage (not deposited); every other stop deposits the
|
|
# track's remaining energy locally so total energy is conserved.
|
|
TERM_ESCAPED = "escaped"
|
|
TERM_ENERGY_CUTOFF = "energy_cutoff"
|
|
TERM_MAX_STEPS = "max_steps"
|
|
TERM_NATURAL_END = "natural_end"
|
|
TERM_UNKNOWN_PDG = "unknown_pdg"
|
|
TERM_MAX_TRACKS = "max_tracks"
|