Open-source release: pipeline code, raw logs, derived data, licences, tests

Adds src/ (scripts, raw measurement logs, derived data, report source),
tests/, LICENSE (MIT, code) and LICENSE-DATA.md (CC BY 4.0 for the survey's
data; third-party terms). The report is updated to the current site; the
v1 and v2 data hand-off files are unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Toby
2026-10-27 20:09:54 -04:00
parent 75da69fc31
commit c094eb88fa
81 changed files with 249210 additions and 127 deletions
+93
View File
@@ -0,0 +1,93 @@
"""Reduce WonderNetwork's public one-day ping dump (2020-07-19/20) to one
robust RTT floor per city pair and test it against every model.
RTT used = median of the per-run minimums (each run = 30 pings). Using the
median instead of the single fastest ping discards glitch runs and errs in the
flat models' favour (a higher RTT is easier for a long flat route to explain).
"""
import csv, gzip, json, statistics, sys
from collections import defaultdict
from models import MODELS, distance, floor_ms, C_FIBER, C_VACUUM
RAW = "raw/wn"
SLACK_KM = 200 # each endpoint may sit up to 100 km from its listed coordinates
SLACK_MS = 1.0 # timer / queueing jitter allowance
servers = {}
with open(f"{RAW}/servers-2020-07-19.csv") as f:
for r in csv.DictReader(f):
servers[r["id"]] = dict(name=r["title"], country=r["country"],
lat=float(r["latitude"]), lon=float(r["longitude"]))
runs = defaultdict(list)
avgs = defaultdict(list)
with gzip.open(f"{RAW}/pings-2020-07-19-2020-07-20.csv.gz", "rt") as f:
for r in csv.DictReader(f):
s, d = r["source"], r["destination"]
if s == d or s not in servers or d not in servers:
continue
try:
mn, av = float(r["min"]), float(r["avg"])
except ValueError:
continue
if mn > 0:
key = tuple(sorted((s, d), key=int))
runs[key].append(mn)
avgs[key].append(av)
def impossible(rtt, km, speed=C_FIBER):
return rtt + SLACK_MS < floor_ms(max(0.0, km - SLACK_KM), speed)
pairs = []
for (a, b), mins in runs.items():
if len(mins) < 5:
continue
A, B = servers[a], servers[b]
pa, pb = (A["lat"], A["lon"]), (B["lat"], B["lon"])
row = dict(a=a, b=b, n=len(mins), rtt=round(statistics.median(mins), 2),
best=round(min(mins), 2), avg=round(statistics.median(avgs[(a, b)]), 2))
for m in MODELS:
row[m] = round(distance(m, pa, pb), 1)
pairs.append(row)
# A pair that is impossible on the globe is impossible on every flat map too
# (all three flat maps stretch every distance relative to the globe), so one
# of the two servers' advertised location must be wrong. Greedily drop the
# server implicated most often; when only 1:1 conflicts remain we can't tell
# which side is lying, so both go.
mislocated = set()
while True:
bad = [r for r in pairs if r["a"] not in mislocated and r["b"] not in mislocated
and impossible(r["rtt"], r["globe"])]
if not bad:
break
count = defaultdict(int)
for r in bad:
count[r["a"]] += 1
count[r["b"]] += 1
worst = max(count.values())
mislocated |= {s for s, n in count.items() if n == worst} if worst == 1 else {max(count, key=count.get)}
clean = [r for r in pairs if r["a"] not in mislocated and r["b"] not in mislocated]
def report(rows, label):
print(f"\n{label}: {len(rows)} pairs")
for m in MODELS:
fib = sum(impossible(r["rtt"], r[m]) for r in rows)
vac = sum(impossible(r["rtt"], r[m], C_VACUUM) for r in rows)
print(f" {m:9s} beats light-in-fibre: {fib:5d} ({fib/len(rows):6.2%}) beats light-in-vacuum: {vac:5d} ({vac/len(rows):6.2%})")
print("mislocated servers dropped:", ", ".join(f"{servers[s]['name']} ({servers[s]['country']})" for s in sorted(mislocated, key=int)))
report(pairs, "ALL pairs")
report(clean, "CLEAN pairs")
south = [r for r in clean if servers[r["a"]]["lat"] < 0 and servers[r["b"]]["lat"] < 0]
report(south, "CLEAN, both ends in southern hemisphere")
if len(sys.argv) > 1:
used = {s for r in clean for s in (r["a"], r["b"])}
json.dump(dict(servers={k: v for k, v in servers.items() if k in used},
mislocated=[servers[s] for s in sorted(mislocated, key=int)],
pairs=clean), open(sys.argv[1], "w"))