From 5e5588fddb904ea6bfc8a736b4bbec0f13fa8a11 Mon Sep 17 00:00:00 2001 From: Ryan Malloy Date: Tue, 17 Feb 2026 21:51:26 -0700 Subject: [PATCH] Update docs for v0.7.0: types, operators, test count, performance framing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - types.mdx: "seven" → "seven base types + one SQL composite", add observer_window section with field table and usage example - operators-gist.mdx: "three operators" → "four operators", reframe SP-GiST performance as scalability feature (honest about seqscan being faster at 14k catalog size, index helps at 100k+) - installation.mdx: "14 test suites" → "15 test suites", list all suites including od_fit, spgist_tle, vallado_518 - design-principles.mdx: clarify observer_window is SQL composite (variable-length, query-time only), base types still STORAGE=plain - pass-prediction.mdx: lead with operator value (80-90% elimination), SP-GiST index framed as optional for large catalogs --- .../docs/architecture/design-principles.mdx | 2 +- .../docs/getting-started/installation.mdx | 4 +- .../content/docs/guides/pass-prediction.mdx | 2 +- .../content/docs/reference/operators-gist.mdx | 6 ++- docs/src/content/docs/reference/types.mdx | 39 ++++++++++++++++++- 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/docs/src/content/docs/architecture/design-principles.mdx b/docs/src/content/docs/architecture/design-principles.mdx index 651b569..8c065ac 100644 --- a/docs/src/content/docs/architecture/design-principles.mdx +++ b/docs/src/content/docs/architecture/design-principles.mdx @@ -104,7 +104,7 @@ For v0.1.0/v0.2.0 functions, there are no file-scope variables, no static locals ### Fixed-size types -All seven pg_orrery types use `STORAGE = plain` and fixed `INTERNALLENGTH`. No TOAST, no detoasting, no variable-length headers. The `tle` type is exactly 112 bytes. Direct pointer access via `PG_GETARG_POINTER(n)` --- no copies, no allocations on read. +All seven pg_orrery base types use `STORAGE = plain` and fixed `INTERNALLENGTH`. No TOAST, no detoasting, no variable-length headers. The `tle` type is exactly 112 bytes. Direct pointer access via `PG_GETARG_POINTER(n)` --- no copies, no allocations on read. The eighth type, `observer_window`, is a SQL composite used only as a query-time parameter --- it is never stored in table columns. ### Deterministic memory diff --git a/docs/src/content/docs/getting-started/installation.mdx b/docs/src/content/docs/getting-started/installation.mdx index 155a245..896ac91 100644 --- a/docs/src/content/docs/getting-started/installation.mdx +++ b/docs/src/content/docs/getting-started/installation.mdx @@ -97,13 +97,13 @@ import { Tabs, TabItem, Steps, Aside } from "@astrojs/starlight/components"; ## Running the test suite -If building from source, the regression tests verify all functions across 14 test suites: +If building from source, the regression tests verify all functions across 15 test suites: ```bash make installcheck PG_CONFIG=/usr/bin/pg_config ``` -This runs the tests listed in the `REGRESS` variable: TLE parsing, SGP4 propagation, coordinate transforms, pass prediction, GiST indexing, convenience functions, star observation, Keplerian propagation, planet observation, moon observation, Lambert transfers, and DE ephemeris. +This runs the tests listed in the `REGRESS` variable: TLE parsing, SGP4 propagation, coordinate transforms, pass prediction, GiST indexing, convenience functions, star observation, Keplerian propagation, planet observation, moon observation, Lambert transfers, DE ephemeris, orbit determination, SP-GiST visibility index, and the 518 Vallado test vectors. ## Upgrading diff --git a/docs/src/content/docs/guides/pass-prediction.mdx b/docs/src/content/docs/guides/pass-prediction.mdx index f3e8eef..2bdbb08 100644 --- a/docs/src/content/docs/guides/pass-prediction.mdx +++ b/docs/src/content/docs/guides/pass-prediction.mdx @@ -6,7 +6,7 @@ sidebar: import { Steps, Aside, Tabs, TabItem } from "@astrojs/starlight/components"; -Satellite pass prediction answers a deceptively simple question: "which satellites will fly over me tonight?" The brute-force approach -- propagating every object in a 30,000-satellite catalog with SGP4 at 10-second intervals over a 24-hour window -- requires billions of floating-point operations. pg_orrery solves this with an SP-GiST index on the `tle` type that prunes by orbital geometry before any propagation runs, reducing the candidate set to a handful of objects that could plausibly be visible. +Satellite pass prediction answers a deceptively simple question: "which satellites will fly over me tonight?" The brute-force approach -- propagating every object in a 30,000-satellite catalog with SGP4 at 10-second intervals over a 24-hour window -- requires billions of floating-point operations. pg_orrery solves this with the `&?` visibility cone operator, which applies three geometric filters (altitude, inclination, RAAN) to eliminate 80-90% of candidates without any SGP4 propagation. An optional SP-GiST index provides tree-level pruning for large catalogs. ## How you do it today diff --git a/docs/src/content/docs/reference/operators-gist.mdx b/docs/src/content/docs/reference/operators-gist.mdx index dd52a11..f8367c2 100644 --- a/docs/src/content/docs/reference/operators-gist.mdx +++ b/docs/src/content/docs/reference/operators-gist.mdx @@ -6,7 +6,7 @@ sidebar: import { Aside, Tabs, TabItem } from "@astrojs/starlight/components"; -pg_orrery defines three operators on the `tle` type and two operator classes (GiST and SP-GiST) that enable indexed satellite queries over large catalogs. The GiST index accelerates conjunction screening (orbit-to-orbit overlap). The SP-GiST index accelerates pass prediction (observer-to-orbit visibility). +pg_orrery defines four operators on the `tle` type and two operator classes (GiST and SP-GiST) that enable indexed satellite queries over large catalogs. The GiST index accelerates conjunction screening (orbit-to-orbit overlap). The SP-GiST index accelerates pass prediction (observer-to-orbit visibility). --- @@ -288,7 +288,9 @@ During the index scan, inner nodes are pruned by altitude band (level 0) and inc ### Performance -The SP-GiST index is most effective for: +The `&?` operator eliminates 80-90% of a satellite catalog without SGP4 propagation --- this is the primary value, regardless of whether a sequential scan or index scan evaluates it. At typical catalog sizes (10-30k objects), the operator evaluates the full catalog in under 10 ms, and PostgreSQL's query planner may choose a sequential scan over the index. + +The SP-GiST index becomes advantageous at larger catalog sizes (100k+ objects) where tree-level pruning avoids examining individual TLEs in entire subtrees. The index is most effective for: - **Short query windows** (1-6 hours): The RAAN filter aggressively eliminates satellites whose orbital plane is not currently aligned with the observer - **Mid-latitude observers** (30-60 degrees): The inclination filter eliminates equatorial and low-inclination satellites diff --git a/docs/src/content/docs/reference/types.mdx b/docs/src/content/docs/reference/types.mdx index d81797a..42255a8 100644 --- a/docs/src/content/docs/reference/types.mdx +++ b/docs/src/content/docs/reference/types.mdx @@ -6,7 +6,7 @@ sidebar: import { Aside, Tabs, TabItem } from "@astrojs/starlight/components"; -pg_orrery defines seven composite types that represent the core data structures of orbital mechanics. Each type has a fixed on-disk size, a text I/O format for readability, and accessor functions for extracting individual fields. +pg_orrery defines seven fixed-size base types and one SQL composite type that represent the core data structures of orbital mechanics. Each base type has a fixed on-disk size, a text I/O format for readability, and accessor functions for extracting individual fields. ## tle @@ -267,3 +267,40 @@ SELECT body_id, FROM generate_series(1, 8) AS body_id, planet_heliocentric(body_id, now()) AS h; ``` + +--- + +## observer_window + +**Type:** SQL composite (variable-length) + +A query-time parameter that defines a ground observer's visibility window. Unlike the seven base types above, `observer_window` is a SQL composite type --- it is not designed for table storage, but as an argument to the `&?` visibility cone operator. + +### Fields + +| Field | Type | Description | +|-------|------|-------------| +| `obs` | `observer` | Ground location (latitude, longitude, altitude) | +| `t_start` | `timestamptz` | Start of observation window | +| `t_end` | `timestamptz` | End of observation window | +| `min_el` | `float8` | Minimum elevation angle in degrees | + +### Construction + +Construct with `ROW(...)::observer_window` syntax: + +```sql +-- Eagle, Idaho: 6-hour window, 10 deg minimum elevation +SELECT tle +FROM catalog +WHERE tle &? ROW( + observer('43.6977N 116.3535W 760m'), + '2024-01-01 01:00:00+00'::timestamptz, + '2024-01-01 07:00:00+00'::timestamptz, + 10.0 +)::observer_window; +``` + +