Skip to content

Commit ecba79e

Browse files
authored
python-sgp4 compatability layer (#70)
* python-sgp4 compatability layer * doc update
1 parent 1cdd72d commit ecba79e

20 files changed

Lines changed: 2137 additions & 1009 deletions

.github/workflows/ci.yaml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,48 @@ jobs:
111111
print(f'Batch: {positions.shape}')
112112
"
113113
114+
- name: Test python-sgp4 compatible API
115+
run: |
116+
pip install sgp4
117+
python -c "
118+
from astroz.api import Satrec, SatrecArray, jday, WGS72
119+
from sgp4.api import Satrec as Sgp4Satrec, jday as sgp4_jday, WGS72 as SGP4_WGS72
120+
import numpy as np
121+
122+
line1 = '1 25544U 98067A 24127.82853009 .00015698 00000+0 27310-3 0 9995'
123+
line2 = '2 25544 51.6393 160.4574 0003580 140.6673 205.7250 15.50957674452123'
124+
125+
# Test Satrec
126+
sat = Satrec.twoline2rv(line1, line2, WGS72)
127+
print(f'Satrec: satnum={sat.satnum}, error={sat.error}')
128+
129+
# Test jday
130+
jd, fr = jday(2024, 5, 6, 12, 0, 0.0)
131+
print(f'jday: {jd} + {fr}')
132+
133+
# Test sgp4
134+
e, r, v = sat.sgp4(jd, fr)
135+
print(f'sgp4: error={e}, pos=({r[0]:.1f}, {r[1]:.1f}, {r[2]:.1f})')
136+
137+
# Test sgp4_array
138+
jd_arr = np.full(100, jd)
139+
fr_arr = fr + np.arange(100) / 1440.0
140+
e, r, v = sat.sgp4_array(jd_arr, fr_arr)
141+
print(f'sgp4_array: shape={r.shape}')
142+
143+
# Test SatrecArray
144+
arr = SatrecArray([sat])
145+
e, r, v = arr.sgp4(jd_arr, fr_arr)
146+
print(f'SatrecArray: shape={r.shape}')
147+
148+
# Accuracy test vs python-sgp4
149+
sgp4_sat = Sgp4Satrec.twoline2rv(line1, line2, SGP4_WGS72)
150+
az_e, az_r, az_v = sat.sgp4(jd, fr)
151+
sg_e, sg_r, sg_v = sgp4_sat.sgp4(jd, fr)
152+
pos_diff = np.linalg.norm(np.array(az_r) - np.array(sg_r))
153+
assert pos_diff < 0.001, f'Position error {pos_diff*1000:.1f}m exceeds 1mm'
154+
print(f'Accuracy: {pos_diff*1000:.3f}mm (< 1mm OK)')
155+
"
156+
114157
- name: Run Python example
115158
run: python examples/python_sgp4.py

.github/workflows/python.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,19 @@ jobs:
119119
pos = propagate(tle_text, [30.0])
120120
print(f'Position: {pos[0, 0]}')
121121
"
122+
python -c "
123+
from astroz.api import Satrec, SatrecArray, jday, WGS72
124+
import numpy as np
125+
line1 = '1 25544U 98067A 24127.82853009 .00015698 00000+0 27310-3 0 9995'
126+
line2 = '2 25544 51.6393 160.4574 0003580 140.6673 205.7250 15.50957674452123'
127+
sat = Satrec.twoline2rv(line1, line2, WGS72)
128+
jd, fr = jday(2024, 5, 6, 12, 0, 0.0)
129+
e, r, v = sat.sgp4(jd, fr)
130+
print(f'astroz.api: pos=({r[0]:.1f}, {r[1]:.1f}, {r[2]:.1f})')
131+
arr = SatrecArray([sat])
132+
e, r, v = arr.sgp4(np.array([jd]), np.array([fr]))
133+
print(f'SatrecArray: shape={r.shape}')
134+
"
122135
123136
- name: Upload wheels
124137
uses: actions/upload-artifact@v4

README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,54 @@ The [Cesium visualization example](examples/README.md) propagates the entire act
5353
pip install astroz
5454
```
5555

56+
#### python-sgp4 Compatible API (Recommended)
57+
58+
Drop-in replacement for [python-sgp4](https://github.com/brandon-rhodes/python-sgp4). Just change the import for instant speedup:
59+
60+
```python
61+
# Before # After
62+
from sgp4.api import Satrec, jday → from astroz.api import Satrec, jday
63+
```
64+
65+
| Your Code | python-sgp4 | astroz | Speedup |
66+
|-----------|-------------|--------|---------|
67+
| `sat.sgp4()` loop | 1.3M/s | 2.5M/s | **2x** |
68+
| `sat.sgp4_array()` | 2.7M/s | 15M/s | **5x** |
69+
| `SatrecArray.sgp4()` | 3M/s | 290M/s | **100x** |
70+
71+
See [migration guide](bindings/python/README.md#migrating-from-python-sgp4) for optimization tips.
72+
73+
```python
74+
from astroz.api import Satrec, SatrecArray, jday, WGS72
75+
import numpy as np
76+
77+
# Single satellite (same syntax as python-sgp4)
78+
line1 = "1 25544U 98067A 24127.82853009 .00015698 00000+0 27310-3 0 9995"
79+
line2 = "2 25544 51.6393 160.4574 0003580 140.6673 205.7250 15.50957674452123"
80+
sat = Satrec.twoline2rv(line1, line2, WGS72)
81+
82+
jd, fr = jday(2024, 5, 6, 12, 0, 0.0)
83+
error, position, velocity = sat.sgp4(jd, fr)
84+
85+
# Batch propagation (270-330M props/sec with SIMD)
86+
sat_array = SatrecArray([sat1, sat2, ...]) # List of Satrec objects
87+
88+
# Single time point (scalars)
89+
e, r, v = sat_array.sgp4(2460000.5, 0.5)
90+
91+
# Multiple time points (arrays)
92+
jd = np.full(1440, 2460000.5)
93+
fr = np.linspace(0, 1, 1440)
94+
e, r, v = sat_array.sgp4(jd, fr) # (n_sats, n_times, 3)
95+
96+
# Skip velocities for 30% faster propagation
97+
e, r, _ = sat_array.sgp4(jd, fr, velocities=False)
98+
```
99+
100+
#### High-Level API
101+
102+
Convenience functions for common workflows:
103+
56104
```python
57105
from astroz import propagate, Constellation
58106
import numpy as np

benchmarks/python_bench.py

Lines changed: 0 additions & 92 deletions
This file was deleted.

0 commit comments

Comments
 (0)