# A geometric pass is not an optical visibility prediction

Prepared 5 November 2026 by Alex Carter, SatellitePlus · CannedRocket.

This is an independent, reproducible **historical calculation** using Skyfield.
It is not a live forecast, an observed sighting, or a test of SatellitePlus.

## The question

If a satellite is above your horizon and in sunlight, can you necessarily see it?
This reference case separates three quantities instead of calling them all
"visible": satellite elevation, sunlight at the satellite, and the Sun's
elevation at the observing site.

The calculation uses an archived ISS element set from Skyfield's MIT-licensed
test fixture, with an epoch of **2018-07-03 19:25:57 UTC**. The observing site is
a fixed Greenwich reference (51.4769° N, 0.0005° W, 46 m elevation). The window
is 2018-07-04 00:00 UTC through 2018-07-05 00:00 UTC. These are data dates, not
the publication date or claims about today's sky.

## Recorded result

The reference run found **4 culminations above a 10° elevation threshold**.
All four peaks were sunlit, but all occurred with the Sun above the site's
horizon. **0 peaks and 0 ten-second sampled intervals** passed this example's
combined screen: satellite elevation at least 10°, Sun below -6°, and satellite
sunlit. The zero is a computed result for this fixed case, not missing data.

The -6° limit is a chosen twilight screening threshold, not a universal rule
for naked-eye detection. Brightness, phase angle, attitude, weather, eyesight,
light pollution and the real skyline are not modelled. A passing screen does
not prove visibility; a failing darkness screen does not prove every object
is optically impossible to detect with every instrument.

## Reproduce

Tested with CPython 3.14 on macOS arm64. Create a virtual environment and install
the exact dependencies from PyPI (network access is needed for this step):

```sh
python3.14 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python calculate.py --output reproduced.json
```

All calculation inputs, including the unmodified DE421 kernel, are bundled.
After installation, the calculation runs offline: the timescale uses
Skyfield's bundled tables. `calculate.py` checks the kernel SHA-256 before
loading it and writes a new file rather than overwriting `results.json`.

Compare `summary`, `events` and `sampled_screen_windows` with `results.json`.
The program also checks event ordering and the numerical altitude at each
10° crossing. Event timestamps are numerical model results, not millisecond
physical-accuracy claims. Sampled window endpoints have a 10-second grid;
shorter intervals could be missed. A peak's illumination must not be used to
label an entire pass: the separate sampling step evaluates conditions within
the search window.

## Files and provenance

- `calculate.py`: original calculation, MIT licensed; see `LICENSE.txt`.
- `iss.tle`: the two archived lines, unchanged from the source recorded in
  `fixture-source.json`; the source commit and full fixture hash are included.
- `SKYFIELD-LICENSE.txt`: upstream copyright and MIT permission notice.
- `de421.bsp`: **unmodified** NASA/JPL DE421 planetary ephemeris distributed by
  NAIF. `ephemeris-source.json` records its official URL, byte length and hash.
  [NAIF's rules permit redistribution of unmodified kernels](https://naif.jpl.nasa.gov/naif/rules.html).
  No SPICE Toolkit is included. The original producers and distributors do not
  endorse this example; their data and software come without warranty.
- `requirements.txt`: pinned calculation dependencies; dependency packages are
  installed separately and retain their respective licences.
- `results.json`: actual reference output, including versions, data hashes,
  event directions/ranges, screening conditions and limitations.
- `SHA256SUMS.txt`: package integrity checks, excluding this manifest itself.

Primary method reference: [Skyfield Earth satellites](https://rhodesmill.org/skyfield/earth-satellites.html).
Ephemeris credit: NASA/JPL Solar System Dynamics, DE421, distributed by NAIF.
Do not reuse this old element set for present-day observing. Use fresh orbital
data, your real site and local conditions for an actual session.
