Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a788cdc
feat(catalog): add observable asteroids
mrosseel Jul 15, 2026
b95cf39
merge: deepchart into observable-asteroids (cedar shmem restart-recov…
mrosseel Jul 16, 2026
2692406
fix(web): accept comma or period decimal separator in location entry
mrosseel Jul 16, 2026
8090ec9
feat(ui): software update screen polish
mrosseel Jul 16, 2026
fdac4d1
merge: sqm-fix into observable-asteroids (wing-boundary floor, band o…
mrosseel Jul 16, 2026
190ac91
chore: retrigger build (built_at manifest stamp)
mrosseel Jul 16, 2026
6d009dc
chore: retrigger build (built_at manifest stamp)
mrosseel Jul 16, 2026
b4088f9
merge: sqm-fix into observable-asteroids (SQM rotation fix, growth-cu…
mrosseel Jul 17, 2026
fbe42b9
merge: sqm-fix into observable-asteroids (imx296 band offset refit)
mrosseel Jul 17, 2026
40a4e6d
merge: sqm-fix into observable-asteroids (exposure-invariant zero poi…
mrosseel Jul 17, 2026
0e40dce
refactor(sqm): port orthogonal measurement fixes onto deepchart
mrosseel Jul 17, 2026
6c886bc
feat(sqm): black-level tracking + cloud/dew guard
mrosseel Jul 17, 2026
be8b7b6
merge: sqm-fix into observable-asteroids (radiometer-first SQM + upst…
mrosseel Jul 17, 2026
1e834f9
merge: nixos into observable-asteroids
mrosseel Jul 18, 2026
d7823a0
fix(test): match test_radec_entry to current radec_entry API
mrosseel Jul 18, 2026
7ca99df
merge: optical-black SQM into observable-asteroids
mrosseel Jul 19, 2026
20267a1
merge: IMX462 dark-sky correction into observable-asteroids
mrosseel Jul 21, 2026
6d68b5a
merge: sync deepchart after IMX462 SQM integration
mrosseel Jul 21, 2026
2d875f9
ci(nixos): ARM-primary testable build (ubuntu-24.04-arm first, pi5 la…
mrosseel Jul 21, 2026
fa09f51
feat(telemetry): section checklist, size cap, recomputable radio event
mrosseel Jul 22, 2026
5e950cb
merge: sync deepchart (gaia charts + SQM/airglow) into observable-ast…
mrosseel Jul 23, 2026
846fd2e
merge: deepchart (upstream/main sync) into observable-asteroids
mrosseel Jul 24, 2026
ea6c0c2
merge: deepchart (upstream sync, full-sensor sweeps) into observable-…
mrosseel Jul 29, 2026
67b8cd2
merge: deepchart (CI manifest-checkout fix) into observable-asteroids
mrosseel Jul 29, 2026
79ea1e9
merge: current deepchart into observable-asteroids
mrosseel Aug 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion CONTEXT-MAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ PiFinder is a multi-process Raspberry Pi finder/plate-solver. These contexts eac
- **Bring-up ↛ `hardware_detect`**: unlike `main.py` and `splash.py`, bring-up does **not** derive its panel from the BQ25895 probe. Doing so would make a dead charger indistinguishable from a dead screen on exactly the boards it exists to diagnose.

Companion architecture docs live next to each `CONTEXT.md`:
- [`docs/ax/nixos.md`](./docs/ax/nixos.md)
- [`docs/ax/catalog.md`](./docs/ax/catalog.md)
- [`docs/ax/positioning.md`](./docs/ax/positioning.md)
- [`docs/ax/sqm.md`](./docs/ax/sqm.md)
Expand Down
4 changes: 3 additions & 1 deletion default_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"Str",
"PL",
"CM",
"MP",
"RDS"
],
"filter.object_types": [
Expand All @@ -52,7 +53,8 @@
"*",
"?",
"Pla",
"CM"
"CM",
"AS"
],
"filter.constellations": [
"And",
Expand Down
52 changes: 52 additions & 0 deletions docs/adr/0021-mpc-bright-asteroid-catalog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# MPC annual bright-minor-planet files for the asteroid catalog

PiFinder needs an asteroid subset small enough for a Raspberry Pi and useful to
visual observers. The complete MPCORB catalog is orders of magnitude larger
than the set that can become visually observable in a given year. An absolute
magnitude (`H`) cut is also insufficient: it can omit intrinsically faint
near-Earth asteroids during a bright close apparition.

The `MP` dynamic catalog uses the Minor Planet Center's annual
`Ephemerides/Bright/<year>/Soft00Bright.txt` file. It is already curated by
observing year, uses the standard MPCORB one-line format supported by the
pinned Skyfield release, contains numbered asteroids, and supplies the `H` and
`G` photometric parameters.

## Decisions

- Load the current year's file and opportunistically merge next year's once it
is published. A previous-year file remains a stale-data fallback around New
Year or during network failure. Duplicate asteroid numbers use the newest
packed element epoch. Because a Pi 4 has no RTC, source-year selection waits
for trustworthy GPS time; before that, the UI may identify an already stored
edition from its filename but never chooses a download year from wall time.
- The minor-planet number is the catalog sequence. Observation logs for virtual
objects are keyed by `(catalog, sequence)`, so `MP 4` must remain Vesta across
refreshes and restarts.
- Propagate the small element set locally in vectorized NumPy operations and
compute apparent magnitude with the IAU H-G phase law. Non-finite values and
objects fainter than the named magnitude-15 catalog safety limit are omitted;
the user's ordinary magnitude and altitude filters remain the observing
controls.
- For visible objects, search 550 days for the first upcoming
ecliptic-longitude opposition (or greatest elongation for an interior object)
and the peak magnitude associated with that apparition. Day zero is excluded
from “upcoming” so an event that just passed is not reported as the next one.
- Catalog source updates are transactional: bytes go to a temporary sibling,
are parsed and validated, and atomically replace the active file. The old
objects and their source edition remain visible during download or after failure.
A populated catalog shows a compact determinate or indeterminate progress bar.
- JPL SBDB is a documented replacement candidate if MPC retires the annual
file, not an automatic fallback. Supporting two unrelated runtime formats
would add failure modes without improving normal operation.
- Existing persisted Catalog and Type filters receive `MP` and `AS` through a
one-time config migration. Its marker ensures a later user choice to disable
asteroids remains authoritative.

## Consequences

Asteroid calculations stay bounded to a few hundred source rows, stable numbers
make jump-to and logging meaningful, and close NEO apparitions are retained
without downloading the full MPCORB database. Annual elements are two-body
propagated, so they do not claim Horizons-level precision; vectorized results
are regression-tested against Skyfield's per-object MPCORB orbit builder.
43 changes: 35 additions & 8 deletions docs/ax/catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ At a high level:
│ └─► re-filter
│
├── dynamic catalogs: PlanetCatalog (TimerMixin, every ~5 min)
│ CometCatalog (similar)
│ CometCatalog (downloaded MPC elements)
│ AsteroidCatalog (annual MPC bright subset)
│
└─► Catalogs object (single instance shared across the app)
│
Expand Down Expand Up @@ -64,7 +65,9 @@ displays. It's a dataclass that merges three things:
the object's listings counts, keyed by `object_id`; virtual objects
key on their own listing — see ADR 0020),
`last_filtered_time`/`last_filtered_result` (used by the filter
cache).
cache), and optional structured solar-system fields
(`earth_distance_au`, `sun_distance_au`, `opposition_date`,
`peak_magnitude`, `peak_date`).

Two `CompositeObject`s are equal iff their `object_id`s match. That
means the same underlying object referenced by multiple catalogs (e.g.
Expand Down Expand Up @@ -164,8 +167,8 @@ menu). It:
one `Catalog` per entry in `catalogs_info`, ending up with a
`Catalogs` instance even for catalogs that are currently empty (the
background loader will populate them later).
5. Appends two dynamic catalogs: `PlanetCatalog` (`PL`) and, via local
import, `CometCatalog`.
5. Appends three dynamic catalogs: `PlanetCatalog` (`PL`), `CometCatalog`
(`CM`), and `AsteroidCatalog` (`MP`).
6. Asserts `check_catalogs_sequences(...)`.

The reference to the background loader is also stashed on the
Expand Down Expand Up @@ -251,6 +254,12 @@ Two freshness triggers advance `dirty_time` besides the setters
and `UIObjectList.update()` polls it so an open list refreshes in
place.

Runtime position/catalog replacements call `invalidate_filter_cache()` for
the changed catalog and set a catalog-content-dirty flag. This wakes an open
list without advancing `dirty_time`, so unchanged catalogs retain their cached
results. Automatic list rebuilds reapply the current sort silently, reserving
the “Sorting by…” toast for a user-selected sort.

### 4.2 Altitude requires GPS

`calc_fast_aa(shared_state)` builds a `FastAltAz` from the current
Expand Down Expand Up @@ -334,10 +343,28 @@ A `Catalog` subclass that:
### 6.2 `CometCatalog`

Imported locally in `CatalogBuilder.build()` to avoid a circular
import. Same general pattern: dynamic, status-aware, registered as a
regular `Catalog` in the `Catalogs` collection.
import. It downloads MPC comet elements transactionally and keeps the active
objects visible while a replacement downloads. `CatalogStatus` carries known
percentage progress or `None` for an indeterminate progress bar. Successful
downloads trigger a full recalculation; failed downloads leave both the old
objects and their displayed source age intact.

### 6.3 `AsteroidCatalog`

The `MP` catalog reads MPC's annual `Soft00Bright.txt` observing subset (ADR
0021). Its catalog listing sequence is the stable numbered minor planet, while
its negative object ID remains session-minted like every virtual object.
Vectorized propagation supplies J2000 RA/Dec, Earth/Sun distance, and an IAU
H-G apparent magnitude. Objects above the magnitude-15 safety limit are omitted;
ordinary catalog filters can impose a brighter user limit.

Visible objects are enriched across the next 550 days with the first upcoming
ecliptic-longitude opposition (or greatest elongation) plus the peak magnitude
and date for that apparition. These structured values drive the Asteroids list's
Brightest, Distance, and Opposition sorts; description text is presentation
only.

### 6.3 `TimerMixin`
### 6.4 `TimerMixin`

Provides `start_timer()` / `stop()` plus a `time_delay_seconds` that can
be either an int or a callable. Each fire schedules itself again via
Expand All @@ -346,7 +373,7 @@ catalog method does not run on the timer thread directly — useful
because `do_timed_task` can take a noticeable amount of time
(`sf_utils.calc_planets` is not cheap).

### 6.4 `VirtualIDManager`
### 6.5 `VirtualIDManager`

Static helper that hands out monotonically decreasing `object_id`
values for non-DB objects. Held under `virtual_id_lock` and persists
Expand Down
20 changes: 18 additions & 2 deletions docs/ax/catalog/CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The Catalog context owns runtime loading, filtering, searching and display of as
### Identity

**Catalog code**:
Short string identifier for a catalog as a whole — `"M"`, `"NGC"`, `"IC"`, `"WDS"`, `"PL"` (planets). Drives DB queries and the UI designator. Its readable sibling is the **catalog display name** ("Collinder" for code `"Cr"`).
Short string identifier for a catalog as a whole — `"M"`, `"NGC"`, `"IC"`, `"WDS"`, `"PL"` (planets), `"MP"` (asteroids). Drives DB queries and the UI designator. Its readable sibling is the **catalog display name** ("Collinder" for code `"Cr"`).
_Avoid_: catalog id, prefix; for the readable form say **catalog display name**, not "catalog name".

**Catalog display name**:
Expand Down Expand Up @@ -101,6 +101,10 @@ _Avoid_: logged (when speaking to users or in UI copy), seen.
Epoch timestamps driving the two filter cache layers. `mark_dirty()` advances `filter.dirty_time`; an object's verdict is re-evaluated only when `obj.last_filtered_time < filter.dirty_time` (per-object layer), and a whole catalog skips its scan while `catalog.last_filtered > filter.dirty_time` (per-catalog layer). Beyond the parameter setters, dirty time also advances when an object is logged with an observed criterion active (`Catalogs.mark_logged`) and when staleness is promoted (see **Stale**).
_Avoid_: invalidation, cache key.

**Catalog content dirty**:
A wake-up flag for runtime object changes under unchanged filter criteria. The changed catalog resets its own cached verdicts, then `mark_catalog_content_dirty()` makes open lists rebuild without advancing **Dirty time**.
_Avoid_: filter dirty (the criteria did not change), stale (time did not expire the verdict).

**Stale** (filter staleness):
Verdicts outdated by time passing rather than by a parameter change — only possible for time-sensitive criteria, today just altitude (the sky rotates ≤ 15°/hour). `CatalogFilter.is_stale()` reports it: altitude criterion active, alt/az available, and either verdicts older than `ALTITUDE_STALE_SECONDS` (600 s ≈ 2.5° of drift) or an alt/az fix arrived after verdicts were computed without one. Staleness never invalidates by itself; `Catalogs.filter_catalogs()` promotes it to a dirty bump. See [ADR 0020](../../adr/0020-filter-freshness-staleness-promotion.md).
_Avoid_: dirty (that's a parameter change), expired.
Expand Down Expand Up @@ -138,7 +142,7 @@ _Avoid_: load-done event, ready signal.
### Dynamic catalogs

**Dynamic catalog**:
A `Catalog` whose objects are computed at runtime rather than loaded from `objects.db`. Currently `PlanetCatalog` and `CometCatalog`.
A `Catalog` whose objects are computed at runtime rather than loaded from `objects.db`. Currently `PlanetCatalog`, `CometCatalog`, and `AsteroidCatalog`.
_Avoid_: live catalog, computed catalog.

**PlanetCatalog**:
Expand All @@ -149,6 +153,18 @@ _Avoid_: planets, ephemeris (those are more general).
Comet equivalent of `PlanetCatalog`. Imported locally inside `CatalogBuilder.build()` to break a circular import.
_Avoid_: comets.

**AsteroidCatalog**:
The `"MP"` dynamic catalog. Loads the MPC annual bright-minor-planet subset, uses the numbered minor planet as its stable **Sequence**, computes current position and H-G apparent magnitude, and enriches visible objects with distance, opposition/greatest-elongation, and apparition-peak data. Source replacement is atomic; populated objects remain available during download.
_Avoid_: minor planets (when the concrete catalog class is meant), `Ast` (that code means asterism).

**Catalog data age**:
Whole days since the active downloaded elements file's server timestamp. Used for frequently refreshed sources such as comets. During refresh this continues to describe the objects actually on screen; it changes only after a validated file replaces the active source. Annual asteroid data instead shows its compact MPC edition label, because a large day count is normal rather than a stale-data warning.
_Avoid_: catalog age (ambiguous with the runtime `Catalog` object).

**Download progress**:
The `CatalogStatus.data["progress"]` percentage for a downloaded dynamic catalog. `None` means the response has no known Content-Length and the UI draws an indeterminate bar. Progress does not imply the old objects have been removed; they stay usable until recalculation succeeds.
_Avoid_: loading progress (deferred database catalog loading is a different lifecycle).

**TimerMixin**:
Composition helper providing self-rescheduling periodic timers. `time_delay_seconds` may be a callable for adaptive delays. Updates run in their own thread, not on the timer thread.
_Avoid_: scheduler, ticker.
Expand Down
1 change: 1 addition & 0 deletions docs/ax/catalog/obslist-formats/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ like `"Galaxy"`. The canonical set is defined by `OBJ_TYPES` in
| `PN` | Planetary nebula | | `Kt` | Knot |
| `DN` | Dark nebula | | `Pla` | Planet |
| `C+N` | Cluster + nebula | | `CM` | Comet |
| `AS` | Asteroid | | | |
| | | | `?` | Unknown |

A code drives two things: the symbol drawn next to the object, and the **Type**
Expand Down
Binary file added markers/mrk_asteroid.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading