Astrophotography
Tenrankai has first-class support for astrophotography galleries, powered by the seiza plate-solving library. Point it at a few catalog files and your images gain an exact sky solution: labeled deep-sky objects, named stars, live supernova markers, and comets and asteroids placed where they actually were on the night you pressed the shutter.
Everything here is optional. Without an [astro] section, Tenrankai behaves
exactly as it always has.
What You Get
- Plate solving — a real WCS is fitted from the star field itself, not guessed from metadata. Solutions are persisted next to the image.
- Blind solving — images with no coordinates at all are solved from the star field alone, using a whole-sky pattern index.
- Object overlays — labeled ellipses for deep-sky objects (NGC/IC/Messier, Sharpless, Barnard) and tick marks for named stars, oriented to the object’s true position angle, with per-catalog visibility toggles.
- Transient markers — supernovae from a catalog you refresh on a cron, scoped to each image’s capture date.
- Comets and asteroids — positions propagated to the moment of capture, drawn with oriented tails and motion trails.
- Sky maps — an all-sky chart with a crosshair on the target, which works from RA/Dec alone and needs no plate solution.
Overlays appear on the image detail page, inside zoomed and pinch-zoomed views, on gallery images embedded in posts, and on post hero images.
Getting the Catalogs
Tenrankai ships no catalogs and calls no external service at runtime — you supply the data files. The easy path is to fetch the prebuilt ones:
seiza download-data prebuilt --output /var/lib/tenrankai/astro
They’re also published directly at
downloads.seiza.fyi. If you’d
rather build your own from source catalogs, each file has a corresponding
seiza build-* command:
| File | Built with | Purpose |
|---|---|---|
| Star tiles | seiza build-data | Required. The reference star field everything is solved against. |
| Blind pattern index | seiza build-blind-index | Whole-sky patterns for solving images that carry no coordinates. |
| Object catalog | seiza build-data objects | Deep-sky objects and named stars to overlay. |
| Transient catalog | seiza build-data transients | Active supernovae (Rochester list). |
| Minor bodies | seiza build-data minor-bodies | Comet and asteroid orbital elements. |
No astrometry.net index files are involved, and there’s nothing to install at runtime — seiza is a library compiled into the binary.
The [astro] Block
Astro data files are configured once, in the bootstrap config.toml — not
per-gallery and not per-site. All sites share the catalogs.
[astro]
star_data = "/var/lib/tenrankai/astro/stars-deep-gaia17.bin" # Required
blind_index = "/var/lib/tenrankai/astro/blind-gaia16.idx" # Optional
object_data = "/var/lib/tenrankai/astro/objects.bin" # Optional
transient_data = "/var/lib/tenrankai/astro/transients.bin" # Optional
minor_body_data = "/var/lib/tenrankai/astro/minor-bodies.bin" # Optional
Every key is a filesystem path. star_data is the only required one — the rest
each switch on a capability, and omitting one simply means you don’t get it.
| Key | Required | Format | Purpose and behavior |
|---|---|---|---|
star_data | Yes | SEIZAST1 | The reference star tiles. If the file can’t be opened, plate solving is disabled entirely and the server logs a warning — the site still starts and serves normally. |
blind_index | No | SEIZABI1 | Prebuilt whole-sky pattern index for blind solving. Memory-mapped on first use. Without it, an index is built on demand from star_data covering only the bright tiers. See below. |
object_data | No | SEIZAOB1 | The objects to overlay. Without it, images still solve but nothing is drawn. Loaded once at startup — changing it needs a restart. |
transient_data | No | — | Supernovae and other transients. Reloaded automatically whenever the file’s mtime changes, so a cron can refresh it with no restart. |
minor_body_data | No | — | Comet and asteroid orbital elements. Also reloaded on mtime change. |
Omit the whole [astro] table and none of this exists: the astro API returns
404 and no toggles appear.
Unknown keys are rejected at startup, so a typo fails loudly rather than being silently ignored.
The Blind Pattern Index
blind_index is what lets Tenrankai solve an image that carries no
coordinates at all. It’s worth understanding the trade-off, because the
fallback is quietly limited.
With blind_index set, the file is memory-mapped on first use — a fraction
of a second, regardless of size. The index carries its own magnitude limit and
pattern extent, and the solver honors them, so a deep index can solve small,
fine-scale fields.
Without it, seiza builds an index from star_data on the first blind solve.
That runtime build only ever covers the bright tiers (roughly G ≤ 11.8),
because building the deep tiers over a large catalog costs minutes and
gigabytes. The practical consequence: wide fields still blind-solve, but
small, fine-scale fields never will. If blind solving mysteriously fails on
your longer focal lengths, this is why.
The index must be built from the same catalog as star_data. Tenrankai
checks this at load and logs a warning when the two are far apart:
astro: blind index blind-gaia16.idx was built from 4200000 stars
but star_data has 91000000; blind solves may fail
If the file is missing or unreadable, Tenrankai warns and falls back to the on-demand build rather than failing — so a bad path degrades blind solving instead of taking the site down.
There are no solver tuning knobs. The scale ladder (roughly 0.11–5.6 arcsec/pixel), search radius, detection limits, and magnitude cutoffs are internal constants chosen to cover typical amateur setups.
Marking Astronomical Folders
Add astro = true to a folder’s _folder.md to declare that everything in it
is an astronomical image. Subfolders inherit the flag.
+++
title = "Deep Sky"
description = "Narrowband and broadband deep-sky imaging"
astro = true
+++
This is what permits blind solving — solving an image that carries no coordinates at all. Without the flag, Tenrankai will not blind-solve arbitrary photos.
How an Image Gets Solved
An image is eligible for solving when either:
-
It has an RA/Dec hint. The
raanddecfields in the image’s markdown sidecar give the solver a starting point. Coordinates parse from sexagesimal hour or degree forms as well as plain decimal degrees:+++ title = "Orion Nebula" telescope = "Celestron NexStar 8SE" mount = "EQ6-R Pro" filters = "Ha, OIII, SII" total_exposure_time = 12.5 ra = "05h 34m 32s" dec = "+22° 00' 52\"" +++Note that RA/Dec come from the sidecar, not from EXIF.
-
It has no hint, but it’s clearly an astro image — either the sidecar has a
telescopefield, or the folder (or an ancestor) is markedastro = true. Tenrankai then falls back to a blind solve, searching the star field without a starting position.
Anything else is skipped. Your landscape photos will never be blind-solved.
Solving happens on demand, once per image. The first hinted solve typically
takes a few seconds. Blind solves additionally need a pattern index: with
blind_index configured it’s memory-mapped almost instantly, and without it one
is built from star_data on first use — a slower path that only covers bright
stars, and won’t solve small fields. Either way the index is loaded once per
process and reused.
Failed solves are remembered only in memory, so restarting the server gives them another chance — useful after you improve a catalog.
Persisted Solutions
A successful solution is written to the app-managed TOML sidecar beside the
image — beach.jpg gets beach.toml. Your hand-written beach.jpg.md is
never rewritten.
The sidecar stores the fitted WCS (crval, crpix, cd), quality metrics
(matched_stars, rms_arcsec), the overlay objects with their pixel positions
and ellipse geometry, and an objects_version stamp identifying the catalog
that produced them.
Because the WCS is persisted, later work is cheap: when the object catalog changes, objects are reprojected through the stored solution in milliseconds rather than re-solved.
Transients, comets, and asteroids are never persisted. They’re projected live on every request, because discoveries keep arriving and minor bodies keep moving.
Keeping Catalogs Fresh
The transient and minor-body files are re-read whenever their mtime changes, so a cron job can keep them current without restarting the server:
# Refresh nightly
0 4 * * * seiza build-data transients -o /var/lib/tenrankai/astro/transients.seiza
30 4 * * * seiza build-data minor-bodies -o /var/lib/tenrankai/astro/minor-bodies.seiza
The star and object catalogs are loaded once at startup. After replacing an object catalog, restart Tenrankai — then either let overlays reproject lazily on first view, or regenerate them in bulk.
Regenerating Overlays
When the object catalog changes, persisted overlays can be reprojected in one pass:
# Reproject a gallery's overlays against the current object catalog
tenrankai astro regen -g main
# A specific site (defaults to "default")
tenrankai astro regen -g main -s clients
# Report what would change without writing anything
tenrankai astro regen -g main --dry-run
This walks the gallery’s persisted sidecars, skips any whose objects_version
already matches the loaded catalog, and reprojects the rest through their stored
WCS — no re-solving. It prints the object-count change per image and a summary
of how many solutions were refreshed versus already current.
The same reprojection happens lazily whenever a stale image is viewed, so
astro regen is a convenience, not a requirement.
Capture Dates and Transients
The capture date is what makes transients and minor bodies meaningful. Tenrankai
takes it from EXIF, falling back to a capture_date field in the sidecar.
Transients are marked near capture when their discovery date falls between 365 days before and 30 days after the image was taken — a window wide enough to cover a supernova that was already up when you shot, and one discovered shortly after. Markers outside that window are hidden behind a “+N old transients” toggle, so a five-year-old image doesn’t get littered with today’s discoveries.
Comets and asteroids are only drawn when a capture date exists. Their
positions are propagated to that exact moment, down to a magnitude limit of 18,
and labeled with brightness and distance (V~11.4, 1.83 AU).
Reading the Overlay
| Object | Marker |
|---|---|
| Deep-sky object | Cyan ellipse, oriented to its position angle |
| Named star | Yellow tick marks |
| Transient (supernova) | Magenta diamond |
| Comet | Teal diamond with a dash pointing along the anti-solar tail |
| Asteroid | Orange diamond with a dash along its motion trail |
Labels combine catalog and common name (NGC 1976 · Orion Nebula) and nudge
themselves to avoid collisions. An object whose ellipse swallows the entire
frame isn’t drawn as an ellipse — it’s listed in a “Field within: …” note in the
corner, so a wide-field shot inside a large nebula still tells you where you are.
Toggle overlays with the Objects (N) control beneath the image. The toggle state follows you into the desktop loupe and the mobile pinch-zoom view, and the controls are placed so they don’t fight with touch gestures.
Choosing Catalogs
A rich field can carry hundreds of catalogued objects, and labeling all of them at once is unreadable. Next to the Objects toggle is a Catalogs menu that turns individual catalogs on and off:
| Group | Contains |
|---|---|
| NGC / IC / Messier | The main deep-sky catalogs |
| Sharpless / vdB | Sh2- emission and vdB reflection nebulae |
| Dark nebulae (B / LDN) | Barnard and Lynds dark nebulae |
| Supernova remnants | SNR entries |
| Wolf-Rayet stars | WR entries |
| Stars (HD / named) | Named and catalogued stars |
| UGC galaxies | UGC entries |
| PGC galaxies | PGC entries |
| Comets / asteroids | Solar-system bodies |
The menu only lists the groups actually present in the image, so it stays short. Choices are remembered in your browser and carry across images and pages — turn off PGC galaxies once and they stay off while you browse. This is a viewer-side preference; there’s nothing for the operator to configure.
Overlays in Posts
Gallery images embedded in a post carry overlays too, as a compact Objects (N) pill over the embed, with the same Catalogs menu and the same remembered catalog choices as the detail page. This also works for a post’s hero image, provided the hero is referenced as a gallery image rather than a plain URL:
+++
title = "A Supernova in NGC 3310"
hero_image = "gallery:main:astro/ngc3310.jpg"
+++
Old transients are always hidden in post embeds — the pill shows the objects that matter for the image.
If you maintain custom post templates, note that the post-detail context now
carries hero_image_gallery and hero_image_path; the hero overlay depends on
them.
Permissions
The astro API and every overlay are gated by can_see_technical_details, the
same permission that governs the rest of the technical metadata. Viewers without
it simply see the image, with no toggle and no sky map.
API
GET /api/gallery/{name}/astro/{path}
Returns the solution and overlay as JSON: the WCS, scale_arcsec_px,
rms_arcsec, matched_stars, and the object list with pixel coordinates,
ellipse geometry, kinds, and a near_capture flag on each transient. An image
that can’t be solved returns {"solved": false}.
Requires can_see_technical_details; returns 403 otherwise, and 404 when
[astro] isn’t configured.
Sky Maps
Separately from plate solving, any image with ra and dec in its sidecar gets
a Sky Position card on its detail page: an all-sky chart with the brightest
stars and a crosshair at the target, plus links that open
Aladin Lite and
SIMBAD at those coordinates. This needs
no catalogs and no solution — just the coordinates.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| No Objects toggle anywhere | [astro] missing, or star_data failed to load — check the startup log for a warning |
| Toggle appears, but no objects | object_data not configured; solving works but there’s nothing to overlay |
| Image never solves | No ra/dec in the sidecar, no telescope field, and the folder isn’t marked astro = true |
| Blind solving works on wide fields but never on narrow ones | No blind_index — the on-demand fallback only covers bright stars. Configure a prebuilt index |
| Log warns the blind index “was built from N stars” | blind_index and star_data come from different catalogs; rebuild or re-download them as a matched pair |
| Blind solve is slow the first time | The index loads once per process. Memory-mapping a prebuilt blind_index is near-instant; building the fallback is not |
| Server refuses to start with a config error | [astro] rejects unknown keys — check for a typo’d key name |
| No supernova markers | transient_data not set, or the discovery falls outside the capture window — check the “+N old transients” toggle |
| No comets or asteroids | minor_body_data not set, or the image has no capture date in EXIF or sidecar |
| Overlays look stale after a catalog update | Restart (object catalogs load at startup), then run tenrankai astro regen -g <gallery> |
| Viewer sees no overlay at all | Missing can_see_technical_details permission |
Upgrading
Tenrankai currently builds against seiza 0.3.0. Existing catalog files keep
working — the star, object, transient, and minor-body formats are unchanged
from 0.2.x, so there’s nothing to rebuild. The blind pattern index is a new,
additional file: if you want blind solving on narrow fields, fetch or build one
and add blind_index to your [astro] block.
Next Steps
- Gallery Setup - Image processing, sizes, and formats
- Permissions - Who can see technical details
- API Reference - The full endpoint list