"""Check our 1-minute positions (cubic Hermite from hourly states) against Horizons' own 1-minute output, and rerun the candidate test on Horizons' 1-minute positions for those days. Usage: python -I check_interpolation.py <1-minute dir> [ ...] """ import datetime, json, pathlib, sys sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent)) import numpy as np import config_dates as cd INV = {v: k for k, v in cd.NAMES.items()} def main(): hdir, mdir, sel_path = sys.argv[1], pathlib.Path(sys.argv[2]), sys.argv[3] sel = {r["year"]: r for r in json.load(open(sel_path, encoding="utf-8"))} worst = 0.0 for day in sys.argv[4:]: d = datetime.date.fromisoformat(day); year = d.year; nxt = d + datetime.timedelta(days=1) bodies = [INV[n] for n in sel[year]["selected"]] k0 = (d - datetime.date(year, 1, 1)).days * 1440 # minute index of 00:00 true, interp = [], [] for b in ["199", "299", "399", "301", "499", "599"]: jd, st = cd.load_states(mdir / f"{b}_{day}_{nxt.isoformat()}_1m.txt") pos = cd.minute_positions(hdir, b, year)[k0 + 1:k0 + 1 + len(jd)] err = np.abs(pos - st[:, :3]).max(); worst = max(worst, err) print(f"{day} {cd.NAMES[b]:8s} max |interpolated - Horizons 1-min| = {err:.2e} AU") if b in bodies: true.append(st[:, :3]); interp.append(pos) for label, P in (("Horizons 1-min", true), ("interpolated", interp)): X = np.stack([np.zeros_like(P[0])] + P, axis=1) Xs, _ = cd.embed(X) jumps = np.abs(np.diff(Xs, axis=0)).max(axis=(1, 2)) hits = [(datetime.datetime.combine(d, datetime.time()) + datetime.timedelta(minutes=int(i) + 1)).strftime("%H:%M") for i in np.nonzero(jumps >= 0.35e-4)[0]] print(f" candidates on {day} from {label} positions ({'+'.join(sel[year]['selected'])}): {hits}") print(f"largest position difference over all days and bodies: {worst:.2e} AU") if __name__ == "__main__": main()