Move the processing code under pipeline/

Preparing to merge this repository into a combined astrophotography
repo. session-scripts/ becomes pipeline/ because the scripts import
layout.py from their own directory and must stay together, and because
'pipeline' says what it is rather than how it came about. observing/
stays at the top level: observing plans are not processing code.
This commit is contained in:
laurence 2026-07-21 17:13:54 +01:00
parent 653ca103cd
commit c6299f41ab
53 changed files with 0 additions and 0 deletions

View file

@ -1,146 +0,0 @@
"""Write the final flagged-object CSVs, with an identification and verdict
attached to every row.
Two files are produced.
mo-flagged-objects.csv is the short list: the six sources that survived every
cut of the transient search, plus the (zero) moving-object candidates, each
with the identification established from published catalogues and an explicit
assessment. This is the file to read.
mo-transient-candidates.csv (written by mo_transient.py) is the long list of
all 567 catalogue non-matches, kept for completeness. Almost all of them are
faint objects below the depth at which Gaia DR3 and SkyMapper DR2 are complete
against this galaxy, and are not individually assessed.
"""
import csv
import os
import numpy as np
import mo_common as C
# Identifications from cross-matching against published Centaurus A cluster
# catalogues (Woodley+2007 J/AJ/134/494 and others), SIMBAD, NED and a blanket
# VizieR cone search. Separations quoted are to the matched catalogue entry.
IDENT = {
"201.672625": dict(
name="WHH-31", otype="GlC (SIMBAD)", sep=0.10,
refs="Woodley+2007; Hughes+2021 #86; SCABS GC prob=1.0",
cat_phot="V=19.50 B=20.44 R=18.94",
assessment="Known Centaurus A globular cluster. Not a transient."),
"201.500583": dict(
name="pff_gc-081", otype="GlC (SIMBAD)", sep=0.32,
refs="Woodley+2007; Hughes+2021 ID 248669; SCABS GC prob=1.0",
cat_phot="V=19.34 B=20.17 R=18.80",
assessment="Known Centaurus A globular cluster. Not a transient."),
"201.441625": dict(
name="WHH-24", otype="GlC (SIMBAD)", sep=0.19,
refs="Woodley+2007; SCABS GC prob=1.0",
cat_phot="V=19.63 B=20.43 R=19.12",
assessment="Known Centaurus A globular cluster. Not a transient."),
"201.407000": dict(
name="resolved object at the position of CAVS 210 / "
"Gaia DR3 6088701636326983168",
otype="resolved (1.34x PSF, elongation 1.40); not a point source",
sep=1.32,
refs="de Jong+2008 J/A+A/478/755 (CAVS 210); DENIS 1996-2001; "
"Swift/UVOT SSC (12 ObsIDs); XMM-OM ~2020; VHS DR4; KS4 DR1",
cat_phot="Gaia DR3 G=21.03 at 1.32\" (point source); "
"DENIS I=18.23 J=16.44; UVOT U=18.2-18.6",
assessment="NOT a transient and NOT a brightening; the 2.8 mag "
"difference from Gaia is a measurement artefact. The "
"source is resolved (r50 = 2.96 px vs PSF 2.21 px, "
"elongation 1.40), so an integrated aperture magnitude is "
"not comparable with Gaia's point-source G; Gaia has no "
"entry at all for the extended object and nothing within "
"25\" brighter than G=19.8. It is steady over the session "
"(rms 0.066 mag vs 0.039 for comparison stars) and is "
"present on 1990s DSS2 red plates at the same brightness "
"relative to its neighbours (implied change +0.26 mag). "
"Even the PSF-scaled 2 px core gives G=18.63. See "
"notes-transient-search.md section 4.3 and NGC5128-mo-cavs210.png."),
"201.303542": dict(
name="WHH-10", otype="GlC (SIMBAD)", sep=0.23,
refs="Woodley+2007; SCABS GC prob=1.0",
cat_phot="V=19.57 B=20.36 R=19.07",
assessment="Known Centaurus A globular cluster. Not a transient."),
"201.256708": dict(
name="pff_gc-029 / GC0103", otype="GlC (SIMBAD)", sep=0.23,
refs="Woodley+2007; Peng+2004; Spitler+2008; Hughes+2021; Dumont+2022",
cat_phot="V=19.37 B=19.75 R=19.06 Ks=14.69",
assessment="Known Centaurus A globular cluster, well studied. "
"Not a transient."),
}
def ident_for(ra):
for k, v in IDENT.items():
if abs(float(k) - ra) < 1e-4:
return v
return dict(name="", otype="", sep=np.nan, refs="", cat_phot="",
assessment="UNIDENTIFIED - needs follow-up")
FIELDS = ["search", "ra_hms", "dec_dms", "ra_deg", "dec_deg", "x_ref",
"y_ref", "g_mag_this_image", "snr", "r50_over_psf", "n_subs",
"snr_R", "snr_G", "snr_B", "dist_from_cenA_arcmin",
"identification", "object_type", "match_sep_arcsec",
"catalogue_photometry", "references", "assessment"]
def main():
rows = []
vet = list(np.load(os.path.join(C.OUT, "_mo_vetted.npy"),
allow_pickle=True))
vet.sort(key=lambda r: r["dist_cenA_arcmin"])
for r in vet:
d = ident_for(r["ra_deg"])
rows.append({
"search": "transient",
"ra_hms": r["ra_hms"], "dec_dms": r["dec_dms"],
"ra_deg": r["ra_deg"], "dec_deg": r["dec_deg"],
"x_ref": r["x"], "y_ref": r["y"],
"g_mag_this_image": r["g_mag"], "snr": r["snr"],
"r50_over_psf": r["r50_over_psf"], "n_subs": r["n_subs"],
"snr_R": r["snr_R"], "snr_G": r["snr_G"], "snr_B": r["snr_B"],
"dist_from_cenA_arcmin": r["dist_cenA_arcmin"],
"identification": d["name"], "object_type": d["otype"],
"match_sep_arcsec": d["sep"],
"catalogue_photometry": d["cat_phot"],
"references": d["refs"], "assessment": d["assessment"]})
# Moving-object search: zero candidates, but the file should say so
# explicitly rather than being empty.
mo = os.path.join(C.OUT, "mo-moving-candidates.csv")
nmov = 0
if os.path.exists(mo):
with open(mo) as fh:
nmov = max(0, sum(1 for _ in fh) - 1)
if nmov == 0:
rows.append({f: "" for f in FIELDS} | {
"search": "moving-object",
"identification": "(no candidates)",
"assessment": "Blind tracklet search over the 12 luminance subs "
"returned 0 candidates. Sensitivity measured by "
"synthetic injection: 50% recovery at G=18.9 for "
"8-40 arcsec/hr; no sensitivity below ~4 arcsec/hr. "
"The only catalogued minor planet within 30' of the "
"pointing, (427494) 2002 BK26 at V=21.7, fell 2.4' "
"outside the frame."})
out = os.path.join(C.OUT, "mo-flagged-objects.csv")
with open(out, "w", newline="", encoding="utf-8") as fh:
w = csv.DictWriter(fh, fieldnames=FIELDS)
w.writeheader()
w.writerows(rows)
print(f"wrote {out} ({len(rows)} rows)")
for r in rows:
print(f" {r['search']:14s} {r['identification'][:44]:44s} "
f"{str(r['g_mag_this_image']):>6s} "
f"{r['assessment'][:60]}")
if __name__ == "__main__":
main()