Metadata-Version: 2.5
Name: pysatellitespotter
Version: 0.2.0
Summary: Predict naked-eye satellite passes, as See A Satellite Tonight does
Project-URL: Homepage, https://github.com/kedube/pysatellitespotter
Project-URL: Issues, https://github.com/kedube/pysatellitespotter/issues
Project-URL: Upstream, https://github.com/wildekek/see-a-satellite
Project-URL: Website, https://james.darpinian.com/satellites/
Author-email: Willem Vooijs <willem@vooijs.eu>
Maintainer: Katherine Dubé
License-Expression: MIT
License-File: LICENSE
Keywords: astronomy,home-assistant,iss,satellite,sgp4,starlink
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Astronomy
Classifier: Typing :: Typed
Requires-Python: >=3.13
Requires-Dist: aiohttp>=3.9
Requires-Dist: numpy>=1.26
Requires-Dist: sgp4>=2.23
Description-Content-Type: text/markdown

# pysatellitespotter

Predict when satellites are visible to the naked eye, the way
[See A Satellite Tonight](https://james.darpinian.com/satellites/) does. This
is a Python port of James Darpinian's site, made with his permission. It powers
the Home Assistant [Satellite Spotter](https://github.com/kedube/ha-satellite-spotter)
integration.

This is a fork of Willem Vooijs's
[see-a-satellite](https://github.com/wildekek/see-a-satellite), with fixes for
crashes on valid catalog data and on passes past the prediction window
([wildekek/see-a-satellite#2](https://github.com/wildekek/see-a-satellite/pull/2)).
It installs as its own module, `pysatellitespotter`, so it can sit beside
see-a-satellite in one environment, as it does when Home Assistant runs both
integrations.

```sh
pip install pysatellitespotter
```

```python
import aiohttp
from pysatellitespotter import fetch_site_catalog, group_transits, predict_transits

async with aiohttp.ClientSession() as session:
    satellites = await fetch_site_catalog(session)

# CPU bound (a few seconds): run it in an executor from async code.
for group in group_transits(predict_transits(satellites, 52.03, 5.56, 10)):
    t = group.primary
    print(group.start, t.satellite.name, f"mag {group.min_magnitude:.1f}",
          f"rises {t.rise.azimuth:.0f}°/{t.rise.elevation:.0f}°", "bright" if group.bright else "")
```

## What it computes

The pipeline follows the website step by step:

- **Propagation.** SGP4 runs from OMM elements at one-minute steps for 5 days, and positions are rotated from the TEME frame to Earth-fixed coordinates.
- **Brightness.** The intrinsic magnitude at 1000 km is adjusted for range, atmospheric extinction (Green 1992) and phase angle (diffuse sphere). Starlink and BlueBird satellites use their own phase-function models (Mallama et al. 2025; Cole et al. 2025).
- **Visibility.** A satellite counts as visible when it is at least 10° up, brighter than the limiting magnitude for the sun's depression (Weaver 1947), and lit by the sun above the troposphere (grazing height ≥ 15 km).
- **Refinement and grouping.** Each pass is refined to one second. Overlapping passes are grouped, incidental Starlinks are pruned, and a "bright" label is applied.

Checked against the website, for every pass the site shows over 5 days:

- start times agree within 9 s
- end times agree within 19 s
- magnitudes agree within 0.03

A 5-day prediction for the website's catalog of about 860 satellites takes
0.8 s on one core of an Apple M5. Minutes when the sky is too bright for a
satellite to be seen are skipped, so most of the time goes to SGP4 for the
twilight and night hours.

## Catalog

`fetch_site_catalog(session, "brightest" | "starlink")` downloads the
website's catalog, which the site's author collects and curates. Orbital
elements come mostly from [Space-Track](https://www.space-track.org/) (US
Space Force 18th Space Defense Squadron), and Starlink elements come from
[CelesTrak](https://celestrak.org/). Magnitudes come from Mike McCants and the
MMT-9 survey (Karpov et al. 2016), and constellation phase functions come from
published photometry. See James's
[write-up](https://james.darpinian.com/blog/how-see-a-satellite-tonight-works).
This library only consumes the catalog. The site refreshes it every 8 hours.
Cache it (`dump_catalog` / `parse_site_catalog`) rather than downloading it on
every prediction.

## Development

```sh
uv sync
uv run pytest && uv run mypy && uv run ruff check src tests
```
