Scope
Lightweight, copy-paste checks you can run locally using only CSV files (no downloads from this blog). Validates coverage, headers, and the node identity Ketu(t) = wrap360( Rahu(t) + 180 ).
CSV layout (expected headers)"planet","date","lon_sidereal_lahiri_deg"
A) Python 3 (portable; save as public_check.py)
import csv, sys
from collections import defaultdict
def wrap360(x):
return ((x % 360.0) + 360.0) % 360.0
def coverage(path):
rows = defaultdict(list)
with open(path, newline='') as f:
rdr = csv.DictReader(f)
exp = ["planet","date","lon_sidereal_lahiri_deg"]
assert rdr.fieldnames == exp, f"header_mismatch: {rdr.fieldnames} != {exp}"
for r in rdr:
p = r["planet"].strip().lower()
rows[p].append(r["date"])
for p, ds in sorted(rows.items()):
ds = sorted(ds)
print(f"{p:8s} rows={len(ds)} first={ds[0]} last={ds[-1]}")
def nodes_relation(path):
bydate = defaultdict(dict)
with open(path, newline='') as f:
rdr = csv.DictReader(f)
for r in rdr:
p = r["planet"].strip().lower()
if p not in ("rahu","ketu"):
continue
bydate[r["date"]][p] = float(r["lon_sidereal_lahiri_deg"])
mism = 0
for d, mp in bydate.items():
if "rahu" in mp and "ketu" in mp:
exp = wrap360(mp["rahu"] + 180.0)
diff = abs(wrap360(mp["ketu"] - exp))
if diff > 1e-6:
mism += 1
print("nodes_mismatch_count=", mism)
if __name__ == "__main__":
if len(sys.argv) < 3:
print("usage: python public_check.py <planets_csv> <nodes_csv>")
sys.exit(2)
planets_csv, nodes_csv = sys.argv[1], sys.argv[2]
print("coverage (planets):"); coverage(planets_csv)
print("\nnodes relation:"); nodes_relation(nodes_csv)
B) Windows PowerShell (nodes relation check, Rahu ↔ Ketu)
$wrap360 = { param($x) ((($x % 360) + 360) % 360) }
$nodes = Import-Csv "<nodes.csv>"
$g = $nodes | Where-Object { $_.planet -in @('rahu','ketu') } | Group-Object date
$mism=0
foreach($grp in $g){
$rah = $grp.Group | Where-Object planet -eq 'rahu' | Select-Object -First 1
$ket = $grp.Group | Where-Object planet -eq 'ketu' | Select-Object -First 1
if($rah -and $ket){
$exp = & $wrap360 ([double]$rah.lon_sidereal_lahiri_deg + 180.0)
$diff = [math]::Abs( & $wrap360 ( [double]$ket.lon_sidereal_lahiri_deg - $exp ) )
if($diff -gt 1e-6){ $mism++ }
}
}
"nodes_mismatch_count=$mism"
Tips
- Keep frame/time conventions consistent (sidereal Lahiri; one fixed daily timestamp).
- Use case-insensitive planet names and strict headers.
- For daily CSVs, angles should change smoothly day-to-day; large jumps imply wrap issues.
- Treat undefined aggregates as
NaNrather than0.
Navigation
Back: SSM-JTK – Data & Calibration — Integrity & invariants (2.11)
Next: SSM-JTK – Results to Date — Public-golden CSV checks (3.1)