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.1.tar.gz (206.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.1-cp39-abi3-win_amd64.whl (2.3 MB view details)

Uploaded CPython 3.9+Windows x86-64

seiza-0.11.1-cp39-abi3-manylinux_2_28_aarch64.whl (2.4 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ ARM64

seiza-0.11.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.5 MB view details)

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

seiza-0.11.1-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (4.5 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.1.tar.gz.

File metadata

  • Download URL: seiza-0.11.1.tar.gz
  • Upload date:
  • Size: 206.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.1.tar.gz
Algorithm Hash digest
SHA256 2f27a2f6da07895e2fc1c1d1db18f9d7b177ef5e98eb0eb49a86d11a518e1860
MD5 5fef011b6bfdb444bf47cbc0e4034c91
BLAKE2b-256 abce1ee8515262cd21087705dc3a86c254ed96a5174076b2fb77f8e3dd08933d

See more details on using hashes here.

Provenance

The following attestation bundles were made for seiza-0.11.1.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.1-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: seiza-0.11.1-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.1-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 ec8514a39ffbe56268a4b78b00849adc2ff5ae91c0e073f217708b440627941a
MD5 efe8b5c890613fb6f4b5f643f0a257ff
BLAKE2b-256 633e32dd0ab1e79a5b5918a3e5618e3f41a4bc1269ea37a91427f906a3132980

See more details on using hashes here.

Provenance

The following attestation bundles were made for seiza-0.11.1-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.1-cp39-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for seiza-0.11.1-cp39-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 8eb57d68153b5104f47f366c4bf5e35be48abaa5415c33ad75a1ada62e327e00
MD5 9a5ebda5c7235f2e6197405ba3764b60
BLAKE2b-256 2523b9134bb5d3393531f701147cc3303346af79d48cafe1cdf6d8b7728bcb7b

See more details on using hashes here.

Provenance

The following attestation bundles were made for seiza-0.11.1-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.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for seiza-0.11.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 eea68f8d696a83ddf4643a56bb730dea5ed1f1de1fa1abcddede015d81267e11
MD5 1e5e00be13a37009a141d6ed8d7fd83a
BLAKE2b-256 fe42acf1d12b40c2bab3f1a5a359a9f9f53ce937af47f6983b73ddbcebf8d6aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for seiza-0.11.1-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.1-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.1-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 4210d6be7822eea015c9cb9c017cd0d8bbac77517dcc8b982d62265b56bc20d3
MD5 ddd2791c7e459692cd26f3e5996d5b3c
BLAKE2b-256 c3c5f401342192689f1c299ddd1faf9c0dfe31963dcad9b72561f24d7b6b668b

See more details on using hashes here.

Provenance

The following attestation bundles were made for seiza-0.11.1-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