Move the processing code under pipeline/

Preparing to merge this repository into a combined astrophotography
repo. session-scripts/ becomes pipeline/ because the scripts import
layout.py from their own directory and must stay together, and because
'pipeline' says what it is rather than how it came about. observing/
stays at the top level: observing plans are not processing code.
This commit is contained in:
laurence 2026-07-21 17:13:54 +01:00
parent 653ca103cd
commit c6299f41ab
53 changed files with 0 additions and 0 deletions

View file

@ -1,124 +0,0 @@
"""Reorganise the session directory so a file's kind is obvious from where it sits.
Placement is decided by filename rules rather than by hand, so the same layout
can be reproduced for any other session. Dry run by default; --apply to move.
raw/ exactly what iTelescope delivered: the zips and jpegs
calibrated/ the uncompressed calibrated subs
stacks/masters/ per-filter registered, plate-solved masters
stacks/original/ the alignment-only baseline stacks
final/ the four deliverable renderings + the comparison
renderings/ other finished images (LRGB, HDR, annotated, starless)
science/figures/ analysis plots
science/catalogues/ measured tables (CSV)
science/data/ models, masks and derived quantities
science/notes/ the analysis write-ups
intermediates/ caches and scratch that a re-run can regenerate
"""
import os
import shutil
import sys
ROOT = r"C:\Users\lhorrocks-barlow\Downloads\NGC5128\20260721"
STACKED = os.path.join(ROOT, "stacked")
APPLY = "--apply" in sys.argv
DIRS = ["raw", "calibrated", "stacks/masters", "stacks/original", "final",
"renderings", "science/figures", "science/catalogues", "science/data",
"science/notes", "intermediates"]
def destination(name, from_stacked):
"""Where a file belongs, decided by its name alone."""
low = name.lower()
if not from_stacked:
if low.endswith(".zip"):
return "raw"
if low.startswith("jpeg-") and low.endswith(".jpg"):
return "raw"
if low.startswith("calibrated-") and low.endswith((".fit", ".tif")):
return "calibrated"
return None
if name.startswith("_"):
return "intermediates"
if name.startswith("master-") and low.endswith(".fit"):
return "stacks/masters"
if name.startswith("notes-") and low.endswith(".md"):
return "science/notes"
if low.endswith(".csv"):
return "science/catalogues"
if name.startswith("sb-") and low.endswith((".fits", ".npy", ".txt")):
return "science/data"
if low.endswith(".png") and any(f"-{p}-" in name for p in ("gc", "sb", "mo")):
return "science/figures"
if name.startswith(("NGC5128-LRGB", "NGC5128-img-")):
return "renderings"
if name == "METHODS.md":
return "."
return None
def plan():
moves = []
for name in sorted(os.listdir(ROOT)):
path = os.path.join(ROOT, name)
if os.path.isfile(path):
d = destination(name, from_stacked=False)
if d:
moves.append((path, os.path.join(ROOT, d, name)))
for name in sorted(os.listdir(STACKED)):
path = os.path.join(STACKED, name)
if name in ("final", "original", "scripts"):
continue
if os.path.isdir(path):
if name.startswith("_"):
moves.append((path, os.path.join(ROOT, "intermediates", name)))
continue
d = destination(name, from_stacked=True)
if d:
target = ROOT if d == "." else os.path.join(ROOT, d)
moves.append((path, os.path.join(target, name)))
moves.append((os.path.join(STACKED, "final"), os.path.join(ROOT, "final")))
moves.append((os.path.join(STACKED, "original"),
os.path.join(ROOT, "stacks", "original")))
return moves
if __name__ == "__main__":
moves = plan()
counts = {}
for src, dst in moves:
rel = os.path.relpath(os.path.dirname(dst), ROOT)
counts[rel] = counts.get(rel, 0) + 1
print(f"{len(moves)} moves\n")
for d in sorted(counts):
print(f" {d + '/':24s} {counts[d]:3d}")
unplaced = []
for name in sorted(os.listdir(ROOT)):
if os.path.isfile(os.path.join(ROOT, name)) and \
not destination(name, False):
unplaced.append(name)
for name in sorted(os.listdir(STACKED)):
p = os.path.join(STACKED, name)
if os.path.isfile(p) and not destination(name, True):
unplaced.append("stacked/" + name)
if unplaced:
print(f"\nNOT PLACED by any rule ({len(unplaced)}):")
for n in unplaced:
print(f" {n}")
if not APPLY:
print("\nDRY RUN - nothing moved. Re-run with --apply")
sys.exit(0)
for d in DIRS:
os.makedirs(os.path.join(ROOT, d), exist_ok=True)
for src, dst in moves:
os.makedirs(os.path.dirname(dst), exist_ok=True)
if os.path.exists(dst):
print(f" SKIP (exists): {dst}")
continue
shutil.move(src, dst)
print(f"moved {len(moves)} items")