Skip to content

satkit 0.24.0

Latest

Choose a tag to compare

@ssmichael1 ssmichael1 released this 26 Sep 19:51
· 14 commits to main since this release
26e711b

0.24 comes out of a full review of the time, frames, ephemeris, SGP4, data and binding layers. It fixes a set of long-standing defects, several of which gave wrong numbers without any error, and it tightens the Python API: exception types, return shapes and keyword handling. Please read Migrating to 0.24 before upgrading.

Check your results

These defects changed numbers without raising an error. If your work depends on one of them, re-run it with 0.24. The migration page has the details.

  • Quaternion × N×3 array applied the inverse rotation (0.14.1–0.23.1). A single 3-vector was rotated correctly.
  • satproperties(a, b) positional arguments swapped drag and radiation pressure. The constructor is now keyword-only.
  • lambert was wrong for long-way, retrograde, hyperbolic and near-parabolic transfers (0.14.1–0.23.1). kepler.from_pv was wrong at inclination π.
  • SGP4 kept a stale initialization after a TLE was edited or gravconst / opsmode changed. Rust sgp4() and TLE fitting used WGS84; the default is now WGS72 everywhere.
  • Time strings with UTC offsets: from_rfc3339 ignored ±HHMM / ±HH, the strptime %z sign was inverted, and from_string read offsets as microseconds.
  • Leap seconds and TDB: midnight after a leap second was 1 s early, UT1 was up to 0.5 s off the day before one, TDB was off by up to 3.3 ms, and the JPL ephemerides were evaluated at TT instead of TDB.
  • moon.pos_gcrf returned mean-of-date coordinates, planets.heliocentric_pos had wrong obliquity and outer-planet terms, and sun.rise_set often returned the next day's events.
  • Drag and density: drag now applies up to 1,000 km (was 700 km). Density on the day after a missing F10.7 was 35–39 % low, and density.nrlmsise() ignored datetime times.
  • Pre-1972 UTC follows the 1961–1971 "rubber second" model, so labels move by up to 9.9 s. EOP before 1973 is no longer available: UT1 = UTC there.

Highlights

  • Python 3.11–3.15: wheels for CPython 3.15 (ready for its October release); Python 3.10 (end of life October 2026) is no longer supported.
  • numpy datetime64 time input everywhere a time or time array is accepted (any unit, read as UTC), so pandas / xarray time columns go straight in.
  • Warnings use standard logging: Rust's log facade (stderr when no logger is installed) and, in Python, the logging module under satkit.* loggers — silence with logging.getLogger("satkit").setLevel(logging.ERROR).
  • Faster: EOP and space-weather lookups, gmst (−53 %), TEME→ITRF (−40 %) and GEO propagation (−12 %) are faster than 0.23.1; LEO propagation with drag is ~2 % faster.
  • Earth orientation from IERS finals2000A.all only, with a stale-prediction warning, rejection of truncated downloads, and a parser that no longer panics on duplicated rows.
  • Time: the pre-1972 UTC model matches ERFA; the Earth rotation angle agrees with ERFA to 9 µas (it was off by up to 1 cm at LEO, 6 cm at GEO); microsecond rounding is exact through strings, datetime, chrono and pickles; Rust has new checked_add / checked_sub.
  • TLEs: parse errors give the line and satellite, there is a new Rust TLE::records() iterator, checksum checks are optional (check_checksum=True), and mismatched or orphan lines are rejected. OMMs with day-of-year epochs are accepted. The line-1 classification letter is kept (TLE.classification, OMM CLASSIFICATION_TYPE), and malformed Alpha-5 satellite numbers are rejected.
  • SGP4: thread-safe on a shared TLE; errflag=True reports element sets that cannot be initialized as NaN rows; TLE.fit_from_states() takes gravconst / opsmode.
  • New: Python moon.pos_mod; geodetic and propstats pickle; satstate, density.nrlmsise() and sun.rise_set() accept a datetime.
  • Robustness: sun.shadowfunc no longer returns NaN near L2 or inside the Earth, the planets' Kepler solver can no longer hang, and time arithmetic overflow raises OverflowError instead of wrapping.
  • Docs: a rewritten Time Systems reference page, a Troubleshooting & FAQ page and the migration guide.
  • Verification: differential tests against ERFA, property tests (proptest / hypothesis), and stubtest over every stub module. Builds are reproducible.

Breaking changes

See the migration page for each change and what to do.

  • Python 3.11 or newer is required.
  • satproperties() is keyword-only. Unknown keywords raise TypeError (was ValueError).
  • One-element lists keep their axis: sgp4(tle, [t]) is (1, 3) and sgp4([tle], t) is (1, 3).
  • TLE.from_lines() / from_file() / from_url() always return list[TLE].
  • Warnings go through log / Python logging instead of being printed directly; their text no longer starts with Warning: when shown by Python.
  • Many invalid calls raise a specific TypeError / ValueError / OverflowError / ZeroDivisionError instead of RuntimeError or a meaningless value (table).
  • EOP comes only from IERS finals2000A.all, and the satkit[data] extra is gone.
  • utils.build_date() is removed (utils.version() now returns the release version), and frametransform.eop_source() is deprecated.
  • Pickles written by 0.24 do not load in 0.23.
  • Rust: EopSource removed, DataDirReadOnly { path, reason }, EopCoverage fields, SGP4InitArgs::epoch_days_1950, lambert::Error #[non_exhaustive], Instant operators saturate, Instant::UNIX_EPOCH.raw, new public TLE::classification field.
  • Reminder: the deprecated Python as_* conversions are removed in 0.25.

Full list: CHANGELOG.

Install / upgrade

pip install --upgrade satkit
cargo add satkit@0.24
conda install -c conda-forge satkit=0.24