The scripts that processed the NGC 5128 session of 2026-07-21 previously lived inside the data directory and addressed it with absolute paths. Code and data are now separated: the code lives here, and a session is located at runtime through the ASTRO_SESSION environment variable. layout.py is what makes that work. It maps a FILENAME to the subdirectory that file belongs in, using the same rules the session directories are organised with, so a script can go on asking for 'master-Red.fit' or '_stars.npz' without any call site knowing the directory structure. Anything unrecognised resolves to the session root, which is visible and correctable rather than silently wrong. restructure.py reorganises a flat session directory into that layout. It is idempotent and dry-run by default. The 50 session scripts are kept as they were run rather than tidied into a library. They were written in sequence as the work went along, several of them by parallel agents, and they show it - but they are the honest provenance of a published set of results, and the productionised pipeline should be able to reproduce those results exactly. Verified before committing: all 51 files compile without warnings, and verify_core.py, closeup.py and triptych.py were run end to end against the reorganised session, correctly finding inputs across calibrated/, stacks/masters/ and final/ and writing outputs back to the right places.
33 lines
1.1 KiB
Python
33 lines
1.1 KiB
Python
"""Uncompress every calibrated-*.zip in the session folder, in place.
|
|
|
|
iTelescope ships each calibrated frame as a one-entry zip (.fit.zip and
|
|
.tif.zip). Extraction is skipped when the target already exists and is
|
|
non-empty, so this is safe to re-run.
|
|
"""
|
|
import glob
|
|
import os
|
|
import zipfile
|
|
|
|
import layout
|
|
|
|
SRC = layout.SESSION
|
|
|
|
zips = sorted(glob.glob(layout.path("calibrated-*.zip")))
|
|
print(f"{len(zips)} calibrated archives")
|
|
done = skipped = 0
|
|
for z in zips:
|
|
with zipfile.ZipFile(z) as zf:
|
|
for info in zf.infolist():
|
|
target = layout.path(os.path.basename(info.filename))
|
|
if os.path.exists(target) and os.path.getsize(target) == info.file_size:
|
|
skipped += 1
|
|
continue
|
|
with zf.open(info) as fsrc, open(target, "wb") as fdst:
|
|
while chunk := fsrc.read(1 << 20):
|
|
fdst.write(chunk)
|
|
done += 1
|
|
print(f"extracted {done}, already present {skipped}")
|
|
|
|
for ext in (".fit", ".tif"):
|
|
n = len(glob.glob(layout.path(f"calibrated-*{ext}")))
|
|
print(f"{ext}: {n} files")
|