keplemon 3.1.1__cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. keplemon/.DS_Store +0 -0
  2. keplemon/._.DS_Store +0 -0
  3. keplemon/._arm +0 -0
  4. keplemon/._libastrofunc.so +0 -0
  5. keplemon/._libdllmain.so +0 -0
  6. keplemon/._libelops.so +0 -0
  7. keplemon/._libenvconst.so +0 -0
  8. keplemon/._libextephem.so +0 -0
  9. keplemon/._libobs.so +0 -0
  10. keplemon/._libsatstate.so +0 -0
  11. keplemon/._libsensor.so +0 -0
  12. keplemon/._libsgp4prop.so +0 -0
  13. keplemon/._libspvec.so +0 -0
  14. keplemon/._libtimefunc.so +0 -0
  15. keplemon/._libtle.so +0 -0
  16. keplemon/._libvcm.so +0 -0
  17. keplemon/EGM-2008.GEO +2563 -0
  18. keplemon/EGM-96.GEO +2563 -0
  19. keplemon/JPLcon_1950_2050.405 +392370 -0
  20. keplemon/SGP4_Open_License.txt +186 -0
  21. keplemon/WGS84-70.GEO +2563 -0
  22. keplemon/__init__.py +33 -0
  23. keplemon/__init__.pyi +54 -0
  24. keplemon/__main__.py +20 -0
  25. keplemon/_keplemon.abi3.so +0 -0
  26. keplemon/bodies.py +8 -0
  27. keplemon/bodies.pyi +367 -0
  28. keplemon/catalogs.py +5 -0
  29. keplemon/catalogs.pyi +19 -0
  30. keplemon/elements.py +39 -0
  31. keplemon/elements.pyi +521 -0
  32. keplemon/enums.py +21 -0
  33. keplemon/enums.pyi +120 -0
  34. keplemon/estimation.py +9 -0
  35. keplemon/estimation.pyi +200 -0
  36. keplemon/events.py +17 -0
  37. keplemon/events.pyi +103 -0
  38. keplemon/exceptions.py +5 -0
  39. keplemon/libastrofunc.so +0 -0
  40. keplemon/libdllmain.so +0 -0
  41. keplemon/libelops.so +0 -0
  42. keplemon/libenvconst.so +0 -0
  43. keplemon/libextephem.so +0 -0
  44. keplemon/libobs.so +0 -0
  45. keplemon/libsatstate.so +0 -0
  46. keplemon/libsensor.so +0 -0
  47. keplemon/libsgp4prop.so +0 -0
  48. keplemon/libspvec.so +0 -0
  49. keplemon/libtimefunc.so +0 -0
  50. keplemon/libtle.so +0 -0
  51. keplemon/libvcm.so +0 -0
  52. keplemon/propagation.py +15 -0
  53. keplemon/propagation.pyi +50 -0
  54. keplemon/py.typed +0 -0
  55. keplemon/time.py +96 -0
  56. keplemon/time.pyi +293 -0
  57. keplemon/time_constants.dat +19472 -0
  58. keplemon-3.1.1.dist-info/METADATA +21 -0
  59. keplemon-3.1.1.dist-info/RECORD +76 -0
  60. keplemon-3.1.1.dist-info/WHEEL +5 -0
  61. keplemon-3.1.1.dist-info/entry_points.txt +2 -0
  62. keplemon.libs/libastrofunc-d5d29f1a.so +0 -0
  63. keplemon.libs/libdllmain-83b073db.so +0 -0
  64. keplemon.libs/libelops-d6961cbd.so +0 -0
  65. keplemon.libs/libenvconst-5ff8e89b.so +0 -0
  66. keplemon.libs/libextephem-9ddad493.so +0 -0
  67. keplemon.libs/libgfortran-daac5196.so.5 +0 -0
  68. keplemon.libs/libgomp-d22c30c5.so.1 +0 -0
  69. keplemon.libs/libobs-acba28cb.so +0 -0
  70. keplemon.libs/libsatstate-a0706992.so +0 -0
  71. keplemon.libs/libsensor-15ffa85c.so +0 -0
  72. keplemon.libs/libsgp4prop-8300f9d3.so +0 -0
  73. keplemon.libs/libspvec-b3cef8a2.so +0 -0
  74. keplemon.libs/libtimefunc-d4915652.so +0 -0
  75. keplemon.libs/libtle-72004375.so +0 -0
  76. keplemon.libs/libvcm-460d66c8.so +0 -0
@@ -0,0 +1,200 @@
1
+ # flake8: noqa
2
+ from typing import Optional
3
+
4
+ from keplemon.elements import TopocentricElements, CartesianVector
5
+ from keplemon.time import Epoch
6
+ from keplemon.bodies import Satellite, Sensor, Constellation
7
+ from keplemon.enums import KeplerianType, AssociationConfidence
8
+
9
+ class Covariance:
10
+ sigmas: list[float]
11
+ """"""
12
+
13
+ class ObservationAssociation:
14
+ observation_id: str
15
+ satellite_id: str
16
+ residual: "ObservationResidual"
17
+ confidence: "AssociationConfidence"
18
+
19
+ class Observation:
20
+ """
21
+ Args:
22
+ sensor: Sensor that made the observation
23
+ epoch: Time of the observation
24
+ observed_teme_topocentric: Topocentric elements of the satellite at the time of observation
25
+ observer_teme_position: Position of the observer in TEME coordinates
26
+ """
27
+
28
+ id: str
29
+ """Unique identifier for the observation"""
30
+
31
+ sensor: Sensor
32
+ """Sensor which produced the observation"""
33
+
34
+ epoch: Epoch
35
+ """Time the measurement was observed"""
36
+
37
+ range: Optional[float]
38
+ """Observed range from the sensor to the satellite in **_kilometers_**"""
39
+
40
+ range_rate: Optional[float]
41
+ """Observed range rate from the sensor to the satellite in **_kilometers per second_**"""
42
+
43
+ right_ascension: float
44
+ """Observed TEME right ascension in **_degrees_**"""
45
+
46
+ declination: float
47
+ """Observed TEME declination in **_degrees_**"""
48
+
49
+ right_ascension_rate: Optional[float]
50
+ """Observed right ascension rate in **_degrees per second_**"""
51
+
52
+ declination_rate: Optional[float]
53
+ """Observed declination rate in **_degrees per second_**"""
54
+
55
+ observed_satellite_id: Optional[str]
56
+ """Tagged satellite ID of the observation"""
57
+
58
+ def __init__(
59
+ self,
60
+ sensor: Sensor,
61
+ epoch: Epoch,
62
+ observed_teme_topocentric: TopocentricElements,
63
+ observer_teme_position: CartesianVector,
64
+ ) -> None: ...
65
+ @staticmethod
66
+ def from_saal_files(sensor_file: str, observation_file: str) -> list["Observation"]: ...
67
+ def get_residual(self, sat: Satellite) -> Optional[ObservationResidual]:
68
+ """
69
+ Calculate the residual of the observation with respect to a given satellite state.
70
+
71
+ !!! note
72
+ If an error occurs during propagation of the satellite state, this method will return None.
73
+
74
+ Args:
75
+ sat: Expected satellite state
76
+
77
+ Returns:
78
+ Calculated residual
79
+ """
80
+ ...
81
+
82
+ def get_associations(self, sats: Constellation) -> list[ObservationAssociation]:
83
+ """
84
+ Calculate the associations of the observation with respect to a given constellation of satellites.
85
+
86
+ Args:
87
+ sats: Constellation of satellites to compare against
88
+
89
+ Returns:
90
+ List of possible observation associations
91
+ """
92
+ ...
93
+
94
+ class ObservationResidual:
95
+ range: float
96
+ """Euclidean distance between the observed and expected state in **_kilometers_**"""
97
+
98
+ radial: float
99
+ """Radial distance between the observed and expected state in **_kilometers_**"""
100
+
101
+ in_track: float
102
+ """In-track distance between the observed and expected state in **_kilometers_**"""
103
+
104
+ cross_track: float
105
+ """Cross-track distance between the observed and expected state in **_kilometers_**"""
106
+
107
+ velocity: float
108
+ """Velocity magnitude difference between the observed and expected state in **_kilometers per second_**"""
109
+
110
+ radial_velocity: float
111
+ """Radial velocity difference between the observed and expected state in **_kilometers per second_**"""
112
+
113
+ in_track_velocity: float
114
+ """In-track velocity difference between the observed and expected state in **_kilometers per second_**"""
115
+
116
+ cross_track_velocity: float
117
+ """Cross-track velocity difference between the observed and expected state in **_kilometers per second_**"""
118
+
119
+ time: float
120
+ """Time difference between the observed and expected state in **_seconds_**"""
121
+
122
+ beta: float
123
+ """Out-of-plane difference between the observed and expected state in **_degrees_**"""
124
+
125
+ height: float
126
+ """Height difference between the observed and expected state in **_kilometers_**"""
127
+
128
+ class BatchLeastSquares:
129
+ """
130
+ Args:
131
+ obs: List of observations to be used in the estimation
132
+ a_priori: A priori satellite state
133
+ """
134
+
135
+ converged: bool
136
+ """Indicates if the solution meets the tolerance criteria"""
137
+
138
+ max_iterations: int
139
+ """Maximum number of iterations to perform when solving if the tolerance is not met"""
140
+
141
+ iteration_count: int
142
+ """Number of iterations performed to reach the solution"""
143
+
144
+ current_estimate: Satellite
145
+ """Current estimate of the satellite state after iterating or solving"""
146
+
147
+ rms: Optional[float]
148
+ """Root mean square of the residuals in **_kilometers_**"""
149
+
150
+ weighted_rms: Optional[float]
151
+ """Unitless weighted root mean square of the residuals"""
152
+
153
+ estimate_srp: bool
154
+ """Flag to indicate if solar radiation pressure should be estimated
155
+
156
+ !!! warning
157
+ This currently has unexpected behavior if solving for output_types other than XP
158
+ """
159
+
160
+ estimate_drag: bool
161
+ """Flag to indicate if atmospheric drag should be estimated
162
+
163
+ !!! warning
164
+ This currently has unexpected behavior if solving for output_types other than XP
165
+ """
166
+
167
+ a_priori: Satellite
168
+ """A priori satellite state used to initialize the estimation"""
169
+
170
+ observations: list[Observation]
171
+ """List of observations used in the estimation"""
172
+
173
+ residuals: list[tuple[Epoch, ObservationResidual]]
174
+ """List of residuals for each observation compared to the current estimate"""
175
+
176
+ covariance: Optional[Covariance]
177
+ """UVW covariance matrix of the current estimate in **_kilometers_** and **_kilometers per second_**"""
178
+
179
+ output_type: KeplerianType
180
+ """Type of Keplerian elements to be used in the output state"""
181
+
182
+ eccentricity_constraint_weight: Optional[float]
183
+ """Tikhonov weight that keeps equinoctial a_f/a_g (eccentricity) near the a priori state"""
184
+
185
+ def __init__(
186
+ self,
187
+ obs: list[Observation],
188
+ a_priori: Satellite,
189
+ ) -> None: ...
190
+ def solve(self) -> None:
191
+ """Iterate until the solution converges or the maximum number of iterations is reached."""
192
+ ...
193
+
194
+ def iterate(self) -> None:
195
+ """Perform a single iteration of the estimation process."""
196
+ ...
197
+
198
+ def reset(self) -> None:
199
+ """Reset the estimation process to the initial state."""
200
+ ...
keplemon/events.py ADDED
@@ -0,0 +1,17 @@
1
+ from keplemon._keplemon.events import ( # type: ignore
2
+ CloseApproach,
3
+ CloseApproachReport,
4
+ HorizonAccess,
5
+ HorizonAccessReport,
6
+ FieldOfViewCandidate,
7
+ FieldOfViewReport,
8
+ )
9
+
10
+ __all__ = [
11
+ "CloseApproach",
12
+ "CloseApproachReport",
13
+ "HorizonAccess",
14
+ "HorizonAccessReport",
15
+ "FieldOfViewCandidate",
16
+ "FieldOfViewReport",
17
+ ]
keplemon/events.pyi ADDED
@@ -0,0 +1,103 @@
1
+ # flake8: noqa
2
+ from keplemon.time import Epoch, TimeSpan
3
+ from keplemon.elements import HorizonState, CartesianVector, TopocentricElements
4
+ from keplemon.enums import ReferenceFrame
5
+
6
+ class FieldOfViewCandidate:
7
+ satellite_id: str
8
+ """ID of the candidate satellite"""
9
+
10
+ direction: TopocentricElements
11
+ """Measured direction to the candidate satellite in the sensor's topocentric frame"""
12
+
13
+ class FieldOfViewReport:
14
+ epoch: Epoch
15
+ """UTC epoch of the field of view report"""
16
+
17
+ sensor_position: CartesianVector
18
+ """TEME position of the sensor in the observatory's topocentric frame in **_kilometers_**"""
19
+
20
+ sensor_direction: TopocentricElements
21
+ """Direction of the sensor in the observatory's topocentric frame"""
22
+
23
+ fov_angle: float
24
+ """Field of view angle of the sensor in **_degrees_**"""
25
+
26
+ candidates: list[FieldOfViewCandidate]
27
+ """List of candidate satellites within the field of view"""
28
+
29
+ reference_frame: ReferenceFrame
30
+ """Reference frame of the output direction elements"""
31
+
32
+ class CloseApproach:
33
+ epoch: Epoch
34
+ """UTC epoch of the close approach"""
35
+
36
+ primary_id: str
37
+ """Satellite ID of the primary body in the close approach"""
38
+
39
+ secondary_id: str
40
+ """Satellite ID of the secondary body in the close approach"""
41
+
42
+ distance: float
43
+ """Distance between the two bodies in **_kilometers_**"""
44
+
45
+ class CloseApproachReport:
46
+ """
47
+ Args:
48
+ start: CA screening start time
49
+ end: CA screening end time
50
+ distance_threshold: Distance threshold for CA screening in **_kilometers_**
51
+ """
52
+
53
+ close_approaches: list[CloseApproach]
54
+ """List of close approaches found during the screening"""
55
+
56
+ distance_threshold: float
57
+ def __init__(self, start: Epoch, end: Epoch, distance_threshold: float) -> None: ...
58
+
59
+ class HorizonAccess:
60
+
61
+ satellite_id: str
62
+ """ID of the satellite for which the access is calculated"""
63
+
64
+ observatory_id: str
65
+ """ID of the observatory for which the access is calculated"""
66
+
67
+ start: HorizonState
68
+ """State of the satellite at the start of the access period"""
69
+
70
+ end: HorizonState
71
+ """State of the satellite at the end of the access period"""
72
+
73
+ class HorizonAccessReport:
74
+ """
75
+ Args:
76
+ start: UTC epoch of the start of the access report
77
+ end: UTC epoch of the end of the access report
78
+ min_elevation: Minimum elevation angle for access in **_degrees_**
79
+ min_duration: Minimum duration of access
80
+ """
81
+
82
+ accesses: list[HorizonAccess]
83
+ """List of horizon accesses found during the screening"""
84
+
85
+ elevation_threshold: float
86
+ """Minimum elevation angle for access in **_degrees_**"""
87
+
88
+ start: Epoch
89
+ """UTC epoch of the start of the access report"""
90
+
91
+ end: Epoch
92
+ """UTC epoch of the end of the access report"""
93
+
94
+ duration_threshold: TimeSpan
95
+ """Minimum duration of a valid access"""
96
+
97
+ def __init__(
98
+ self,
99
+ start: Epoch,
100
+ end: Epoch,
101
+ min_elevation: float,
102
+ min_duration: TimeSpan,
103
+ ) -> None: ...
keplemon/exceptions.py ADDED
@@ -0,0 +1,5 @@
1
+ from keplemon._keplemon.exceptions import ( # type: ignore
2
+ SAALError,
3
+ )
4
+
5
+ __all__ = ["SAALError"]
Binary file
keplemon/libdllmain.so ADDED
Binary file
keplemon/libelops.so ADDED
Binary file
Binary file
Binary file
keplemon/libobs.so ADDED
Binary file
Binary file
keplemon/libsensor.so ADDED
Binary file
Binary file
keplemon/libspvec.so ADDED
Binary file
Binary file
keplemon/libtle.so ADDED
Binary file
keplemon/libvcm.so ADDED
Binary file
@@ -0,0 +1,15 @@
1
+ from keplemon._keplemon.propagation import ( # type: ignore
2
+ ForceProperties,
3
+ InertialPropagator,
4
+ SGP4Output,
5
+ b_star_to_drag_coefficient,
6
+ drag_coefficient_to_b_star,
7
+ )
8
+
9
+ __all__ = [
10
+ "ForceProperties",
11
+ "InertialPropagator",
12
+ "SGP4Output",
13
+ "b_star_to_drag_coefficient",
14
+ "drag_coefficient_to_b_star",
15
+ ]
@@ -0,0 +1,50 @@
1
+ # flake8: noqa
2
+ from __future__ import annotations
3
+
4
+ from typing import Optional
5
+
6
+ from keplemon.elements import CartesianState, GeodeticPosition, KeplerianElements, KeplerianState, TLE
7
+ from keplemon.time import Epoch
8
+
9
+ class ForceProperties:
10
+ srp_coefficient: float
11
+ drag_coefficient: float
12
+ mass: float
13
+ srp_area: float
14
+ drag_area: float
15
+ mean_motion_dot: float
16
+ mean_motion_dot_dot: float
17
+ def __init__(
18
+ self,
19
+ srp_coefficient: float,
20
+ srp_area: float,
21
+ drag_coefficient: float,
22
+ drag_area: float,
23
+ mass: float,
24
+ mean_motion_dot: float,
25
+ mean_motion_dot_dot: float,
26
+ ) -> None: ...
27
+
28
+ class InertialPropagator:
29
+ @staticmethod
30
+ def from_tle(tle: TLE) -> InertialPropagator: ...
31
+
32
+ def get_cartesian_state_at_epoch(self, epoch: Epoch) -> Optional[CartesianState]: ...
33
+ def get_keplerian_state_at_epoch(self, epoch: Epoch) -> Optional[KeplerianState]: ...
34
+
35
+ keplerian_state: KeplerianState
36
+ force_properties: ForceProperties
37
+
38
+ class SGP4Output:
39
+ cartesian_state: CartesianState
40
+ mean_elements: KeplerianElements
41
+ osculating_elements: KeplerianElements
42
+ geodetic_position: GeodeticPosition
43
+
44
+ def b_star_to_drag_coefficient(b_star: float) -> float:
45
+ """Convert B* to drag coefficient."""
46
+ ...
47
+
48
+ def drag_coefficient_to_b_star(drag_coefficient: float) -> float:
49
+ """Convert drag coefficient to B*."""
50
+ ...
keplemon/py.typed ADDED
File without changes
keplemon/time.py ADDED
@@ -0,0 +1,96 @@
1
+ from keplemon._keplemon.time import ( # type: ignore
2
+ TimeSpan,
3
+ TimeComponents,
4
+ Epoch,
5
+ )
6
+ import requests # type: ignore
7
+ from datetime import datetime
8
+ from keplemon._keplemon.enums import TimeSystem # type: ignore
9
+
10
+ __all__ = [
11
+ "TimeSpan",
12
+ "TimeComponents",
13
+ "Epoch",
14
+ "request_time_constants_update",
15
+ ]
16
+
17
+
18
+ def request_time_constants_update(output_path: str) -> None:
19
+ finals = requests.get("https://maia.usno.navy.mil/ser7/finals.all").text.splitlines()
20
+
21
+ leap_seconds = requests.get("https://maia.usno.navy.mil/ser7/tai-utc.dat").text.splitlines()
22
+
23
+ month_map = {
24
+ "JAN": 1,
25
+ "FEB": 2,
26
+ "MAR": 3,
27
+ "APR": 4,
28
+ "MAY": 5,
29
+ "JUN": 6,
30
+ "JUL": 7,
31
+ "AUG": 8,
32
+ "SEP": 9,
33
+ "OCT": 10,
34
+ "NOV": 11,
35
+ "DEC": 12,
36
+ }
37
+ leap_second_map = {}
38
+ for line in leap_seconds:
39
+ yy = int(line[3:5].strip())
40
+ mm = month_map[line[6:9]]
41
+ dd = int(line[10:12].strip())
42
+ time_comps = TimeComponents(yy, mm, dd, 0, 0, 0)
43
+ current_epoch = Epoch.from_time_components(time_comps, TimeSystem.UTC)
44
+ ds50 = int(current_epoch.days_since_1950)
45
+ leap = float(line[38:48].strip())
46
+ leap_second_map[ds50] = leap
47
+
48
+ time_constant_lines: list[str] = []
49
+ sorted_leap_seconds = sorted(leap_second_map, reverse=True)
50
+ ut1 = 0.0
51
+ prev_ut1_utc = 0.0
52
+ prev_time = 0
53
+ prev_leap = 0.0
54
+ for line in finals:
55
+
56
+ if len(line.strip()) < 68:
57
+ break
58
+
59
+ yy = int(line[0:2].strip())
60
+ mm = int(line[2:4].strip())
61
+ dd = int(line[4:6].strip())
62
+ if yy < 50:
63
+ yyyy = 2000 + yy
64
+ else:
65
+ yyyy = 1900 + yy
66
+ ymd = datetime(yyyy, mm, dd).strftime("%d-%b-%y")
67
+
68
+ time_comps = TimeComponents(yy, mm, dd, 0, 0, 0)
69
+ current_epoch = Epoch.from_time_components(time_comps, TimeSystem.UTC)
70
+ ds50 = int(current_epoch.days_since_1950)
71
+ leap = 0.0
72
+ for leap_ds50 in sorted_leap_seconds:
73
+ if ds50 >= leap_ds50:
74
+ leap = leap_second_map[leap_ds50]
75
+ break
76
+
77
+ ut1 = float(line[58:68].strip())
78
+ if prev_time == 0:
79
+ ut1_r = 0.0
80
+ else:
81
+ ut1_r = (ut1 - prev_ut1_utc) / (ds50 - prev_time)
82
+ ut1_r = (ut1_r - (leap - prev_leap)) * 1e3
83
+
84
+ p_x = float(line[18:27].strip())
85
+ p_y = float(line[37:46].strip())
86
+
87
+ doy = current_epoch.day_of_year
88
+ time_constant_lines.append(
89
+ f" {yy:02d} {doy:03.0f} {ymd} {leap:3.0f} {ut1:8.5f} {ut1_r:6.3f} {p_x:7.4f} {p_y:7.4f}\n"
90
+ )
91
+ prev_time = ds50
92
+ prev_ut1_utc = ut1
93
+ prev_leap = leap
94
+
95
+ with open(output_path, "w") as f:
96
+ f.writelines(time_constant_lines)