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
70
session-scripts/analyse.py
Normal file
70
session-scripts/analyse.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
"""Pass 1: measure every calibrated frame and cache its star list.
|
||||
|
||||
Frames are 4788x3194 float32 (61 MB each) and the machine has little free RAM,
|
||||
so each frame is opened, measured and released one at a time. The star lists are
|
||||
cached to an npz because both the registration pass and the plate solve need
|
||||
them, and re-detecting costs more than re-reading a small array.
|
||||
|
||||
Recorded per frame: sky background and its rms, the number of detections, and a
|
||||
median FWHM derived from sep's half-flux radius. The FWHM is the seeing metric
|
||||
used later to pick the registration reference and to weight the stack.
|
||||
"""
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
|
||||
import numpy as np
|
||||
import sep
|
||||
from astropy.io import fits
|
||||
|
||||
import layout
|
||||
|
||||
SRC = layout.SESSION
|
||||
CACHE = layout.path("_stars.npz")
|
||||
os.makedirs(os.path.dirname(CACHE), exist_ok=True)
|
||||
|
||||
NAME_RE = re.compile(r"-(Luminance|Red|Green|Blue)-BIN2-W-300-(\d+)\.fit$")
|
||||
|
||||
|
||||
def frame_list():
|
||||
out = []
|
||||
for path in sorted(glob.glob(layout.path("calibrated-*.fit"))):
|
||||
m = NAME_RE.search(path)
|
||||
if m:
|
||||
out.append((path, m.group(1), int(m.group(2))))
|
||||
return out
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
frames = frame_list()
|
||||
print(f"{len(frames)} calibrated frames")
|
||||
store, meta = {}, []
|
||||
for path, filt, idx in frames:
|
||||
with fits.open(path, memmap=False) as hd:
|
||||
data = hd[0].data.astype(np.float32)
|
||||
bkg = sep.Background(data, bw=64, bh=64, fw=3, fh=3)
|
||||
back_med = float(np.median(bkg.back()))
|
||||
rms = float(bkg.globalrms)
|
||||
sub = data - bkg.back()
|
||||
objs = sep.extract(sub, 5.0, err=rms, minarea=9, deblend_cont=0.005)
|
||||
objs = objs[(objs["flag"] == 0) & (objs["npix"] > 12) &
|
||||
(objs["npix"] < 2000)]
|
||||
objs = objs[np.argsort(objs["flux"])[::-1][:400]]
|
||||
rad, _ = sep.flux_radius(sub, objs["x"], objs["y"], 6.0 * objs["a"],
|
||||
0.5, normflux=objs["flux"])
|
||||
fwhm = float(np.median(rad) * 2.0)
|
||||
key = f"{filt}_{idx:03d}"
|
||||
store[key + "_xy"] = np.column_stack([objs["x"], objs["y"]])
|
||||
store[key + "_flux"] = objs["flux"]
|
||||
meta.append((key, os.path.basename(path), filt, idx, len(objs), fwhm,
|
||||
back_med, rms))
|
||||
print(f"{key:16s} stars={len(objs):4d} fwhm={fwhm:5.2f}px "
|
||||
f"bg={back_med:8.1f} rms={rms:6.1f}")
|
||||
del data, sub, bkg, objs
|
||||
|
||||
np.savez_compressed(
|
||||
CACHE,
|
||||
meta=np.array(meta, dtype=object),
|
||||
**store,
|
||||
)
|
||||
print("cached ->", CACHE)
|
||||
Loading…
Add table
Add a link
Reference in a new issue