"""Flares on the Sun in the 24 hours before the S0 News episode of October 26, 2026, from NOAA's records. Usage: python3 -I sun_window.py [FOLDER] FOLDER holds the three files published next to this script (default: the script's own folder): goes18-xray-1min-2026-10-25-26.csv GOES-18 1-minute X-ray flux, 0.1-0.8 nm, October 25 10:00 to October 26 12:00 UTC goes18-flares-2026-10-19-26.csv GOES-18 flare list, the 7 days to October 26, 17:36 UTC swpc-xra-events-2026-10-25-26.csv the X-ray events (XRA) in the Space Weather Prediction Center's Edited Events They are extracts of NOAA files that roll over after 3 and 7 days (services.swpc.noaa.gov/json/goes/primary/ xrays-3-day.json and xray-flares-7-day.json, and ftp.swpc.noaa.gov/pub/indices/events/2026102{5,6}events.txt), as served on October 26, 2026, about 19:00 UTC. NOAA data are US government works, in the public domain. Prints, for the 24 hours before the upload (11:51:41 UTC) and three other windows: the flares by class, the peak flux and its time, the minutes at or above C1 (1e-6 W/m2) and the median flux. Standard library only. "Our analysis". Flare classes from a peak flux F (W/m2): A < 1e-7 <= B < 1e-6 <= C < 1e-5 <= M < 1e-4 <= X. """ import csv import datetime as dt import os import statistics import sys UTC = dt.timezone.utc UPLOAD = dt.datetime(2026, 10, 26, 11, 51, 41, tzinfo=UTC) # the video's uploadDate, 2026-10-26T04:51:41-07:00 def iso(s): return dt.datetime.strptime(s, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=UTC) def flare_class(f): for lim, c in ((1e-4, "X"), (1e-5, "M"), (1e-6, "C"), (1e-7, "B")): if f >= lim: return f"{c}{f / lim:.1f}" return f"A{f / 1e-8:.1f}" def main(): folder = sys.argv[1] if len(sys.argv) > 1 else os.path.dirname(os.path.abspath(__file__)) with open(os.path.join(folder, "goes18-xray-1min-2026-10-25-26.csv"), newline="", encoding="utf-8") as f: flux = [(iso(r["time_utc"]), float(r["flux_w_m2"])) for r in csv.DictReader(f)] with open(os.path.join(folder, "goes18-flares-2026-10-19-26.csv"), newline="", encoding="utf-8") as f: flares = [(iso(r["max_utc"]), r["max_class"]) for r in csv.DictReader(f)] events = [] with open(os.path.join(folder, "swpc-xra-events-2026-10-25-26.csv"), newline="", encoding="utf-8") as f: for r in csv.DictReader(f): day = dt.datetime.strptime(r["date"], "%Y-%m-%d").replace(tzinfo=UTC) t = day + dt.timedelta(hours=int(r["max_utc"][:2]), minutes=int(r["max_utc"][2:])) events.append((t, r["xray_class"], r["region"], r["event"])) windows = [ ("24 hours before the upload", UPLOAD - dt.timedelta(hours=24), UPLOAD), ("24 hours before 11:00 UTC on October 26", dt.datetime(2026, 10, 25, 11, tzinfo=UTC), dt.datetime(2026, 10, 26, 11, tzinfo=UTC)), ("24 hours before 10:00 UTC on October 26", dt.datetime(2026, 10, 25, 10, tzinfo=UTC), dt.datetime(2026, 10, 26, 10, tzinfo=UTC)), ("October 25, 00:00-24:00 UTC (no 1-minute flux)", dt.datetime(2026, 10, 25, tzinfo=UTC), dt.datetime(2026, 10, 26, tzinfo=UTC)), ] for name, a, b in windows: print(f"== {name}: {a:%b %d %H:%M:%S} to {b:%b %d %H:%M:%S} UTC") fw = [x for x in flares if a <= x[0] < b] by = {} for _, c in fw: by[c[0]] = by.get(c[0], 0) + 1 print(f" GOES-18 flare list: {len(fw)} flares, by class {dict(sorted(by.items()))}") print(" C class or above:", ", ".join(f"{c} at {t:%d %H:%M}" for t, c in fw if c[0] in "CMX") or "none") ev = [x for x in events if a <= x[0] < b] print(f" Edited Events, X-ray: {len(ev)} events, {sum(1 for x in ev if x[1][0] in 'CMX')} of C class or above") fx = [x for x in flux if a <= x[0] < b] if len(fx) >= 1380: # the 1-minute extract starts at 10:00 UTC on October 25 top = max(fx, key=lambda x: x[1]) print(f" 1-minute flux: peak {top[1]:.3e} W/m2 ({flare_class(top[1])}) at {top[0]:%d %H:%M} UTC; " f"{sum(1 for x in fx if x[1] >= 1e-6)} minutes at or above C1; median {statistics.median(v for _, v in fx):.2e} " f"({flare_class(statistics.median(v for _, v in fx))}); {len(fx)} minutes") big = [(t, c) for t, c in flares if c[0] in "MX"] print("M- or X-class flares anywhere in the 7-day list:", big or "none", f"(the list runs {flares[0][0]:%b %d %H:%M} to {flares[-1][0]:%b %d %H:%M} UTC)") t19 = dt.datetime(2026, 10, 26, 8, 38, tzinfo=UTC) gap = UPLOAD - t19 print(f"From the C1.9 at 08:38 UTC to the upload: {gap.seconds // 3600} h {gap.seconds % 3600 // 60} min") if __name__ == "__main__": main()