Processing and analysis code for remote-telescope imaging sessions
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.
This commit is contained in:
commit
5286a2e81b
53 changed files with 8820 additions and 0 deletions
91
session-scripts/rename.py
Normal file
91
session-scripts/rename.py
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
"""Prefix every image output with the object name, and fix every reference.
|
||||
|
||||
Renaming files is the easy half. The half that breaks a project silently is the
|
||||
references: METHODS.md and the three analysis notes cite these filenames, and
|
||||
the scripts that WRITE them would otherwise recreate the old names on the next
|
||||
run. So this rewrites the markdown and the scripts in the same pass.
|
||||
|
||||
Dry run by default; pass --apply to actually move anything.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
import layout
|
||||
|
||||
ROOT = layout.SESSION
|
||||
PREFIX = "NGC5128-"
|
||||
IMAGE_EXT = (".png", ".jpg", ".jpeg", ".tif", ".tiff")
|
||||
APPLY = "--apply" in sys.argv
|
||||
|
||||
|
||||
def image_files():
|
||||
"""Every image in the stacked tree that is not already prefixed."""
|
||||
out = []
|
||||
for folder in (ROOT, layout.path("original")):
|
||||
if not os.path.isdir(folder):
|
||||
continue
|
||||
for name in sorted(os.listdir(folder)):
|
||||
path = os.path.join(folder, name)
|
||||
if not os.path.isfile(path):
|
||||
continue
|
||||
if not name.lower().endswith(IMAGE_EXT):
|
||||
continue
|
||||
if name.startswith(PREFIX):
|
||||
continue
|
||||
out.append((folder, name, PREFIX + name))
|
||||
return out
|
||||
|
||||
|
||||
renames = image_files()
|
||||
print(f"{len(renames)} image files to rename\n")
|
||||
for folder, old, new in renames:
|
||||
where = os.path.relpath(folder, ROOT)
|
||||
print(f" {where}/{old} -> {new}")
|
||||
|
||||
# Build the substitution map. Longest names first so that a short name which is
|
||||
# a substring of a longer one cannot corrupt it.
|
||||
mapping = {old: new for _, old, new in renames}
|
||||
ordered = sorted(mapping, key=len, reverse=True)
|
||||
|
||||
targets = []
|
||||
for folder, _, _ in [(ROOT, None, None)]:
|
||||
for name in os.listdir(folder):
|
||||
if name.lower().endswith(".md"):
|
||||
targets.append(os.path.join(folder, name))
|
||||
scripts = layout.path("scripts")
|
||||
if os.path.isdir(scripts):
|
||||
for name in os.listdir(scripts):
|
||||
if name.lower().endswith(".py"):
|
||||
targets.append(os.path.join(scripts, name))
|
||||
|
||||
print(f"\nchecking {len(targets)} markdown and script files for references")
|
||||
edits = []
|
||||
for path in targets:
|
||||
try:
|
||||
text = open(path, encoding="utf-8").read()
|
||||
except UnicodeDecodeError:
|
||||
text = open(path, encoding="latin-1").read()
|
||||
updated = text
|
||||
hits = 0
|
||||
for old in ordered:
|
||||
# A reference is the bare filename; guard the left edge so an already
|
||||
# prefixed occurrence is not double-prefixed.
|
||||
pattern = re.compile(r"(?<![\w./-])" + re.escape(old))
|
||||
updated, n = pattern.subn(mapping[old], updated)
|
||||
hits += n
|
||||
if hits:
|
||||
edits.append((path, hits, updated))
|
||||
|
||||
for path, hits, _ in edits:
|
||||
print(f" {os.path.relpath(path, ROOT)}: {hits} references")
|
||||
|
||||
if not APPLY:
|
||||
print("\nDRY RUN - nothing changed. Re-run with --apply")
|
||||
sys.exit(0)
|
||||
|
||||
for folder, old, new in renames:
|
||||
os.replace(os.path.join(folder, old), os.path.join(folder, new))
|
||||
for path, _, updated in edits:
|
||||
open(path, "w", encoding="utf-8").write(updated)
|
||||
print(f"\nrenamed {len(renames)} files, updated {len(edits)} referencing files")
|
||||
Loading…
Add table
Add a link
Reference in a new issue