COOLJAPAN
← All posts

OxiEphemeris 0.1.1 Released — Charts Become Linked Open Data, and Python/WASM Join the CLI on One Compute Path

OxiEphemeris 0.1.1 adds a full RDF/SKOS/PROV-O astrology vocabulary with a live SPARQL endpoint, new Python and WebAssembly bindings sharing one compute facade with the CLI, and a deeper astrology layer — ayanamshas, dignities, declinations, Arabic Parts, synastry. The sovereign ephemeris layer for COOLJAPAN.

release oxiephemeris astrology ephemeris rdf sparql linked-open-data pure-rust wasm python

Every astrology library can tell you the Sun is in Scorpio. As of 0.1.1, OxiEphemeris can also tell a SPARQL query that Scorpio is a skos:Concept with a Wikidata QID — and hand that same chart to Python or a browser tab without recomputing a single degree.

Today we released OxiEphemeris 0.1.1 — a Linked Open Data release: a full RDF/SKOS/PROV-O astrology vocabulary with a SPARQL store and HTTP endpoint, a UI-free chart-computation facade shared bit-for-bit by the CLI and new Python and WebAssembly bindings, and a substantially deeper astrology layer — sidereal ayanamshas, essential dignities, declinations, Arabic Parts, midpoints, and synastry cross-aspects.

No C. No Fortran. No libswe, no pyswisseph FFI at runtime — the README’s 960-case Swiss Ephemeris comparison was run once, offline, against a binary wheel, with its results checked into committed fixture files; pyswisseph itself is never linked into the build. No RocksDB either: the new SPARQL store builds its oxigraph dependency with default-features = false, which drops the C++ storage engine entirely and leaves a pure-Rust in-memory store. The whole workspace runs unsafe_code = "forbid" at the lint level, with zero .unwrap()/.expect() in library code (clippy::unwrap_used/expect_used denied workspace-wide). It compiles to a single static binary — or to WebAssembly, running a full chart computation entirely offline in a browser tab — and runs everywhere Rust runs.

Why OxiEphemeris 0.1.1 is a game changer

The incumbents in this space all share the same shape of compromise:

OxiEphemeris 0.1.1 ends all of that:

Technical Deep Dive: from a DE kernel to a dereferenceable IRI

  1. Time and ephemeris (oxiephemeris-core, oxiephemeris-de) — the unchanged foundation, plus one new hook. Two-part JulianDate (hi/lo) arithmetic, proleptic Gregorian/Julian calendar conversions, an embedded UTC leap-second table, the Fairhead–Bretagnon TT↔TDB series, and the 15-piece Espenak–Meeus ΔT polynomial have shipped since 0.1.0. oxiephemeris-de reads JPL’s classic DE440/DE441 binary format and the SPK/DAF .bsp container (segment types 2, 3, and 13) via Chebyshev interpolation over Clenshaw recurrence. 0.1.1 adds exactly one new primitive here: DeFile::de_number(), exposing the DE header’s NUMDE field — added purely so the RDF layer three levels up can record which ephemeris a chart’s provenance graph actually came from.
  2. Frames and astrology (oxiephemeris-bodies, oxiephemeris-astro) — where 0.1.1’s real depth lands. oxiephemeris-bodies supplies IAU 2006 frame bias/precession (Fukushima–Williams angles), the full IAU 2000A_R06 nutation series with a 2000B-class fast path, and the apparent-place pipeline (light-time iteration, aberration, optional light deflection) — also since 0.1.0. oxiephemeris-astro is where 0.1.1’s new modules live: ayanamsha (five sidereal systems — Fagan/Bradley, Lahiri, Krishnamurti, Raman, J2000-zero, plus a custom-anchor mode — propagated from cited epochs via the IAU 2006 P03 general-precession polynomial), dignities (domicile/exaltation/triplicity/term/face rulers, detriment/fall/peregrine, a configurable RulershipScheme), declination (ecliptic→equatorial conversion, antiscia, and parallel/contraparallel/out-of-bounds classification, cross-checked against an independent rotation-based oracle), parts (Sect-aware Arabic Parts), midpoints, and synastry (CrossHit, for_each_cross_aspect — the engine behind the CLI’s new synastry/transit/progress/composite commands).
  3. The chart facade and its three front ends (oxiephemeris-chart, oxiephemeris-cli, oxiephemeris-py, oxiephemeris-wasm) — entirely new in 0.1.1. oxiephemeris-chart is the UI-free compute layer: natal_chart, synastry, transit, progression, and composite, each returning a ChartResource/ChartComparison/CompositeChartResource that renders to JSON or RDF through chart_to_json/chart_to_rdf and friends, with its own dependency-free ISO 8601 parser instead of pulling in chrono. oxiephemeris-cli’s chart/houses/synastry/transit/progress/composite commands are now thin renderers over this facade — epoch resolution moved out of the CLI’s own code and into oxiephemeris_chart::epoch — and the new oxiephemeris-py (PyO3, abi3-py38) and oxiephemeris-wasm (wasm-bindgen) crates call the exact same functions underneath.
  4. Linked Open Data (oxiephemeris-rdf, oxiephemeris-lod) — the release’s headline layer. oxiephemeris-rdf defines the oxa:/oxc:/oxs: vocabulary plus PROV-O provenance and canonical, byte-stable Turtle/N-Triples serialization — triples are sorted before every write, so re-emitting the same chart never produces a spurious diff. oxiephemeris-lod sits above it: FileBackedStore is an in-memory oxigraph Store built with default-features = false (no RocksDB) plus whole-file N-Quads persistence via atomic rename; endpoint::handle implements the SPARQL 1.1 Protocol as a pure function, testable without ever binding a socket; and oxieph-sparqld is the thin binary wiring both to oxhttp.

Getting Started

cargo install oxiephemeris-cli

Two commands, zero and one file dependency respectively:

# The oxa:/oxc:/oxs: RDF vocabulary itself — no DE kernel needed.
oxieph vocab --part ontology --format turtle

# Synastry: cross-aspects between two natal charts (new in 0.1.1).
oxieph synastry --date-a 1970-01-01T00:00:00 --lat-a 51.4779 --lon-a 0.0 \
  --date-b 2000-01-01T12:00:00 --lat-b 48.8566 --lon-b 2.3522 \
  --de data/de440/linux_p1550p2650.440

From Rust, the same compute path via oxiephemeris-chart:

cargo add oxiephemeris-chart oxiephemeris-de
use oxiephemeris_chart::{chart_to_json, chart_to_rdf, natal_chart, NatalSpec, RdfFormat};
use oxiephemeris_de::DeFile;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let bytes = std::fs::read("data/de440/linux_p1550p2650.440")?;
    let de = DeFile::parse(&bytes)?;

    // The Unix epoch at the Royal Observatory, Greenwich — 0.1.1's
    // canonical reference chart, used throughout the tests and docs.
    let spec = NatalSpec {
        date: "1970-01-01T00:00:00Z".to_owned(),
        lat: 51.4779,
        lon: 0.0,
        alt: 0.0,
        dut1: 0.0,
        cal: "gregorian".to_owned(),
        system: "placidus".to_owned(),
        sidereal: None,
        rulership: "traditional".to_owned(),
    };
    let chart = natal_chart(&de, &spec.into_request()?)?;

    let json = chart_to_json(&chart)?;                                   // stable JSON schema
    let turtle = chart_to_rdf(&chart, None, None, RdfFormat::Turtle)?;    // RDF, default base IRI
    println!("{json}\n{turtle}");
    Ok(())
}

The Python and WebAssembly bindings are new source in this release but aren’t packaged for PyPI/npm yet — build them from source. Python, via maturin:

cd crates/oxiephemeris-py && maturin develop
import oxiephemeris as oxi

with open("de440/linux_p1550p2650.440", "rb") as f:
    de = f.read()

chart = oxi.natal(de, "1970-01-01T00:00:00Z", lat=51.4779, lon=0.0)
sun = next(b for b in chart["bodies"] if b["body"] == "Sun")
print(sun["sign"], round(sun["sign_degrees"], 2), "house", sun["house"])
# -> Capricorn 10.16 house 4

WebAssembly, via wasm-pack (the www/index.html demo page in the crate is a self-contained example):

wasm-pack build crates/oxiephemeris-wasm --target web --out-dir pkg

What’s New in 0.1.1

Tips

This is the foundation

OxiEphemeris is COOLJAPAN’s astrology/ephemeris and Linked-Open-Data computation layer — a clean-room JPL DE/SPK reader, an IAU 2006/2000A frame pipeline, a full astrology layer, and now an RDF vocabulary with a SPARQL endpoint, all computed once and reused everywhere. It’s still a young, standalone project — 0.1.0 shipped one day before this release, on 2026-07-10 — and honestly, there’s no ecosystem consumer list to report yet: a scan of every other COOLJAPAN project’s Cargo.toml turns up nothing depending on it so far. Its own dependency graph also reaches outside COOLJAPAN for one piece: the RDF/SPARQL stack (oxrdf, oxttl, oxigraph, oxhttp) is the independent, third-party Oxigraph project — it shares the “oxi” prefix by coincidence, not affiliation, and is always built with default-features = false so it never pulls in RocksDB.

One real thread already connects OxiEphemeris to the rest of the stack, though: the live public SPARQL endpoint at sparql.cooljapan.tech doesn’t run oxiephemeris-lod’s own oxieph-sparqld binary at all — it’s served by OxiRS, COOLJAPAN’s own SPARQL engine, behind CloudFlare, preloaded with OxiEphemeris’s oxa:/oxc:/oxs: vocabulary. oxieph-sparqld, built on the third-party oxigraph, remains the self-hostable alternative for anyone who wants to run their own instance instead of querying the shared one.

Repository: https://github.com/cool-japan/oxiephemeris

Star the repo if you want an ephemeris engine you can read start to finish, check against JPL’s own test vectors, and query with SPARQL instead of scraping stdout.

The era of ephemeris software that’s either a black-box C core with a license negotiation attached, or a browser reimplementation with its own separate bugs, is over. Pure Rust astrology — clean-room, verified against independent oracles, and now queryable — is here, fast, safe, and sovereign.

KitaSan at COOLJAPAN OÜ
July 11, 2026

↑ Back to all posts