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