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/gc-fetch-vizier.py
Normal file
91
session-scripts/gc-fetch-vizier.py
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
"""Fetch a published globular cluster catalogue for NGC 5128 (Centaurus A) from VizieR.
|
||||
|
||||
Primary catalogue: J/MNRAS/469/3444 table "gc" -- Taylor, Puzia, Ferrarez et al. 2017,
|
||||
MNRAS 469, 3444, "Survey of Centaurus A's Baryonic Structures (SCABS) II":
|
||||
3210 globular cluster candidates with ugriz photometry over ~1.55 deg^2 centred on Cen A.
|
||||
|
||||
Fallback: J/AJ/143/84 (Harris+ 2012, 833 new GC candidates).
|
||||
|
||||
Writes _cena_gc_ref.npz with keys:
|
||||
ra, dec : degrees, J2000 (ICRS)
|
||||
vmag : Johnson V estimated from SDSS g,r via Lupton (2005):
|
||||
V = g - 0.5784*(g-r) - 0.0038
|
||||
gmag,rmag: SDSS-like g and r from the source catalogue (NaN where missing)
|
||||
prob : Taylor+ 2017 GC membership probability (0-1), higher = more likely a GC
|
||||
"""
|
||||
import numpy as np
|
||||
from astroquery.vizier import Vizier
|
||||
from astropy.coordinates import SkyCoord
|
||||
import astropy.units as u
|
||||
|
||||
import layout
|
||||
|
||||
OUT = layout.path("_cena_gc_ref.npz")
|
||||
RA0, DEC0 = 201.365, -43.019
|
||||
# field half-widths in arcmin for a 43' x 29' frame
|
||||
HW_RA, HW_DEC = 21.5, 14.5
|
||||
|
||||
|
||||
def col(t, name):
|
||||
if name not in t.colnames:
|
||||
return None
|
||||
return np.ma.filled(np.ma.asarray(t[name]).astype(float), np.nan)
|
||||
|
||||
|
||||
def report(ra, dec, label):
|
||||
dra = (ra - RA0) * np.cos(np.radians(dec)) * 60.0
|
||||
dde = (dec - DEC0) * 60.0
|
||||
sep = np.hypot(dra, dde)
|
||||
infield = (np.abs(dra) <= HW_RA) & (np.abs(dde) <= HW_DEC)
|
||||
print(f" {label}: {len(ra)} rows")
|
||||
print(f" RA {ra.min():.4f} .. {ra.max():.4f} "
|
||||
f"(span {(ra.max()-ra.min())*np.cos(np.radians(DEC0))*60:.1f}')")
|
||||
print(f" Dec {dec.min():.4f} .. {dec.max():.4f} "
|
||||
f"(span {(dec.max()-dec.min())*60:.1f}')")
|
||||
print(f" sep from centre: median {np.median(sep):.1f}' max {sep.max():.1f}'")
|
||||
print(f" inside 43'x29' field: {infield.sum()}")
|
||||
return infield
|
||||
|
||||
|
||||
def main():
|
||||
v = Vizier(row_limit=-1)
|
||||
cid, tname = "J/MNRAS/469/3444", "J/MNRAS/469/3444/gc"
|
||||
print(f"Fetching {tname} (Taylor+ 2017, SCABS II)")
|
||||
try:
|
||||
tabs = v.get_catalogs(cid)
|
||||
t = [x for x in tabs if x.meta.get("name") == tname][0]
|
||||
except Exception as e:
|
||||
print(f" FAILED: {e}")
|
||||
return 1
|
||||
|
||||
# RAJ2000/DEJ2000 are sexagesimal strings in this table
|
||||
sc = SkyCoord(np.asarray(t["RAJ2000"], str), np.asarray(t["DEJ2000"], str),
|
||||
unit=(u.hourangle, u.deg))
|
||||
ra = sc.ra.deg
|
||||
dec = sc.dec.deg
|
||||
g = col(t, "gmag")
|
||||
r = col(t, "rmag")
|
||||
prob = col(t, "Prob")
|
||||
|
||||
good = np.isfinite(ra) & np.isfinite(dec)
|
||||
ra, dec, g, r, prob = ra[good], dec[good], g[good], r[good], prob[good]
|
||||
|
||||
# -1.0 is the catalogue's "no photometry" sentinel -> NaN
|
||||
g = np.where(g <= 0, np.nan, g)
|
||||
r = np.where(r <= 0, np.nan, r)
|
||||
|
||||
# Lupton (2005) SDSS -> Johnson V
|
||||
vmag = g - 0.5784 * (g - r) - 0.0038
|
||||
|
||||
report(ra, dec, tname)
|
||||
print(f" vmag finite: {np.isfinite(vmag).sum()} "
|
||||
f"range {np.nanmin(vmag):.2f} .. {np.nanmax(vmag):.2f}")
|
||||
print(f" prob >=0.5: {(prob >= 0.5).sum()} >=0.9: {(prob >= 0.9).sum()}")
|
||||
|
||||
np.savez(OUT, ra=ra, dec=dec, vmag=vmag, gmag=g, rmag=r, prob=prob)
|
||||
print(f"WROTE {OUT}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue