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

Uploaded CPython 3.9+Windows x86-64

seiza-0.10.0-cp39-abi3-manylinux_2_28_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ ARM64

seiza-0.10.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.3 MB view details)

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

seiza-0.10.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.10.0.tar.gz.

File metadata

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

File hashes

Hashes for seiza-0.10.0.tar.gz
Algorithm Hash digest
SHA256 744f8c2ceb65cde0204267f587b05873c0fcd3bc9bc513af83a82bc2caaee2f4
MD5 dd9d6908ecc24f39ef6ec78600699515
BLAKE2b-256 500422571d9d533390032a97efacf9cee0ef2cc5fcce1003152a830fe8e9e890

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: seiza-0.10.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.10.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 b7154d80811836fe282801d117726b3062998200e99dc94fcb8a60a657d9aa77
MD5 340cff9d2f6407aa343ca2c28d8d2c17
BLAKE2b-256 e5151b390c51de1d2c155129f0ed21af7a7d4265babf3246506f02e049a4a050

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for seiza-0.10.0-cp39-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 bf7bfd063074d5103abea6e6dc8d0708e312079747a85b968a48418ae39cc2f5
MD5 ad807a0496316be300cf7196506bcc51
BLAKE2b-256 6484b0fcfd539ca067d10eb7bdee42045bb10d0c9ce6e6d3ebd3d9f04da6acb0

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for seiza-0.10.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0c25eacd2d07ebc466f8946f555c514762e2ef574b491716d42295bbe1da0a88
MD5 62c2fef095e4491c1694c0a81e7b01b2
BLAKE2b-256 3ebcc7ff0a7a66bd6a8b2fad53829d26bc012cfa745935bb5d9d560e968f98b5

See more details on using hashes here.

Provenance

The following attestation bundles were made for seiza-0.10.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.10.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.10.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 4a5dae272a5c826c77e518c4a87cd9ab51c5c5fd18889289573e376a449c65da
MD5 c59ae7b8a1eac96690b325537af6691f
BLAKE2b-256 e6fbf4bfe9221c8203f22764b0b6182263d38a553b9ad52ed84cd09bfdb50e8c

See more details on using hashes here.

Provenance

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