Skip to content

Instantly share code, notes, and snippets.

@MaxGhenis
Last active May 13, 2026 20:14
Show Gist options
  • Select an option

  • Save MaxGhenis/ddf033f52eb51e6082bade87564f7b83 to your computer and use it in GitHub Desktop.

Select an option

Save MaxGhenis/ddf033f52eb51e6082bade87564f7b83 to your computer and use it in GitHub Desktop.
PolicyEngine Social Security microdata regression investigation

Social Security microdata regression investigation

Reproducibility appendix for the PolicyEngine postmortem on social_security and social_security_retirement being dropped or ignored in microsimulation.

Files:

  • social_security_microdata_regression_investigation.ipynb: executed notebook with source-control, GitHub Actions, and PyPI evidence.
  • reproduce_social_security_microdata_regression.py: plain Python script with the same checks.

The investigation is metadata-only: it does not download large H5 data files. It expects local clones of PolicyEngine/policyengine-us-data and PolicyEngine/policyengine-us; set US_DATA_REPO and US_REPO if needed.

"""Reproduce the Social Security microdata regression timeline.
Requirements:
- local clones of PolicyEngine/policyengine-us-data and PolicyEngine/policyengine-us
- git, gh, jq
- network access for PyPI metadata checks
Set US_DATA_REPO and US_REPO if your clones are in different locations.
"""
from __future__ import annotations
import json
import os
import re
import subprocess
import tarfile
import tempfile
import urllib.request
from datetime import datetime
from pathlib import Path
US_DATA = Path(os.environ.get("US_DATA_REPO", "/Users/maxghenis/PolicyEngine/policyengine-us-data"))
US = Path(os.environ.get("US_REPO", "/Users/maxghenis/PolicyEngine/policyengine-us"))
def run(cmd: str, cwd: Path | None = None) -> str:
result = subprocess.run(
cmd,
cwd=str(cwd) if cwd else None,
shell=True,
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
check=True,
)
return result.stdout.strip()
def git(repo: Path, args: str) -> str:
return run(f"git {args}", cwd=repo)
def policyengine_us_version_at(data_sha: str) -> str:
lock = git(US_DATA, f"show {data_sha}:uv.lock")
lines = lock.splitlines()
for idx, line in enumerate(lines):
if line.strip() == 'name = "policyengine-us"':
for following in lines[idx + 1 : idx + 8]:
m = re.search(r'version = "([^"]+)"', following)
if m:
return m.group(1)
return "not found"
def pyproject_version_at(repo: Path, sha: str) -> str:
pyproject = git(repo, f"show {sha}:pyproject.toml")
for line in pyproject.splitlines():
if line.startswith("version = "):
return line.split('"')[1]
return "not found"
def commit_row(repo: Path, sha: str) -> dict[str, str]:
out = git(repo, f"show --format='%cI%x09%h%x09%s' --no-patch {sha}")
date, short, subject = out.split("\t", 2)
return {"sha": short, "date": date, "subject": subject}
def has_retirement_formula_in_sdist(version: str) -> bool:
with urllib.request.urlopen(f"https://pypi.org/pypi/policyengine-us/{version}/json", timeout=30) as response:
payload = json.load(response)
sdist_url = next(
file["url"]
for file in payload["urls"]
if file["packagetype"] == "sdist"
)
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / f"policyengine_us-{version}.tar.gz"
urllib.request.urlretrieve(sdist_url, path)
with tarfile.open(path) as tar:
member = next(
m
for m in tar.getmembers()
if m.name.endswith(
"policyengine_us/variables/gov/ssa/ss/social_security_retirement.py"
)
)
text = tar.extractfile(member).read().decode()
return "def formula(" in text
def duration(start: str, end: str) -> str:
delta = datetime.fromisoformat(end) - datetime.fromisoformat(start)
days = delta.days
hours, rem = divmod(delta.seconds, 3600)
minutes = rem // 60
return f"{days}d {hours}h {minutes}m"
def print_table(rows: list[dict[str, str]], columns: list[str]) -> None:
widths = {
col: max(len(col), *(len(str(row.get(col, ""))) for row in rows))
for col in columns
}
print(" | ".join(col.ljust(widths[col]) for col in columns))
print("-+-".join("-" * widths[col] for col in columns))
for row in rows:
print(" | ".join(str(row.get(col, "")).ljust(widths[col]) for col in columns))
def main() -> None:
print("Repositories")
print(f"policyengine-us-data: {US_DATA}")
print(f"policyengine-us: {US}")
print()
print("1. Key source-control events")
key_events = [
("policyengine-us-data", US_DATA, "7025f6a2", "merged formula/adds/subtracts export pruning"),
("policyengine-us-data", US_DATA, "6216d02c", "first data package update after #554"),
("policyengine-us-data", US_DATA, "dd3455a0", "QRF-impute CPS-only variables including SS subcomponents"),
("policyengine-us", US, "c5f1b5da1b", "made social_security_retirement formula-backed"),
("policyengine-us-data", US_DATA, "491ac09c", "first bad dependency lock, failed pipeline"),
("policyengine-us-data", US_DATA, "a2f3bb36", "first completed bad generated data run"),
("policyengine-us-data", US_DATA, "f14931eb", "first promoted/live bad data run found"),
("policyengine-us", US, "06a52825cf", "restored social_security_retirement as canonical input"),
("policyengine-us-data", US_DATA, "61a43e95", "first data package update after the fix"),
]
rows = []
for repo_name, repo, sha, note in key_events:
row = commit_row(repo, sha)
row["repo"] = repo_name
row["note"] = note
if repo_name == "policyengine-us-data":
row["data_version"] = pyproject_version_at(repo, sha)
row["policyengine_us"] = policyengine_us_version_at(sha)
else:
row["data_version"] = ""
row["policyengine_us"] = pyproject_version_at(repo, sha)
rows.append(row)
print_table(rows, ["date", "repo", "sha", "data_version", "policyengine_us", "note"])
print()
print("2. PyPI check: first policyengine-us release where social_security_retirement had a formula")
formula_rows = []
for version in ["1.642.0", "1.643.0", "1.644.0", "1.691.3"]:
formula_rows.append(
{
"policyengine_us": version,
"retirement_has_formula": str(has_retirement_formula_in_sdist(version)),
}
)
print_table(formula_rows, ["policyengine_us", "retirement_has_formula"])
print()
print("3. Incident windows used in the postmortem")
windows = [
{
"window": "total social_security direct-input risk",
"start": "2026-03-04T15:23:42+00:00",
"end": "2026-03-14T13:41:06+00:00",
"duration": duration(
"2026-03-04T15:23:42+00:00",
"2026-03-14T13:41:06+00:00",
),
"basis": "#554 data release -> #589 source fix",
},
{
"window": "retirement, generated artifacts",
"start": "2026-04-30T20:51:13+00:00",
"end": "2026-05-12T17:02:15+00:00",
"duration": duration(
"2026-04-30T20:51:13+00:00",
"2026-05-12T17:02:15+00:00",
),
"basis": "first completed bad run -> first fixed Run Pipeline",
},
{
"window": "retirement, live/promoted artifacts",
"start": "2026-05-04T03:08:33+00:00",
"end": "2026-05-12T17:02:15+00:00",
"duration": duration(
"2026-05-04T03:08:33+00:00",
"2026-05-12T17:02:15+00:00",
),
"basis": "first promoted bad run found -> first fixed Run Pipeline",
},
]
print_table(windows, ["window", "start", "end", "duration", "basis"])
print()
print("4. GitHub Actions evidence for first fixed data update")
runs = run(
"gh run list --repo PolicyEngine/policyengine-us-data "
"--workflow 'Run Pipeline' --created '2026-05-12..2026-05-13' "
"--limit 10 --json createdAt,conclusion,headSha,url "
"| jq -r '.[] | [.createdAt,.conclusion,.headSha,.url] | @tsv'"
)
print(runs)
print()
print("Conclusions")
print("- social_security was at risk when policyengine-us-data stopped exporting computed variables in #554.")
print("- The safer data contract is: export leaf inputs; calculate formula/adds/subtracts variables in policyengine-us.")
print("- That contract failed again when policyengine-us made social_security_retirement formula-backed without preserving the canonical input path.")
print("- The May 12 fix restored social_security_retirement as the canonical input and moved reported/data-only paths out of public formulas.")
if __name__ == "__main__":
main()
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
"""Plot total Social Security from H5 contents by data release date.
Two views:
1. Total $B at sim period 2024: stored aggregate vs subcomponent-sum (shows pre-#554 discontinuity)
2. Total $B at 2024, 2025, 2026 (uprating the subcomponent path with SSA COLA)
Annotates key events: #554 merge, #589 merge, #8040 model break, May 12 fix.
"""
from pathlib import Path
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
CSV = Path("/tmp/ss_sweep_results.csv")
OUT_PRIMARY = Path("/tmp/ss_by_release.png")
OUT_THREE_YEAR = Path("/tmp/ss_by_release_3yr.png")
# SSA COLA factors actually applied to benefits:
# - 2024 COLA = 3.2% (raised benefits paid in 2024 vs 2023)
# - 2025 COLA = 2.5% (raised benefits paid in 2025 vs 2024)
# Policyengine-us uprates SS benefits ~ COLA. Use the published 2025 COLA as 2024→2025,
# and a CBO-typical ~2.5% for 2025→2026. Note: approximate.
COLA_2024_TO_2025 = 1.025
COLA_2025_TO_2026 = 1.025
KEY_EVENTS = [
("2026-03-04T15:23Z", "#554 merged", "darkred"),
("2026-03-14T13:41Z", "#589 merged", "darkgreen"),
("2026-04-17T18:36Z", "policyengine-us#8040", "darkorange"),
("2026-05-12T17:02Z", "Fix promoted", "darkblue"),
]
def main():
df = pd.read_csv(CSV)
df = df[df["status"] == "ok"].copy()
df["date"] = pd.to_datetime(df["commit_date"])
df = df.sort_values("date")
print(f"{len(df)} ok rows from {df['date'].min()} to {df['date'].max()}")
# 1) primary: stored vs sum-of-subs at 2024
fig, ax = plt.subplots(figsize=(11, 5.5))
stored = df.copy()
stored.loc[stored["stored_ss_present"] == 0, "stored_ss_total_B"] = float("nan")
ax.plot(
stored["date"],
stored["stored_ss_total_B"],
marker="o",
markersize=4,
label="Stored social_security/2024 (only when present in H5)",
color="C3",
)
ax.plot(
df["date"],
df["subs_sum_total_B"],
marker="o",
markersize=4,
label="Sum of subcomponents/2024",
color="C0",
)
for ts, label, color in KEY_EVENTS:
d = pd.Timestamp(ts)
ax.axvline(d, color=color, linestyle="--", alpha=0.6)
ax.text(
d,
ax.get_ylim()[1] * 0.95 if ax.get_ylim()[1] > 0 else 1,
f" {label}",
color=color,
rotation=90,
va="top",
fontsize=8,
)
ax.set_title("Social Security in policyengine-us-data H5 by release date (sim period 2024)")
ax.set_ylabel("Total Social Security, weighted ($B)")
ax.set_xlabel("Release date (HF tag)")
ax.xaxis.set_major_locator(mdates.MonthLocator(interval=1))
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m"))
fig.autofmt_xdate()
ax.grid(alpha=0.3)
ax.legend(loc="lower left")
fig.tight_layout()
fig.savefig(OUT_PRIMARY, dpi=140)
print(f"wrote {OUT_PRIMARY}")
# 2) three-year view (uprate subcomponent path)
df["ss_2024_effective_B"] = df.apply(
lambda r: r["stored_ss_total_B"] if r["stored_ss_present"] == 1 else r["subs_sum_total_B"],
axis=1,
)
df["ss_2025_implied_B"] = df["subs_sum_total_B"] * COLA_2024_TO_2025
df["ss_2026_implied_B"] = df["subs_sum_total_B"] * COLA_2024_TO_2025 * COLA_2025_TO_2026
fig, ax = plt.subplots(figsize=(11, 5.5))
ax.plot(df["date"], df["ss_2024_effective_B"], marker="o", markersize=4, label="2024 (sim base year): uses stored if present, else formula", color="C3")
ax.plot(df["date"], df["ss_2025_implied_B"], marker="o", markersize=4, label="2025 (sim formula × 2.5% COLA)", color="C0")
ax.plot(df["date"], df["ss_2026_implied_B"], marker="o", markersize=4, label="2026 (sim formula × 2.5% × 2.5%)", color="C2")
for ts, label, color in KEY_EVENTS:
d = pd.Timestamp(ts)
ax.axvline(d, color=color, linestyle="--", alpha=0.6)
ax.set_title("Implied total Social Security by sim year, by data release date")
ax.set_ylabel("Total Social Security, weighted ($B)")
ax.set_xlabel("Release date (HF tag)")
ax.xaxis.set_major_locator(mdates.MonthLocator(interval=1))
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m"))
fig.autofmt_xdate()
ax.grid(alpha=0.3)
ax.legend(loc="lower left", fontsize=9)
fig.tight_layout()
fig.savefig(OUT_THREE_YEAR, dpi=140)
print(f"wrote {OUT_THREE_YEAR}")
if __name__ == "__main__":
main()
"""Sweep every HF tag of policyengine/policyengine-us-data, compute weighted Social Security
aggregates from the enhanced_cps_2024.h5, then delete the file before fetching the next.
Outputs /tmp/ss_sweep_results.csv with columns:
version, commit_date, n_persons, sum_weights,
stored_ss_present, stored_ss_recipients_M, stored_ss_total_B,
subs_sum_recipients_M, subs_sum_total_B,
retirement_B, disability_B, survivors_B, dependents_B,
retirement_present, disability_present, survivors_present, dependents_present
"""
import csv
import os
import sys
import time
import urllib.request
from pathlib import Path
import h5py
import numpy as np
H5_PATH = Path("/tmp/h5_samples/_current.h5")
RESULTS = Path("/tmp/ss_sweep_results.csv")
TAGS_CSV = Path("/tmp/us_data_tags.csv")
def parse_version_key(v):
try:
return tuple(int(p) for p in v.split("."))
except Exception:
return (0,)
def load_versions():
out = []
with TAGS_CSV.open() as f:
next(f)
for line in f:
parts = line.rstrip("\n").split(",")
ver, sha, date = parts[0], parts[1], parts[2]
if date.startswith("ERR") or date == "NOT_FOUND":
continue
out.append((ver, sha, date))
out.sort(key=lambda r: parse_version_key(r[0]))
return out
def download_h5(version, dest):
url = f"https://huggingface.co/policyengine/policyengine-us-data/resolve/{version}/enhanced_cps_2024.h5"
req = urllib.request.Request(url, headers={"User-Agent": "ss-sweep/1.0"})
with urllib.request.urlopen(req, timeout=180) as r, dest.open("wb") as out:
while True:
chunk = r.read(1 << 20)
if not chunk:
break
out.write(chunk)
SUBS = ["retirement", "disability", "survivors", "dependents"]
def analyze(path):
with h5py.File(path, "r") as f:
if "person_household_id/2024" not in f:
return None
person_hh = f["person_household_id/2024"][:]
hh_id = f["household_id/2024"][:]
hh_w = f["household_weight/2024"][:]
weight_map = dict(zip(hh_id.tolist(), hh_w.tolist()))
person_w = np.array([weight_map[int(h)] for h in person_hh], dtype=np.float64)
row = {
"n_persons": int(person_w.size),
"sum_weights": float(person_w.sum()),
}
stored_present = "social_security/2024" in f
row["stored_ss_present"] = int(stored_present)
if stored_present:
ss = f["social_security/2024"][:]
row["stored_ss_recipients_M"] = float(((ss > 0) * person_w).sum() / 1e6)
row["stored_ss_total_B"] = float((ss * person_w).sum() / 1e9)
else:
row["stored_ss_recipients_M"] = float("nan")
row["stored_ss_total_B"] = float("nan")
subs_sum = np.zeros_like(person_w)
for sub in SUBS:
key = f"social_security_{sub}/2024"
present = key in f
row[f"{sub}_present"] = int(present)
if present:
vals = f[key][:].astype(np.float64)
row[f"{sub}_B"] = float((vals * person_w).sum() / 1e9)
subs_sum += vals
else:
row[f"{sub}_B"] = float("nan")
row["subs_sum_recipients_M"] = float(((subs_sum > 0) * person_w).sum() / 1e6)
row["subs_sum_total_B"] = float((subs_sum * person_w).sum() / 1e9)
return row
def main():
H5_PATH.parent.mkdir(parents=True, exist_ok=True)
versions = load_versions()
print(f"{len(versions)} versions to process", flush=True)
cols = [
"version",
"commit_date",
"n_persons",
"sum_weights",
"stored_ss_present",
"stored_ss_recipients_M",
"stored_ss_total_B",
"subs_sum_recipients_M",
"subs_sum_total_B",
"retirement_B",
"disability_B",
"survivors_B",
"dependents_B",
"retirement_present",
"disability_present",
"survivors_present",
"dependents_present",
"status",
"error",
]
write_header = not RESULTS.exists()
fout = RESULTS.open("a", newline="")
w = csv.DictWriter(fout, fieldnames=cols)
if write_header:
w.writeheader()
done = set()
if not write_header:
with RESULTS.open() as f:
r = csv.DictReader(f)
for row in r:
if row["status"] == "ok":
done.add(row["version"])
print(f"resume: {len(done)} already processed", flush=True)
t0 = time.time()
for idx, (ver, sha, date) in enumerate(versions, 1):
if ver in done:
continue
row = {"version": ver, "commit_date": date, "status": "?", "error": ""}
try:
if H5_PATH.exists():
H5_PATH.unlink()
t = time.time()
download_h5(ver, H5_PATH)
dt_dl = time.time() - t
t = time.time()
res = analyze(H5_PATH)
dt_an = time.time() - t
if res is None:
row["status"] = "no_2024"
else:
row.update(res)
row["status"] = "ok"
print(
f"[{idx}/{len(versions)}] {ver} dl={dt_dl:.1f}s an={dt_an:.1f}s status={row['status']} stored={row.get('stored_ss_total_B')} subs={row.get('subs_sum_total_B')}",
flush=True,
)
except Exception as e:
row["status"] = "error"
row["error"] = str(e)[:200]
print(f"[{idx}/{len(versions)}] {ver} ERR {e}", flush=True)
finally:
try:
if H5_PATH.exists():
H5_PATH.unlink()
except Exception:
pass
w.writerow(row)
fout.flush()
fout.close()
print(f"DONE in {time.time()-t0:.0f}s. Output: {RESULTS}", flush=True)
if __name__ == "__main__":
main()
version commit_date n_persons sum_weights stored_ss_present stored_ss_recipients_M stored_ss_total_B subs_sum_recipients_M subs_sum_total_B retirement_B disability_B survivors_B dependents_B retirement_present disability_present survivors_present dependents_present status error
1.25.3 2025-05-27T00:06:07.000Z 101726 356118023.46653414 1 75.18176303217172 1540.9732745652466 74.53128755692224 1524.5483282707582 1333.9089254364962 190.63940283426223 0.0 0.0 1 1 1 1 ok
1.26.0 2025-06-09T11:52:51.000Z 101726 348644364.7796898 1 74.5980688530499 1520.7694444197052 72.17650021323185 1505.0066235352735 1302.2545419825738 202.75208155269962 0.0 0.0 1 1 1 1 ok
1.28.1 2025-06-12T18:12:12.000Z 101726 353491204.8724582 1 74.15303285685037 1539.80739029271 71.6292330911561 1511.6633386827298 1307.7572450185567 203.9060936641732 0.0 0.0 1 1 1 1 ok
1.28.2 2025-06-13T12:18:35.000Z 101726 356816545.11809874 1 77.04101911530176 1569.2574159869775 75.38451409775006 1574.6396795004828 1356.2423682931367 218.3973112073459 0.0 0.0 1 1 1 1 ok
1.28.4 2025-06-13T17:43:05.000Z 101726 361264926.32439643 1 74.14132366241707 1531.9804569284174 73.09183293935807 1516.6706858640716 1325.6491954938608 191.02149037021056 0.0 0.0 1 1 1 1 ok
1.29.0 2025-06-14T21:50:25.000Z 101726 354604400.2627739 1 73.20342186346457 1499.1131486701377 71.87296577065031 1480.5478617697104 1280.260544976099 200.28731679361135 0.0 0.0 1 1 1 1 ok
1.29.1 2025-06-18T11:19:14.000Z 101726 354387713.9631823 1 75.79403478378707 1550.240222538709 73.08817916526026 1512.8504637416183 1325.7045690183588 187.14589472325972 0.0 0.0 1 1 1 1 ok
1.30.0 2025-06-19T11:21:38.000Z 101726 354143836.71325946 1 73.9694055525508 1521.24807158798 73.08109156813961 1519.6888467890888 1320.3716335783618 199.31721321072672 0.0 0.0 1 1 1 1 ok
1.30.1 2025-06-19T11:25:29.000Z 101726 356509518.6583538 1 74.74111421647389 1530.8872938121267 73.21661093911713 1539.5342931550833 1346.7042209859706 192.830072169113 0.0 0.0 1 1 1 1 ok
1.30.2 2025-06-19T15:12:46.000Z 101726 356181902.40008146 1 74.07601193395863 1509.0528967980192 70.6179565826448 1480.2663090300803 1314.9609395588843 165.3053694711959 0.0 0.0 1 1 1 1 ok
1.31.0 2025-06-19T22:48:33.000Z 101726 352044794.5991116 1 75.6467200553696 1518.899690589845 72.30186669457402 1504.1092685679391 1297.2640408035058 206.84522776443342 0.0 0.0 1 1 1 1 ok
1.32.0 2025-06-28T13:26:50.000Z 101726 351781197.06310105 1 76.53607400891741 1518.7298731292674 72.76967580366775 1467.6780615644732 1275.4621459591726 192.21591560530035 0.0 0.0 1 1 1 1 ok
1.32.1 2025-07-01T17:39:51.000Z 101726 349087761.17170966 1 74.19884821021952 1503.427182142481 71.0747967778907 1442.073183318323 1271.8751681788294 170.19801513949366 0.0 0.0 1 1 1 1 ok
1.36.1 2025-07-03T09:40:51.000Z 101726 352085357.37828124 1 68.64720632891797 1383.1646945220366 68.60249429316103 1381.400002664405 1258.4157822958255 122.98422036857984 0.0 0.0 1 1 1 1 ok
1.36.2 2025-07-08T22:11:54.000Z 101726 355656966.544722 1 68.84178684388286 1408.2780411898023 68.83392548168558 1407.5217481716725 1272.435604200921 135.08614397075104 0.0 0.0 1 1 1 1 ok
1.37.0 2025-07-09T15:18:36.000Z 101726 357073491.61913747 1 69.07159761860997 1412.893682306525 69.03845513646203 1411.7766280475767 1282.1006093414107 129.67601870616602 0.0 0.0 1 1 1 1 ok
1.38.0 2025-07-16T01:19:19.000Z 101726 352909297.7033328 1 68.10216768261165 1408.3253652786739 68.10189549811173 1408.316318222463 1271.0943062237 137.22201199876335 0.0 0.0 1 1 1 1 ok
1.38.1 2025-07-17T20:25:49.000Z 101726 354850951.5338749 1 67.89103564781135 1391.3237224396487 67.89066266421324 1391.306315906671 1250.6490490470503 140.6572668596203 0.0 0.0 1 1 1 1 ok
1.39.0 2025-07-18T16:01:40.000Z 101726 353645636.7520567 1 68.4683129623422 1423.6846713816276 66.74361103163895 1387.2491310897458 1246.9154307278961 140.33370036184974 0.0 0.0 1 1 1 1 ok
1.39.2 2025-07-24T14:06:35.000Z 101726 351043459.6679572 1 68.80101263926285 1397.0553291772806 65.69136265993845 1329.147050383571 1204.5083114801957 124.63873890337513 0.0 0.0 1 1 1 1 ok
1.40.1 2025-07-24T14:38:40.000Z 101726 344949137.5693096 1 67.06182599239811 1366.4245798848797 63.37694584364548 1287.4265232265084 1157.0074392634506 130.41908396305763 0.0 0.0 1 1 1 1 ok
1.41.1 2025-07-26T19:30:12.000Z 101726 354150867.5706811 1 68.62578281160009 1410.2663039404554 66.01401442362946 1349.807611097202 1212.3252576784412 137.48235341876057 0.0 0.0 1 1 1 1 ok
1.41.2 2025-07-26T21:17:01.000Z 101726 350459608.21614105 1 66.19868128539153 1373.2975574712912 64.99366882968636 1343.9827336655328 1205.5295549371008 138.45317872843196 0.0 0.0 1 1 1 1 ok
1.42.0 2025-07-28T16:58:18.000Z 101726 351158197.87785554 1 68.26802944648564 1387.3484441177407 65.03384221389139 1336.6768103418171 1215.3926652184089 121.28414512340834 0.0 0.0 1 1 1 1 ok
1.42.3 2025-07-30T20:48:52.000Z 101726 347042360.549301 1 67.88141232051238 1372.8840599071552 65.1732849027443 1336.16861166469 1205.967613941626 130.20099772306386 0.0 0.0 1 1 1 1 ok
1.42.4 2025-07-30T22:15:52.000Z 101726 352989867.0189288 1 68.70729306500563 1384.375011679517 64.68263560003179 1322.3777573678 1194.9616254142763 127.41613195352393 0.0 0.0 1 1 1 1 ok
1.42.5 2025-07-30T23:05:34.000Z 55683 336193860.22363967 1 66.95932949704472 1403.2341029565864 63.824580508490975 1318.6884739246636 1181.6608737580414 137.02760016662222 0.0 0.0 1 1 1 1 ok
1.42.6 2025-08-01T11:54:56.000Z 55929 336229872.0856241 1 67.46439035701918 1433.2701349696001 64.99705050574406 1330.459221181915 1185.4768629593855 144.98235822252954 0.0 0.0 1 1 1 1 ok
1.43.0 2025-08-04T19:16:56.000Z 56031 334548308.1295147 1 67.30510484831326 1425.220311963644 62.421269042569996 1296.8471952056093 1171.4909688127564 125.35622639285305 0.0 0.0 1 1 1 1 ok
1.43.1 2025-08-06T19:30:14.000Z 53982 336774451.1101157 1 69.09775099164531 1440.0424077924229 64.73689168518864 1357.4956082455994 1236.6474250773172 120.84818316828223 0.0 0.0 1 1 1 1 ok
1.44.0 2025-08-06T19:30:24.000Z 54016 337527274.058625 1 68.76964324161432 1432.951378216563 64.22613520921804 1342.9687986440724 1226.8861317278847 116.08266691618768 0.0 0.0 1 1 1 1 ok
1.44.1 2025-08-08T10:48:31.000Z 54528 336798563.70178694 1 67.77561424697545 1453.1903674075734 63.808115009321185 1381.8113151915884 1243.2165169455538 138.59479824603454 0.0 0.0 1 1 1 1 ok
1.44.2 2025-08-08T15:45:16.000Z 54807 337404541.4531936 1 67.51322174491023 1423.412234499334 63.241140271250714 1347.7754762078073 1221.0962041933105 126.67927201449709 0.0 0.0 1 1 1 1 ok
1.45.0 2025-08-20T19:20:17.000Z 54189 337009130.46771705 1 69.43605369762358 1459.0558325131328 65.21672020042139 1374.6723683263413 1231.0225713714262 143.64979695491482 0.0 0.0 1 1 1 1 ok
1.46.0 2025-09-10T21:03:19.000Z 53430 333354898.4182364 1 67.64879138515964 1421.117299280751 64.88601799124454 1392.2606040001306 1224.1917951328862 168.06880886724423 0.0 0.0 1 1 1 1 ok
1.46.1 2025-11-12T20:39:59.000Z 54130 334946387.67741126 1 67.15385274961552 1455.6784892330538 64.13665498535477 1390.2244004997929 1212.451768787056 177.77263171273697 0.0 0.0 1 1 1 1 ok
1.47.0 2025-11-20T03:28:03.000Z 54693 337023583.2942041 1 67.37132312243676 1431.932348975347 64.4511212506802 1386.3956597476993 1199.0348603241855 187.36079942351392 0.0 0.0 1 1 1 1 ok
1.47.1 2025-12-03T23:54:04.000Z 55241 335574094.71613854 1 67.29985723835158 1435.9826222915121 64.38196401303396 1377.4680251413306 1189.8156596946133 187.6523654467171 0.0 0.0 1 1 1 1 ok
1.48.0 2025-12-08T21:40:15.000Z 54209 339049626.8956548 1 68.2090367110702 1465.674043983219 65.28778425817639 1423.0494090612326 1235.711076124149 187.3383329370835 0.0 0.0 1 1 1 1 ok
1.49.0 2025-12-19T19:21:56.000Z 54232 335420209.41714215 1 66.53323814665004 1446.1154309482215 63.381550383904475 1375.4687357701462 1197.2364359511803 178.2322998189662 0.0 0.0 1 1 1 1 ok
1.50.0 2025-12-23T16:48:49.000Z 54305 336404682.00986284 1 67.73726227896461 1426.3429532904936 65.12121207916921 1363.322502035063 1164.4839274733433 198.83857456171992 0.0 0.0 1 1 1 1 ok
1.51.0 2026-01-01T20:11:49.000Z 53722 335403590.4052346 1 68.21017801126109 1440.3982066448923 64.7110447388469 1370.424359427999 1171.2556837774225 199.1686756505765 0.0 0.0 1 1 1 1 ok
1.51.1 2026-01-07T02:40:48.000Z 52826 335766318.62622714 1 67.10411933682698 1409.9223084034463 63.91663890491204 1351.1466262583924 1168.4043629890496 182.74226326934277 0.0 0.0 1 1 1 1 ok
1.54.0 2026-01-25T19:17:57.000Z 53281 339546487.52022684 1 67.42742299743314 1422.2199087781305 65.3402376354212 1384.415384218183 1193.85781601666 190.5575682015225 0.0 0.0 1 1 1 1 ok
1.55.0 2026-01-26T17:59:18.000Z 54417 333680701.674548 1 66.58563082428161 1406.6437853303594 64.10838998379687 1351.2185763312148 1161.4709895584158 189.74758677279902 0.0 0.0 1 1 1 1 ok
1.56.0 2026-01-26T23:55:20.000Z 54417 333680701.674548 1 66.58563082428161 1406.6437853303594 64.10838998379687 1351.2185763312148 1161.4709895584158 189.74758677279902 0.0 0.0 1 1 1 1 ok
1.57.0 2026-01-31T04:22:31.000Z 158469 334596579.20650524 1 67.14016545672033 1400.2769200923085 65.25258264459987 1359.3607563616238 1176.9718106857713 182.38894567585265 0.0 0.0 1 1 1 1 ok
1.58.0 2026-01-31T20:58:11.000Z 158506 336049519.52483857 1 67.12330536542831 1399.854525980698 65.21331421861306 1358.1918928369307 1177.66324436728 180.5286484696507 0.0 0.0 1 1 1 1 ok
1.59.0 2026-01-31T20:51:17.000Z 157539 334586024.9492419 1 68.92112746083446 1464.7702338401032 67.91369494542194 1434.576769985609 1042.2241903012707 145.8170538846107 162.5676284123959 83.96789738733179 1 1 1 1 ok
1.60.0 2026-01-31T20:58:01.000Z 157542 333882111.0052895 1 68.32346934416721 1451.2530344815293 67.46565832299733 1421.9985571077436 1031.1842136236435 147.61210832263566 160.09745928687863 83.10477587458588 1 1 1 1 ok
1.61.0 2026-01-31T21:24:39.000Z 160147 332788563.2516105 1 68.18856526515837 1450.5998447647264 66.75277266744449 1419.8993239571512 1032.9282677435497 144.58153503038488 157.92331411184952 84.4662070713671 1 1 1 1 ok
1.61.2 2026-02-01T21:50:03.000Z 160646 333441090.333774 1 68.35452158751201 1450.5884423811856 66.98226463301191 1419.828709297384 1031.1372210632906 144.70976991529247 159.6760628706566 84.30565544814411 1 1 1 1 ok
1.62.0 2026-02-07T01:20:32.000Z 157667 332727419.8564606 1 67.767859856063 1438.8031933841917 67.3232634302281 1422.0371271409952 1030.593481870958 147.00689873695814 158.77748018126087 85.65926635181776 1 1 1 1 ok
1.63.0 2026-02-07T20:53:08.000Z 156892 334061352.09167004 1 68.39171313078454 1445.9961224035037 67.79580241488362 1424.5652465985102 1032.0527267973653 148.14978450950449 158.11372603752875 86.24900925411143 1 1 1 1 ok
1.63.1 2026-02-08T04:02:30.000Z 51175 335692945.4512296 1 68.20561455934178 1445.248772801207 68.1088106322198 1440.143078018888 1048.238490456776 148.76107663165934 158.58653189082415 84.55697903962839 1 1 1 1 ok
1.64.0 2026-02-08T05:12:50.000Z 49941 334301233.9133367 1 67.49428396418921 1427.9806325119011 67.12388945364042 1422.134060452216 1033.0263449515767 147.74257899251867 157.99543743910831 83.36969906901243 1 1 1 1 ok
1.64.1 2026-02-09T18:46:01.000Z 49935 336316366.25025284 1 68.05230530367446 1436.5870820740006 67.82162622222428 1430.7901497286914 1039.9049031384325 149.04525712256452 158.15444377958784 83.68554568810666 1 1 1 1 ok
1.65.0 2026-02-12T06:26:46.000Z 50148 335578773.30580693 1 67.63601101487139 1429.7709283731556 67.45171143747756 1425.065027943972 1035.5579310760102 148.3809958915224 157.47784147926447 83.64825949717509 1 1 1 1 ok
1.66.0 2026-02-12T17:38:37.000Z 49756 335007415.46464604 1 68.21322109047517 1438.0937870343325 67.89147784855489 1428.2772425140547 1039.0073353178568 148.1689743100584 158.230205697909 82.87072718823053 1 1 1 1 ok
1.67.0 2026-02-12T20:07:04.000Z 49925 335079291.95736104 1 67.44449615765087 1430.1971832796532 67.11934872722956 1425.7358949694376 1037.1816329422245 147.04358672489846 158.41768400355988 83.09299129875471 1 1 1 1 ok
1.68.0 2026-02-17T16:13:46.000Z 50204 335023196.0275054 1 67.84027589583383 1433.591580035698 67.38399736934615 1426.8165965609196 1037.2950524897567 148.42990459352546 157.80786185075493 83.28377762688272 1 1 1 1 ok
1.69.0 2026-02-18T22:11:06.000Z 44206 334928562.39900804 1 33.82557476587603 824.4948343342854 66.6287548656856 1451.159164145352 1061.9615587688443 147.6677665713329 158.1558229105456 83.374015894629 1 1 1 1 ok
1.69.1 2026-02-19T07:02:39.000Z 44159 335294471.3443033 1 33.700224898113234 822.8333796404671 67.00595464062397 1444.0559276872077 1054.1968874849415 148.15014120928714 157.6764425245499 84.03245646842923 1 1 1 1 ok
1.69.2 2026-02-19T15:59:37.000Z 284250 333871605.0729275 1 33.676839404254395 809.3915603866806 67.48274002991555 1432.6506179753983 1046.2723943106892 147.5046101569288 156.66267714487964 82.2109363629007 1 1 1 1 ok
1.69.3 2026-02-19T18:03:02.000Z 43240 333917525.052158 1 33.67304567742545 808.8371688207056 67.03713099503436 1436.8607359139266 1050.8140652389707 147.1957719254226 156.62139591912884 82.22950283040447 1 1 1 1 ok
1.69.4 2026-02-24T12:07:07.000Z 43279 333211995.0581193 1 33.487459926008746 805.9980059597149 66.8129214093007 1429.8927287281028 1043.9802878384132 146.4950481823368 157.81365607196437 81.60373663538819 1 1 1 1 ok
1.70.0 2026-02-26T03:32:23.000Z 43236 334087453.8296997 1 33.59359258530246 808.0112117290471 66.892291237129 1434.0016912483952 1047.7756604972653 147.11284290096256 156.75390201648338 82.35928583368417 1 1 1 1 ok
1.71.1 2026-03-04T14:45:44.000Z 44748 333911727.8955541 1 33.891858534710344 809.0620682844383 65.56641913855037 1436.4187147002988 1048.2623951445653 147.52532505098284 157.41006667145646 83.2209278332945 1 1 1 1 ok
1.71.2 2026-03-04T16:56:09.000Z 19549 343980043.1172986 0 nan nan 59.924402157912084 1382.6439806066337 998.6815390148314 174.58314963814124 136.53528238528347 72.84400956837786 1 1 1 1 ok
1.71.3 2026-03-04T21:55:16.000Z 19450 343219948.0601027 0 nan nan 61.23954610063633 1387.3028594856926 1003.6594247026724 178.06118074537594 133.7805068788598 71.80174715878465 1 1 1 1 ok
1.71.4 2026-03-04T23:45:06.000Z 284250 345113115.6640005 0 nan nan 63.31791882450462 1402.5457754987842 1020.328295964828 167.32400770019294 139.02067084615854 75.87280098760455 1 1 1 1 ok
1.72.3 2026-03-10T04:12:12.000Z 101384 336148000.2838849 0 nan nan 67.19062969027858 1441.6670554730015 1051.0020092636996 150.94699282048563 156.74650288102472 82.9715505077915 1 1 1 1 ok
1.73.0 2026-03-12T18:55:29.000Z 101384 335857214.2305056 0 nan nan 66.20108423888 1449.3796854686582 1060.230008983388 151.2479285687733 155.40104323016467 82.50070468633203 1 1 1 1 ok
1.74.0 2026-04-03T14:38:07.000Z 101384 335467199.0293275 0 nan nan 64.0213251023007 1466.2729783438763 1079.0801247130971 148.07028743152978 155.7906580281442 83.33190817110507 1 1 1 1 ok
1.74.1 2026-04-03T13:56:33.000Z 101384 335467199.0293275 0 nan nan 64.0213251023007 1466.2729783438763 1079.0801247130971 148.07028743152978 155.7906580281442 83.33190817110507 1 1 1 1 ok
1.74.2 2026-04-04T14:30:18.000Z 101384 336582143.09864753 0 nan nan 64.27987101235627 1453.6669144219388 1065.3839222342685 147.98543148602275 156.28733169018153 84.01022901146604 1 1 1 1 ok
1.74.3 2026-04-07T19:45:29.000Z 101384 334975126.86086035 0 nan nan 63.69626993735162 1447.7281506957859 1061.8598199809883 147.6578771675772 155.07875279225667 83.1317007549637 1 1 1 1 ok
1.75.0 2026-04-08T16:57:01.000Z 101384 336062115.5259162 0 nan nan 64.34932090706177 1472.8555307715842 1084.7826667223824 148.14471965078107 156.29130290871825 83.63684148970275 1 1 1 1 ok
1.75.1 2026-04-09T03:48:30.000Z 101384 333819374.62224483 0 nan nan 62.32323231355859 1429.6853671900567 1047.1310023738017 145.9856097004077 153.58877803071002 82.97997708513704 1 1 1 1 ok
1.75.2 2026-04-09T03:41:06.000Z 101384 335358638.1331346 0 nan nan 64.46137830907962 1463.4164035752551 1076.2113743932784 147.94181559553869 155.59053812080694 83.67267546563112 1 1 1 1 ok
1.75.3 2026-04-09T03:23:51.000Z 101384 333819374.62224483 0 nan nan 62.32323231355859 1429.6853671900567 1047.1310023738017 145.9856097004077 153.58877803071002 82.97997708513704 1 1 1 1 ok
1.75.4 2026-04-09T04:14:48.000Z 101384 335358638.1331346 0 nan nan 64.46137830907962 1463.4164035752551 1076.2113743932784 147.94181559553869 155.59053812080694 83.67267546563112 1 1 1 1 ok
1.75.5 2026-04-09T13:35:24.000Z 101384 336083030.7295989 0 nan nan 64.5434327364349 1476.1232878605283 1087.4751336000377 148.29118201051364 156.783275600727 83.57369664924991 1 1 1 1 ok
1.75.6 2026-04-09T19:08:37.000Z 101384 336072788.00089 0 nan nan 64.45548059583841 1475.2759295678004 1088.2230747441404 148.0070805392315 155.57089409735192 83.47488018707637 1 1 1 1 ok
1.75.7 2026-04-10T03:01:22.000Z 101384 334534783.5997416 0 nan nan 63.45299157716789 1446.797784175054 1063.025489607201 146.6025390929455 154.1952697697459 82.97448570516175 1 1 1 1 ok
1.75.8 2026-04-10T15:53:04.000Z 101384 335033527.0580803 0 nan nan 64.35377667628792 1475.1788007985633 1087.9112079018096 148.63271278072085 155.64360269204207 82.99127742399075 1 1 1 1 ok
1.76.0 2026-04-10T20:35:24.000Z 101384 334920879.69054824 0 nan nan 63.56510965584421 1448.4028229972866 1061.7610052522004 147.75393026574093 155.75736728589783 83.13052019344755 1 1 1 1 ok
1.78.0 2026-04-12T02:43:29.000Z 101384 334906388.9560204 0 nan nan 64.13468124814385 1476.9824837062151 1089.9718189744353 148.31400635755458 155.40437728627282 83.29228108795219 1 1 1 1 ok
1.78.1 2026-04-12T22:43:47.000Z 101384 334719406.92393947 0 nan nan 64.05588612781602 1472.9760546724472 1086.1758465946768 148.4260177874934 155.0593311785 83.31485911177722 1 1 1 1 ok
1.78.2 2026-04-12T21:59:56.000Z 101384 334719406.92393947 0 nan nan 64.05588612781602 1472.9760546724472 1086.1758465946768 148.4260177874934 155.0593311785 83.31485911177722 1 1 1 1 ok
1.90.1 2026-05-04T17:06:39.000Z 101384 334698066.0388521 0 nan nan 28.16504249555555 544.6508951461363 nan 226.85706718920312 218.27012385948314 99.52370409745012 0 1 1 1 ok
1.110.12 2026-05-11T18:56:49.000Z 101384 337835734.37285745 0 nan nan 25.73140802952223 507.5960818788916 nan 241.47235928031472 177.44938605929238 88.67433653928448 0 1 1 1 ok
1.113.1 2026-05-13T03:56:37.000Z 101384 335653612.83335036 0 66.0821974667698 1549.6196964477028 1178.8151985906234 145.48962362883384 145.743517017344 79.57135721090174 1 1 1 1 ok
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment