Goal. Anyone can reproduce daily sidereal angles from a single JSON manifest and a one-line evaluator — no runtime ephemeris, no hidden knobs.
Status. All bodies use the same evaluator. Two kernel families share one format:
- Fixed-n (Moon, Jupiter, Saturn, Uranus, Neptune, Pluto):
n_deg_per_day = 360 / P_sid - Free-n (Sun, Mercury, Venus, Mars):
n_deg_per_dayis learned once and frozen - Nodes (Rahu/Ketu): store Rahu; derive Ketu via
L_ketu = wrap360(L_rahu + 180)
4.1 What to load (universal manifest)
Schema (plain ASCII JSON; one file per body):
{
"planet": "Sun|Moon|Mercury|Venus|Mars|Jupiter|Saturn|Uranus|Neptune|Pluto|Rahu|Ketu",
"t0": "YYYY-MM-DD", // midpoint anchor used during fit
"P_sid": null, // days; present for fixed-n, null/omitted for free-n
"n_deg_per_day": 0.000000, // fixed-n: 360/P_sid ; free-n: learned slope
"P_syn": null, // optional, informational
"selected_model": "base|add_nE|add_3w|add_nE_3w|...",
"omegas": { // rad/day; include only keys you actually use
"w1": 0.0, "w2": 0.0, "w3": 0.0,
"wS": 0.0, "nE": 0.0
},
"beta": { // degrees
"a0": 0.000000, // intercept at t0
"c1": 0.0, "d1": 0.0, // for w1
"c2": 0.0, "d2": 0.0, // for w2
"c3": 0.0, "d3": 0.0, // for w3
"cS": 0.0, "dS": 0.0, // for wS
"cE": 0.0, "dE": 0.0 // for nE
},
"notes": "train/test ranges, sampling mode, gate policy, etc."
}
- Do not hand-edit numbers. The manifest is the single source of truth.
- Nodes: if you store only Rahu, compute Ketu at runtime as
L_ketu = wrap360(L_rahu + 180).
4.2 One-line evaluator (ASCII; identical for all bodies)
Daily timestamp convention: 05:30 IST (date-based evaluation; keep this choice consistent end-to-end)
Inputs: D := calendar_date, M := manifest
Base-linear evaluator (harmonics disabled).
t := days_since(D, M.t0)
y := M.beta.a0 + M.n_deg_per_day * t
L_hat_deg := wrap360(y)
Harmonic scaffold (general form; optional).
for each omega_k present:
y := y + (c_k)*sin(omega_k*t) + (d_k)*cos(omega_k*t)
L_hat_deg := wrap360(y)
Utility. wrap360(x) := x - 360 * floor(x / 360)
Family note. For free-n bodies the learned slope lives in n_deg_per_day; no extra linear term is introduced at runtime.
4.3 Minimal Python (drop-in, planet-agnostic)
# plain-ASCII; Python 3.8+
import json, math, sys, datetime as dt
def wrap360(x):
return x - 360.0 * math.floor(x / 360.0)
def days_since(date_obj, t0_date):
# Daily evaluation at 05:30 IST by convention; date-only index is sufficient
return (date_obj - t0_date).days
def eval_angle_deg(man, date_obj):
t0 = dt.date.fromisoformat(man["t0"])
t = days_since(date_obj, t0)
bet = man.get("beta", {})
omg = man.get("omegas", {})
# base-linear track
y = float(bet.get("a0", 0.0)) + float(man["n_deg_per_day"]) * t
# generic harmonic scaffold (keys optional)
keymap = {
"w1": ("c1","d1"),
"w2": ("c2","d2"),
"w3": ("c3","d3"),
"wS": ("cS","dS"),
"nE": ("cE","dE"),
}
for k, (ck_key, dk_key) in keymap.items():
if k in omg:
w = float(omg[k])
ck = float(bet.get(ck_key, 0.0))
dk = float(bet.get(dk_key, 0.0))
y += ck * math.sin(w * t) + dk * math.cos(w * t)
return wrap360(y)
if __name__ == "__main__":
# Usage: python eval.py manifest.json 2035-10-03
man = json.load(open(sys.argv[1], "r", encoding="utf-8"))
D = dt.date.fromisoformat(sys.argv[2])
print(f"{eval_angle_deg(man, D):.6f}")
Ketu from Rahu: after evaluating L_rahu, compute L_ketu = wrap360(L_rahu + 180).
4.4 Quick validation probes (suggested)
- Ingress clocking: evaluate unwrapped
y(t), locate linear crossings at every30 deg, compare to your reference grid. - Stations: central-difference speed on unwrapped
y; find local minima; optionally refine with a quadratic fit around each candidate.
4.5 Invariants (sanity)
- No drift of
n. Fixed-n bodies usen = 360 / P_sid; free-n use one learned slope frozen in the manifest. - Parsimony. Extras are admitted only with
DeltaBIC >= 6and lower event-aware loss. - Wrap discipline. Wrap for display; unwrap only for OLS and event timing.
- Prev-day cusps. Record ingresses on the previous day after year-boundary normalization.
- Bounded snap. When aligning event dates, use at most
+-1 dayto resolve a clear neighbor mismatch. - Node identity. Always enforce
Ketu = wrap360(Rahu + 180). - Determinism. Outputs are a pure function of
(manifest, date); no network or hidden state.
4.6 Body notes (runtime)
- Sun / Mercury / Venus / Mars (free-n): use the stored
n_deg_per_day. - Moon (fixed-n): fast body; prioritize cusp distance and
30 degcrossing timing. - Jupiter / Saturn / Uranus / Neptune / Pluto (fixed-n): slow carriers; rely on synodic plus slow-sidereal terms (enable harmonics only if they passed the gate).
- Rahu / Ketu: maintain symmetry with
L_ketu = wrap360(L_rahu + 180); you may store only Rahu’s manifest.
Navigation
Back: SSM-JTK – Results to Date – Benchmark cross-checks (observation-only; optional) (3.7)
Next: SSM-JTK – CSV-only Scorecard How-To (5)
Directory of Pages
SSM-JTK – Series index & links
Disclaimer
The contents in the Shunyaya Symbolic Mathematics Jyotish Transit Kernel (SSM-JTK) materials are research/observation material. They are not astrological advice, not a scientific ephemeris, and not operational guidance. Do not use for safety-critical, medical, legal, or financial decisions. Use at your own discretion; no warranties are provided; results depend on correct implementation and inputs.
Explore Further
https://github.com/OMPSHUN