Skip to main content

Star detection, WCS fitting, and hinted/blind plate solving for astrophotography

Project description

seiza (Python)

Python bindings for seiza: star detection, WCS fitting, and hinted/blind plate solving for astrophotography, implemented in Rust. Solves typical frames in a fraction of a second.

pip install seiza

Binary wheels cover Linux (x86_64, aarch64), macOS (universal2), and Windows (x64); each is a single abi3 wheel for every CPython from 3.9 up. Type stubs are included, and solving releases the GIL.

Solve an image

import numpy as np
import seiza

# One-time: download the verified solver catalogs into the shared cache.
paths = seiza.fetch_catalogs()  # lightweight Tycho-2 set
catalog = seiza.StarCatalog.open(paths["stars-lite-tycho2.bin"])

# Detect stars in a 2D float32 (or uint8) luma array.
stars = seiza.detect(image_array)

# Hinted solve: approximate center and pixel scale. sip_order=3 also fits
# SIP distortion polynomials when enough matched stars support them.
solution = seiza.solve(
    stars, catalog, width, height,
    ra=150.1, dec=35.2, scale_arcsec_px=2.5, sip_order=3,
)
print(solution)                 # center, scale, matches, RMS
print(solution.rotation_deg, solution.flipped)
ra, dec = solution.wcs.pixel_to_world(100.0, 200.0)

open takes a file, a directory (the right catalog inside is picked — the deepest star catalog wins), or nothing at all. With no argument the standard places are searched: SEIZA_STAR_DATA / SEIZA_BLIND_INDEX, files next to the program, and the seiza setup directories (SEIZA_CATALOG_DIR). These are the same rules as the CLI's --data:

catalog = seiza.StarCatalog.open("data")   # directory
catalog = seiza.StarCatalog.open()         # after seiza setup

Stars can also be plain (x, y, flux) tuples from any other detector — the solver only needs positions and relative brightness:

solution = seiza.solve([(x1, y1, f1), (x2, y2, f2), ...], catalog, w, h,
                       ra=..., dec=..., scale_arcsec_px=...)

Blind solve

No position hint, only a plausible scale range. Uses the prebuilt whole-sky pattern index and the deep Gaia catalog:

paths = seiza.fetch_catalogs(["stars-deep-gaia17.bin", "blind-gaia16.idx"])
catalog = seiza.StarCatalog.open(paths["stars-deep-gaia17.bin"])
index = seiza.BlindIndex.open(paths["blind-gaia16.idx"])
solution = seiza.solve_blind(stars, catalog, index, width, height,
                             min_scale_arcsec_px=0.5, max_scale_arcsec_px=15.0)

For faint fields, the optional stars-deep-gaia20.bin catalog reaches Gaia G≤20 (about 9 GB). It is intentionally not included in fetch_catalogs("all"), so request it explicitly with the same G≤16 blind index:

paths = seiza.fetch_catalogs(["stars-deep-gaia20.bin", "blind-gaia16.idx"])
catalog = seiza.StarCatalog.open(paths["stars-deep-gaia20.bin"])
index = seiza.BlindIndex.open(paths["blind-gaia16.idx"])

FITS WCS output

Solutions convert directly to FITS WCS keywords (1-indexed CRPIX, TAN or TAN-SIP projection, CD matrix, and the complete A_p_q/B_p_q/AP_p_q/ BP_p_q set when distortion was fitted):

cards = solution.fits_header_cards()   # dict of keyword -> value
text = solution.fits_header_text()     # 80-column cards ending with END

The header text form is suitable for header-injection APIs — for example Siril's sirilpy scripting interface (set_image_header), which makes a seiza solve usable from a Siril Python script.

Predicted satellite tracks

After a solve, predict which satellites crossed the image while the shutter was open. Predictions come from orbital elements — they are never pixel detections. The exposure must be one continuous shutter-open interval (not a stack's total integration) and needs an observer location:

sats = seiza.SatelliteCatalog.fetch_celestrak()   # cached; ~2h refresh floor
# or offline / historical: seiza.SatelliteCatalog.open("elements.json")

result = sats.tracks_in_footprint(
    solution.wcs, width, height,
    start="2026-07-19T06:12:00Z",     # Unix seconds, RFC 3339, or tz-aware datetime
    duration_s=120.0,
    latitude=42.466, longitude=-71.1516, altitude_m=150.0,
)
for track in result.tracks:           # highest elevation first
    print(track.label, track.max_elevation_deg, track.clipped_segments)

Element records older than seven days are reported in result.stale_elements and skipped rather than silently extrapolated (max_element_age_s=None overrides). CelesTrak rate-limits repeated downloads: keep reusing one cache directory, and check sats.cache_state and sats.warning after fetch_celestrak().

Notes

  • Solving and detection release the GIL; other Python threads keep running.
  • Catalog files are memory-mapped and SHA-256 verified at download time; fetch_catalogs caches under the platform cache directory (override with cache_dir= or SEIZA_CACHE_DIR).
  • seiza.StarCatalog.from_stars([...]) builds a small in-memory catalog for tests and synthetic fields.

License

Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

seiza-0.11.0.tar.gz (204.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

seiza-0.11.0-cp39-abi3-win_amd64.whl (2.3 MB view details)

Uploaded CPython 3.9+Windows x86-64

seiza-0.11.0-cp39-abi3-manylinux_2_28_aarch64.whl (2.3 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ ARM64

seiza-0.11.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

seiza-0.11.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (4.3 MB view details)

Uploaded CPython 3.9+macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

File details

Details for the file seiza-0.11.0.tar.gz.

File metadata

  • Download URL: seiza-0.11.0.tar.gz
  • Upload date:
  • Size: 204.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for seiza-0.11.0.tar.gz
Algorithm Hash digest
SHA256 9cfaca5cf15ff81f59035826c1fec861c2bfc3581d1c285157d8f4616841ed50
MD5 c08df671396fd57cd9aa50c643b60f50
BLAKE2b-256 2cfba0e4b9e39d19d30233cf98b834edf112e9e64246a68e6e5f5b3e241aa112

See more details on using hashes here.

Provenance

The following attestation bundles were made for seiza-0.11.0.tar.gz:

Publisher: python-wheels.yml on theatrus/seiza

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file seiza-0.11.0-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: seiza-0.11.0-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.3 MB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for seiza-0.11.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 a0da61cb1b8164681e00a65198e1da50d6be0cd769398d041523b39ef36e5aad
MD5 a8550fe39def37d4febdb86da0f155d6
BLAKE2b-256 5c2fd289674f0cc0b2d0938592b76332c9a8668320f337d2d449a15fb3072967

See more details on using hashes here.

Provenance

The following attestation bundles were made for seiza-0.11.0-cp39-abi3-win_amd64.whl:

Publisher: python-wheels.yml on theatrus/seiza

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file seiza-0.11.0-cp39-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for seiza-0.11.0-cp39-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 8c068bcaaebf6f9ee048127cd85c21f5b334678c56064806e3a0a7771bf2fb1f
MD5 07c99873838fd36dafbe4ae55588819e
BLAKE2b-256 b9c04307fac0caca164671fd1c88523ccf833bf61297f5874508dee108210dbf

See more details on using hashes here.

Provenance

The following attestation bundles were made for seiza-0.11.0-cp39-abi3-manylinux_2_28_aarch64.whl:

Publisher: python-wheels.yml on theatrus/seiza

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file seiza-0.11.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for seiza-0.11.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a1a2b5a92f767e58d9d18ac829c9772759a62dc1b932c22b792331e047d8ccca
MD5 c1fa00a370c21ccfb143bb07e5b53ed1
BLAKE2b-256 5213ef768f836fd6d10e339edf725bd1852e9277785d2855917cb4fafe8f4b9d

See more details on using hashes here.

Provenance

The following attestation bundles were made for seiza-0.11.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: python-wheels.yml on theatrus/seiza

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file seiza-0.11.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for seiza-0.11.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 21b21d54475e7b560cf4f4b2835b98ab6b7196e758dae9bbcbe705d41a887052
MD5 1a39f42b6364090bedfec2e46c6a066b
BLAKE2b-256 460d61e45a230d93e212dffa007dffda7b0c7a6bdc08ab71156707df9080404d

See more details on using hashes here.

Provenance

The following attestation bundles were made for seiza-0.11.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: python-wheels.yml on theatrus/seiza

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page