astrophotography/session-scripts/gc-fetch-vizier.py
laurence 5286a2e81b 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.
2026-07-21 15:29:49 +01:00

91 lines
3.1 KiB
Python

"""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())