Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
0341acd
Fix sign, wrapping and quadrants in the angle and horizon conversions
SuperdoerTrav Oct 8, 2026
dd2798f
Advance the Sun's perihelion in the fast sunPos series
SuperdoerTrav Oct 8, 2026
1200a46
Make lb_to_tan's projected rates the derivative of its projection
SuperdoerTrav Oct 8, 2026
fc7a609
Advance Leapfrog4 epochs by whole steps, not three rounded substeps
SuperdoerTrav Oct 8, 2026
2665e62
Write zero drag terms in make_tle, and keep a source TLE's drag terms
SuperdoerTrav Oct 8, 2026
eb7b0eb
Document what the deprecated radecRate actually returns
SuperdoerTrav Oct 8, 2026
f9644e1
Warn when the Gauss two-position solver does not converge
SuperdoerTrav Oct 8, 2026
5d1b955
Recompute Earth precession-nutation hourly, not every 30 days
SuperdoerTrav Oct 8, 2026
cbe1bdd
Interpolate fixed-step propagators with a quintic Hermite between steps
SuperdoerTrav Oct 8, 2026
cadfd3d
Honour VolumeDistancePrior's scale argument
SuperdoerTrav Oct 8, 2026
bda7a5d
Use the selected row in circular_guess when rates are given
SuperdoerTrav Oct 8, 2026
a4edcc6
Give the drag model the Sun of date and an hourly frame update
SuperdoerTrav Oct 8, 2026
db9bfe4
Make Danchick's two-position solver converge over the whole revolution
SuperdoerTrav Oct 8, 2026
f49695c
Correct VENUS_MASS
SuperdoerTrav Oct 8, 2026
a11e8db
Warn instead of printing when AccelHarmonic clamps its degree or order
SuperdoerTrav Oct 8, 2026
d137851
Scale harmonic gravity by each model's own GM
SuperdoerTrav Oct 8, 2026
5ebcb98
Resolve data files through find_file, skipping git LFS pointers
SuperdoerTrav Oct 8, 2026
c71ba64
Load SSAPy's data from llnl-ssapy-data, with DE440, and drop it here
SuperdoerTrav Oct 8, 2026
460bc01
Select DE440 or DE430 and fetch long-span kernels when epochs need them
SuperdoerTrav Oct 9, 2026
d0a9cb7
Use split SSATK data distributions
SuperdoerTrav Oct 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions .gitattributes

This file was deleted.

14 changes: 1 addition & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ concurrency:

env:
CI_PROJECT_DIR: ${{ github.workspace }}
GIT_LFS_SKIP_SMUDGE: 1

jobs:
test:
Expand All @@ -39,7 +38,6 @@ jobs:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
lfs: false
token: ${{ github.token }}
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
Expand All @@ -50,15 +48,11 @@ jobs:
run: |
# Install dependencies
sudo apt-get update
sudo apt-get install build-essential git git-lfs python3 python3-setuptools python3-venv graphviz cmake
sudo apt-get install build-essential git python3 python3-setuptools python3-venv graphviz cmake

# Initialize and update submodules
git submodule update --init --recursive

# Install Git LFS and pull LFS objects
# git lfs install
# git lfs pull

# Upgrade pip and install Python dependencies
python -m pip install --upgrade pip setuptools flake8
python -m pip install -r requirements.txt
Expand All @@ -77,12 +71,6 @@ jobs:
# Use the actions/setup-python toolchain and avoid Homebrew updates,
# which can fail CI when the hosted runner's brew state is stale.
python -m pip install --upgrade pip setuptools flake8 cmake

# Make LFS usable if the runner already has it, but do not require
# Homebrew just for CI wheel/import checks.
if command -v git-lfs >/dev/null 2>&1; then
git lfs install --skip-repo
fi
git config --global credential.helper "" # avoid Keychain prompts

# Use the actions/setup-python toolchain consistently
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install build-essential git git-lfs cmake
git lfs install
git lfs pull
sudo apt-get install build-essential git cmake
python -m pip install --upgrade pip build twine
python -m pip install -r requirements.txt

Expand Down
1 change: 0 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@ recursive-include pybind11/include/ *
include pybind11/CMakeLists.txt
include pybind11/LICENSE
recursive-include pybind11/tools *
recursive-include ssapy/data *
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ wrappers around coordinate conversions, Lambertian magnitude / brightness
calculations, and related extensions, see the companion project
`SSAPy-Toolkit <https://github.com/llnl/SSAPy-Toolkit>`__.

Optional packaged datasets are available with ``llnl-ssapy[data]``. Install
``llnl-ssapy[all-data]`` to install every split ``ssatk-data-*`` distribution.

SSAPy includes:

- Ability to define satellite parameters (area, mass, radiation and drag coefficients, etc.)
Expand Down
1 change: 1 addition & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and/or heavy dependencies. Below lists the packages available in the ``ssapy``
ssapy.constants
ssapy.correlate_tracks
ssapy.ellipsoid
ssapy.ephemeris
ssapy.gravity
ssapy.io
ssapy.linker
Expand Down
30 changes: 27 additions & 3 deletions docs/source/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@ These requirements can be easily installed on most modern macOS and Linux system
.. code-block:: console

apt update
apt install build-essential git git-lfs python3 python3-distutils python3-venv graphviz
apt install build-essential git python3 python3-distutils python3-venv graphviz

.. tab:: RHEL

.. code-block:: console

dnf install epel-release
dnf group install "Development Tools"
dnf install git git-lfs gcc-gfortran python3 python3-pip python3-setuptools graphviz
dnf install git gcc-gfortran python3 python3-pip python3-setuptools graphviz

.. tab:: macOS Brew

.. code-block:: console

brew update
brew install gcc git git-lfs python3 graphviz
brew install gcc git python3 graphviz

Installation
------------
Expand All @@ -45,6 +45,30 @@ As the package has been published on `PyPI <https://pypi.org/project/llnl-ssapy/

pip install llnl-ssapy

SSAPy's data (ephemerides, gravity models, textures) is installed with it
from the ``llnl-ssapy-data`` package; no Git LFS is needed.

Planetary ephemerides
^^^^^^^^^^^^^^^^^^^^^

SSAPy uses JPL DE440 by default, from the short kernel ``de440s.bsp``
(1849-2150). A 1900-2150 excerpt of DE430 is also installed for reproducing
results from SSAPy 1.1.10 and earlier; select it with
``ssapy.ephemeris.set_planetary_ephemeris("de430")`` or
``SSAPY_EPHEMERIS=de430``.

For epochs outside those spans SSAPy downloads a longer kernel of the same
ephemeris from NAIF (``de440.bsp`` or ``de430.bsp``, 1550-2650, 120 MB) and,
for DE440 beyond 1550-2650, DE441 (1.65 GB per half), checks its SHA-256,
caches it in ``~/.cache/ssapy`` (``SSAPY_DATA_CACHE``), and warns before
downloading. Set ``SSAPY_EPHEMERIS_DOWNLOAD=0`` to forbid downloads, for
example on compute nodes without network access, and prefetch on a node that
has it:

.. code-block:: console

SSAPY_DATA_CACHE=/shared/ssapy-cache python -c "import ssapy.ephemeris as e; e.fetch()"

Orekit dependency
^^^^^^^^^^^^^^^^^

Expand Down
1 change: 0 additions & 1 deletion docs/source/tables/system_prerequisites.csv
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ Python, 3.10--3.12, , Interpreter
C/C++ Compilers, , , Building software
make, , , Build software
git, , , Manage software repositories
git-lfs, , , Track large binary files
graphviz, , , Local documentation building
18 changes: 17 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@ dependencies = [
]

[project.optional-dependencies]
data = [
"ssatk-data-core==0.0.1",
"ssatk-data-gravity==0.0.1",
"ssatk-data-lunar==0.0.1",
"ssatk-data-lunar-gravity==0.0.1",
]

all-data = [
"ssatk-data-core==0.0.1",
"ssatk-data-gravity==0.0.1",
"ssatk-data-lunar==0.0.1",
"ssatk-data-lunar-gravity==0.0.1",
"ssatk-data-propulsion==0.0.1",
"ssatk-data-benchmarks==0.0.1",
]

dev = [
"pytest",
"pytest-cov",
Expand Down Expand Up @@ -70,7 +86,7 @@ packages = { find = { include = ["ssapy", "ssapy.*"], namespaces = true } }
include-package-data = true

[tool.setuptools.package-data]
ssapy = ["*.cpp", "*.h", "data/*"]
ssapy = ["*.cpp", "*.h"]

[tool.pytest.ini_options]
testpaths = ["tests"]
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ graphviz
numpy
scipy
jplephem
llnl-ssapy-data>=0.2.0
astropy
pyerfa
emcee
Expand Down
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ def build_extension(self, ext):
ext_modules=[CMakeExtension("ssapy._ssapy")],
cmdclass={"build_ext": CMakeBuild},
packages=find_namespace_packages(include=["ssapy", "ssapy.*"]),
package_data={'ssapy': ['data/*']},
zip_safe=False,
include_package_data=True,
)
16 changes: 10 additions & 6 deletions skills.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,15 @@ r, v = rv(orbit, times, propagator=KeplerianPropagator())

## Data and Binary Rules

SSAPy currently includes required package data under `ssapy/data`, and that data
is still part of the base package. Do not migrate or delete it unless the task
explicitly calls for a coordinated data migration.

Use `ssapy.datadir` or `ssapy.utils.find_file()` when reading existing bundled
SSAPy's data (ephemerides, gravity models, textures) comes from the required
`llnl-ssapy-data` package, under its `ssapy/` tree; the repository no longer
stores data or uses Git LFS. Planetary ephemerides are handled by `ssapy.ephemeris`:
DE440 (`de440s.bsp`, 1849-2150) by default and a 1900-2150 DE430 excerpt on
request. Epochs outside those spans download the full-span kernel from NAIF
(checksummed, cached, with a warning); `SSAPY_EPHEMERIS_DOWNLOAD=0` disables
that.

Use `ssapy.datadir` or `ssapy.utils.find_file()` when reading bundled
resources. Some model loaders already resolve packaged gravity, SPICE, and Earth
orientation files internally; prefer those public loaders over hard-coded paths.

Expand Down Expand Up @@ -184,7 +188,7 @@ python -m twine check dist/*

## Common Pitfalls

- Do not assume all packaged resources are small; base SSAPy still carries existing required data.
- Do not add data files to this repository; add them to SSAPy-Data and release a new `llnl-ssapy-data`.
- Do not add Git LFS as a default solution for new data in this repository.
- Do not commit generated `_ssapy*.so`, `build/`, `dist/`, egg-info, docs build output, caches, or local environments.
- Do not rely on unbuilt in-tree imports for code paths that require `ssapy._ssapy`.
Expand Down
16 changes: 15 additions & 1 deletion ssapy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,23 @@

__version__ = "1.1.10"

datadir = os.path.join(os.path.dirname(__file__), "data")


def _datadir():
"""Directory holding SSAPy's data files: ssapy/ in llnl-ssapy-data."""
try:
from importlib.resources import files
return os.fspath(files("ssapy_data") / "data" / "ssapy")
except (ImportError, TypeError):
# llnl-ssapy-data is a required dependency; without it find_file
# raises a FileNotFoundError that says how to install it.
return os.path.join(os.path.dirname(__file__), "data")


datadir = _datadir()

from . import _ssapy
from . import ephemeris # noqa: F401 (ssapy.ephemeris.set_planetary_ephemeris)
from .orbit import Orbit, EarthObserver, OrbitalObserver
from .propagator import (
KeplerianPropagator, SeriesPropagator, RK4Propagator, SGP4Propagator,
Expand Down
18 changes: 11 additions & 7 deletions ssapy/accel.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,12 +365,14 @@ class AccelDrag(Accel):
----------
recalc_threshold : float, optional
Number of seconds past which the code will recompute the
precession/nutation matrix. Default: 86400*30 (30 days)
precession/nutation matrix. Default: 3600 (1 hour), matching
EarthOrientation; the previous 30-day default let the frame drift
5 arcsec.
defaultkw : dict
default parameters for kwargs passed to __call__,
(area, mass, CR)
"""
def __init__(self, recalc_threshold=86400 * 30, **defaultkw):
def __init__(self, recalc_threshold=3600.0, **defaultkw):
from . import _ssapy

self.recalc_threshold = recalc_threshold
Expand Down Expand Up @@ -412,7 +414,10 @@ def __call__(self, r, v, t, _T=None, **kwargs):
self._t = t
self._T = erfa.pnm80(2400000.5, mjd_tt)
_T = self._T
r_sun = sunPos(t)
# The density model works in the true-of-date frame, so the Sun's
# right ascension and declination must be of date too; sunPos is
# GCRF, which put the diurnal bulge 0.37 deg off in 2026.
r_sun = _T @ sunPos(t)
r_tod = _T @ r
v_tod = _T @ v

Expand All @@ -425,10 +430,9 @@ def __call__(self, r, v, t, _T=None, **kwargs):
dec_sun
)
if not np.isfinite(density):
print(f"r_tod = {r_tod}")
print(f"ra_sun = {ra_sun}")
print(f"dec_sun = {dec_sun}")
raise ValueError("non finite density")
raise ValueError(
f"non finite density at r_tod = {r_tod}, ra_sun = {ra_sun}, dec_sun = {dec_sun}"
)
a_tod = -0.5 * kw['CD'] * kw['area'] / kw['mass'] * density * v_rel * norm(v_rel)
return _T.T @ a_tod

Expand Down
Loading
Loading