Skip to content

Snakemake orchestration for the real-data pipeline#852

Draft
cailmdaley wants to merge 8 commits into
developfrom
feat/snakemake-orchestration
Draft

Snakemake orchestration for the real-data pipeline#852
cailmdaley wants to merge 8 commits into
developfrom
feat/snakemake-orchestration

Conversation

@cailmdaley

Copy link
Copy Markdown
Contributor

Implements #848 — the living PRD. The design (rule DAG, run index, failure policy, execution profile) lives there and is kept current as this PR evolves; this description stays short on purpose.

Current state: prepare phase green on a 4-tile P3 subset on nibi; compute-phase validation (P0: exposure chain → full tile chain through final_cat) in progress on a one-node allocation.

— Claude (Fable) on behalf of Cail

🤖 Generated with Claude Code

cailmdaley and others added 8 commits July 16, 2026 15:46
)

Implements the round-2 design in #848: static two-phase execution driven by a
parse-time SQLite run index (never a rule input, so appending tiles never
invalidates completed work); rules wrap the existing per-unit shapepipe_run
config chains at tile/exposure granularity with deterministic RUN_DATETIME=False
directory() outputs; in-job completeness count-floor (the ported bash
complete_check table, workflow/scripts/completeness.py); one-allocation
execution profile for nibi with apptainer software-deployment (the workflow
never calls apptainer itself); out-of-DAG run_report verb + onsuccess/onerror
hooks; workflow/bin/sp as the committed launcher.

First pass touches no module code. Validated by dry-run against a 4-tile P3
subset (219-job compute DAG); prepare phase runs green on nibi.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s.cmd

Snakemake formats params once, so a {threads} placeholder inside params.cmd
survives literally and SMP_BATCH_SIZE never resolves (fork width silently 1,
serial modules — the p3-first10 failure mode). Move '--threads {threads}' into
each rule's shell: string; tile_exp_forest takes none (build_forest.py is
single-threaded symlinking and has no such flag). Completeness table doc
touch-ups ride along.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NA8M1oLZLbWJxwoyTNrTAi
…star-cat store naming

Three P0-blocking fixes found by running against real data:
- exposures(name): the fabricated per-unit exp_numbers list must carry the
  original exposure name verbatim (2605805p — get_images matches
  <name>.fits.fz; the bare dedup id matches nothing). The index now stores
  both; exp_get_images passes --exp-name from the parse-time dict.
- tile_star_cat: the pre-generated store names tiles in ShapePipe's
  image-number convention (dots->dashes); translate when linking.
- profile: PYTHONPATH pinned to this branch's src/ (identical to
  develop@97e16d50 — orchestration commits never touch src/); NOT
  shapepipe-prod (drifted to a PR branch mid-run, and the live p3-batch1
  job reads it) and not the sif default (frozen pre-#843).
Run scoped to the 210/211 overlap quad (19 unique exposures, 15 shared —
exercises structural dedup; the zero-overlap 196 quad is kept for the
append-invariant test).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NA8M1oLZLbWJxwoyTNrTAi
… config

- get_images looks up <name>.fits.fz: the store keeps the CFHT 'p' suffix the
  index's base-id key strips. exposures gains a name column; rules pass
  --exp-name; the wrapper writes the ORIGINAL name into the fabricated
  exp_numbers list — and writes it unconditionally (an exists-guard pinned a
  stale pre-fix file).
- Star cats are consumed as DIRECTORIES via the wrapper's $SP_RUN symlinks (the
  v2.0 mechanism; exp cats are per-CCD, 40/exposure) — dropped the per-unit
  star-cat file rules that linked nonexistent names nothing read.
- get_images completeness counts follow the nibi symlink configs (tile 2, exp 3;
  the v2.0 4/6 were the canfar vos flavor), verified against p3-batch1.
- P0 run config: 210/211 quad (19 unique exps, 13 shared across tiles —
  exercises structural dedup; the 196 quad had zero overlap), PYTHONPATH pinned
  to this branch's src (= develop@97e16d50; shapepipe-prod drifted mid-run).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…iterally

Same single-format trap as {threads} (187950c): Snakemake formats the shell
string once, so the escaped {{output}} in tile_exp_forest's params reached
build_forest as a literal './{output}' — all four forest jobs racing one
garbage dir (FileExistsError at 50% of the P0 run). Move --forest {output}
into the shell string. Swept the rules for further escaped placeholders: none.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ac/code/session_01NA8M1oLZLbWJxwoyTNrTAi
…pe is not cosmetic

exp_utils.get_exp_output_files hardwires the v2.0 sharded layout into its
$SP_EXP glob (<SP_EXP>/<prefix>/<base>/output/run_sp_*/...); a flat forest
fails every tile gather stage with 'No split_exp_runner output found'. The
exposure STORE stays flat (nothing globs it — the index drives every path);
only the module-facing forest view carries the 2-digit shard. Verified by
hand-running tile_merge_headers on 210.296 (1/1 OK).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ule's params

The default rerun-triggers' code trigger hashes only the rule's own shell
string — NOT external scripts it calls. Bitten live: the forest-shard fix
changed build_forest.py but no rule text, so stale flat forests survived a
rerun and tile_merge_headers kept failing. SCRIPT_HASH (md5 of sp_rule.py +
completeness.py + build_forest.py, computed at parse time) rides into params
via an accept-and-ignore --script-hash flag, so script edits propagate exactly
like code edits under the full default triggers. One-time cost: every rule's
params change once, re-running completed work — the same tradeoff as any code
change under full triggers, and the P0-scale rerun doubles as a live test of
rerun semantics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-full quota)

def-mjhudson /project sits at its 27/27 TiB ceiling: a .snakemake metadata
write died mid-run (killing an otherwise-green invocation after all 8 ngmix
chunks of the first tile passed), and by end of night even git and file edits
on /project failed. bin/sp now runs snakemake with --directory <run_dir>-state
on /scratch (state only — data paths are absolute), the Snakefile resolves its
configfile relative to itself so --directory can't break it, and the run index
lives with the run on /scratch until project space is reclaimed (finding 15's
/project placement stays the design intent; noted in config).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant