adam-core 0.1.0__tar.gz

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 (68) hide show
  1. adam_core-0.1.0/LICENSE.md +60 -0
  2. adam_core-0.1.0/PKG-INFO +244 -0
  3. adam_core-0.1.0/README.md +230 -0
  4. adam_core-0.1.0/adam_core/__init__.py +0 -0
  5. adam_core-0.1.0/adam_core/constants.py +60 -0
  6. adam_core-0.1.0/adam_core/coordinates/__init__.py +35 -0
  7. adam_core-0.1.0/adam_core/coordinates/cartesian.py +360 -0
  8. adam_core-0.1.0/adam_core/coordinates/cometary.py +374 -0
  9. adam_core-0.1.0/adam_core/coordinates/conversions.py +176 -0
  10. adam_core-0.1.0/adam_core/coordinates/covariances.py +548 -0
  11. adam_core-0.1.0/adam_core/coordinates/io.py +120 -0
  12. adam_core-0.1.0/adam_core/coordinates/jacobian.py +69 -0
  13. adam_core-0.1.0/adam_core/coordinates/keplerian.py +351 -0
  14. adam_core-0.1.0/adam_core/coordinates/origin.py +111 -0
  15. adam_core-0.1.0/adam_core/coordinates/residuals.py +214 -0
  16. adam_core-0.1.0/adam_core/coordinates/spherical.py +301 -0
  17. adam_core-0.1.0/adam_core/coordinates/tests/__init__.py +0 -0
  18. adam_core-0.1.0/adam_core/coordinates/tests/test_benchmarks.py +39 -0
  19. adam_core-0.1.0/adam_core/coordinates/tests/test_cartesian.py +32 -0
  20. adam_core-0.1.0/adam_core/coordinates/tests/test_covariances.py +105 -0
  21. adam_core-0.1.0/adam_core/coordinates/tests/test_origin.py +54 -0
  22. adam_core-0.1.0/adam_core/coordinates/tests/test_residuals.py +194 -0
  23. adam_core-0.1.0/adam_core/coordinates/tests/test_spherical.py +38 -0
  24. adam_core-0.1.0/adam_core/coordinates/tests/test_transforms_spherical.py +93 -0
  25. adam_core-0.1.0/adam_core/coordinates/times.py +28 -0
  26. adam_core-0.1.0/adam_core/coordinates/transform.py +1324 -0
  27. adam_core-0.1.0/adam_core/dynamics/__init__.py +4 -0
  28. adam_core-0.1.0/adam_core/dynamics/barker.py +33 -0
  29. adam_core-0.1.0/adam_core/dynamics/kepler.py +204 -0
  30. adam_core-0.1.0/adam_core/dynamics/tests/__init__.py +0 -0
  31. adam_core-0.1.0/adam_core/dynamics/tests/test_kepler.py +194 -0
  32. adam_core-0.1.0/adam_core/dynamics/tests/test_tisserand.py +50 -0
  33. adam_core-0.1.0/adam_core/dynamics/tisserand.py +65 -0
  34. adam_core-0.1.0/adam_core/orbits/__init__.py +3 -0
  35. adam_core-0.1.0/adam_core/orbits/classification.py +51 -0
  36. adam_core-0.1.0/adam_core/orbits/orbits.py +70 -0
  37. adam_core-0.1.0/adam_core/orbits/query/__init__.py +3 -0
  38. adam_core-0.1.0/adam_core/orbits/query/horizons.py +238 -0
  39. adam_core-0.1.0/adam_core/orbits/query/sbdb.py +237 -0
  40. adam_core-0.1.0/adam_core/orbits/query/tests/__init__.py +43 -0
  41. adam_core-0.1.0/adam_core/orbits/query/tests/test_sbdb.py +107 -0
  42. adam_core-0.1.0/adam_core/orbits/tests/__init__.py +0 -0
  43. adam_core-0.1.0/adam_core/orbits/tests/test_benchmarks.py +21 -0
  44. adam_core-0.1.0/adam_core/orbits/tests/test_orbits.py +43 -0
  45. adam_core-0.1.0/adam_core/propagator/__init__.py +4 -0
  46. adam_core-0.1.0/adam_core/propagator/propagator.py +176 -0
  47. adam_core-0.1.0/adam_core/propagator/pyoorb.py +288 -0
  48. adam_core-0.1.0/adam_core/propagator/tests/__init__.py +0 -0
  49. adam_core-0.1.0/adam_core/propagator/tests/test_utils.py +36 -0
  50. adam_core-0.1.0/adam_core/propagator/utils.py +72 -0
  51. adam_core-0.1.0/adam_core/utils/__init__.py +1 -0
  52. adam_core-0.1.0/adam_core/utils/helpers/__init__.py +2 -0
  53. adam_core-0.1.0/adam_core/utils/helpers/data/__init__.py +0 -0
  54. adam_core-0.1.0/adam_core/utils/helpers/data/sample_orbits.csv +28 -0
  55. adam_core-0.1.0/adam_core/utils/helpers/orbits.py +97 -0
  56. adam_core-0.1.0/adam_core/utils/helpers/tests/__init__.py +0 -0
  57. adam_core-0.1.0/adam_core/utils/helpers/tests/test_orbits.py +25 -0
  58. adam_core-0.1.0/adam_core/utils/mpc.py +473 -0
  59. adam_core-0.1.0/adam_core/utils/spice.py +105 -0
  60. adam_core-0.1.0/adam_core/utils/tests/__init__.py +0 -0
  61. adam_core-0.1.0/adam_core/utils/tests/test_mpc.py +213 -0
  62. adam_core-0.1.0/adam_core.egg-info/PKG-INFO +244 -0
  63. adam_core-0.1.0/adam_core.egg-info/SOURCES.txt +67 -0
  64. adam_core-0.1.0/adam_core.egg-info/dependency_links.txt +1 -0
  65. adam_core-0.1.0/adam_core.egg-info/requires.txt +20 -0
  66. adam_core-0.1.0/adam_core.egg-info/top_level.txt +1 -0
  67. adam_core-0.1.0/pyproject.toml +25 -0
  68. adam_core-0.1.0/setup.cfg +54 -0
@@ -0,0 +1,60 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022-2023, Asteroid Institute
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
19
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21
+ OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+
24
+ The following files are originally derived from the THOR project:
25
+
26
+ adam_core/coordinates/*
27
+ adam_core/constants.py
28
+ adam_core/utils/*
29
+
30
+ THOR maintains a 3-Clause License.
31
+
32
+ BSD 3-Clause License
33
+
34
+ Copyright (c) 2018-2023, Joachim Moeyens
35
+ All rights reserved.
36
+
37
+ Redistribution and use in source and binary forms, with or without
38
+ modification, are permitted provided that the following conditions are met:
39
+
40
+ * Redistributions of source code must retain the above copyright notice, this
41
+ list of conditions and the following disclaimer.
42
+
43
+ * Redistributions in binary form must reproduce the above copyright notice,
44
+ this list of conditions and the following disclaimer in the documentation
45
+ and/or other materials provided with the distribution.
46
+
47
+ * Neither the name of the copyright holder nor the names of its
48
+ contributors may be used to endorse or promote products derived from
49
+ this software without specific prior written permission.
50
+
51
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
52
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
54
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
55
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
57
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
58
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
59
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,244 @@
1
+ Metadata-Version: 2.1
2
+ Name: adam_core
3
+ Version: 0.1.0
4
+ Summary: Core libraries for the ADAM platform
5
+ Author-email: Kathleen Kiker <kathleen@b612foundation.org>, Alec Koumjian <alec@b612foundation.org>, Joachim Moeyens <moeyensj@uw.edu>, Spencer Nelson <spencer@b612foundation.org>, Nate Tellis <nate@b612foundation.org>
6
+ Project-URL: Homepage, https://github.com/b612-asteroid-institute/adam_core
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+ Provides-Extra: tests
13
+ License-File: LICENSE.md
14
+
15
+ # Asteroid Institute ADAM Core
16
+
17
+ A set of shared astrodynamics libraries and utilities.
18
+
19
+ `adam_core` is used by a variety of library and services at Asteroid Institute. Sharing these common classes, types, and conversions amongst our tools ensures consistency and accuracy.
20
+
21
+ ## Usage
22
+
23
+ ### Orbits
24
+
25
+ To define an orbit:
26
+ ```python
27
+ from astropy.time import Time
28
+ from adam_core.coordinates import KeplerianCoordinates
29
+ from adam_core.coordinates import Times
30
+ from adam_core.coordinates import Origin
31
+ from adam_core.orbits import Orbits
32
+
33
+ keplerian_elements = KeplerianCoordinates.from_kwargs(
34
+ times=Times.from_astropy(
35
+ Time([59000.0], scale="tdb", format="mjd")
36
+ ),
37
+ a=[1.0],
38
+ e=[0.002],
39
+ i=[10.],
40
+ raan=[50.0],
41
+ ap=[20.0],
42
+ M=[30.0],
43
+ origin=Origin.from_kwargs(code=["SUN"]),
44
+ frame="ecliptic"
45
+ )
46
+ orbits = Orbits.from_kwargs(
47
+ orbit_ids=["1"],
48
+ object_ids=["Test Orbit"],
49
+ coordinates=keplerian_elements.to_cartesian(),
50
+ )
51
+ ```
52
+ Note that internally, all orbits are stored in Cartesian coordinates. Cartesian coordinates do not have any
53
+ singularities and are thus more robust for numerical integration. Any orbital element conversions to Cartesian
54
+ can be done on demand by calling `to_cartesian()` on the coordinates object.
55
+
56
+ The underlying orbits class is 2 dimensional and can store elements and covariances for multiple orbits.
57
+
58
+ ```python
59
+ from astropy.time import Time
60
+ from adam_core.coordinates import KeplerianCoordinates
61
+ from adam_core.coordinates import Times
62
+ from adam_core.coordinates import Origin
63
+ from adam_core.orbits import Orbits
64
+
65
+ keplerian_elements = KeplerianCoordinates.from_kwargs(
66
+ times=Times.from_astropy(
67
+ Time([59000.0, 60000.0], scale="tdb", format="mjd")
68
+ ),
69
+ a=[1.0, 3.0],
70
+ e=[0.002, 0.0],
71
+ i=[10., 30.],
72
+ raan=[50.0, 32.0],
73
+ ap=[20.0, 94.0],
74
+ M=[30.0, 159.0],
75
+ origin=Origin.from_kwargs(code=["SUN", "SUN"]),
76
+ frame="ecliptic"
77
+ )
78
+ orbits = Orbits.from_kwargs(
79
+ orbit_ids=["1", "2"],
80
+ object_ids=["Test Orbit 1", "Test Orbit 2"],
81
+ coordinates=keplerian_elements.to_cartesian(),
82
+ )
83
+ ```
84
+
85
+ Orbits can be easily converted to a pandas DataFrame:
86
+ ```python
87
+ orbits.to_dataframe()
88
+ orbit_ids object_ids times.jd1 times.jd2 x y z vx vy vz ... cov_vy_y cov_vy_z cov_vy_vx cov_vy_vy cov_vz_x cov_vz_y cov_vz_z cov_vz_vx cov_vz_vy cov_vz_vz
89
+ 0 1 Test Orbit 1 2459000.0 0.5 -0.166403 0.975273 0.133015 -0.016838 -0.003117 0.001921 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
90
+ 1 2 Test Orbit 2 2460000.0 0.5 0.572777 -2.571820 -1.434457 0.009387 0.002900 -0.001452 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
91
+ ```
92
+
93
+ Orbits can also be defined with uncertainties.
94
+ ```python
95
+ import numpy as np
96
+ from astropy.time import Time
97
+ from adam_core.coordinates import KeplerianCoordinates
98
+ from adam_core.coordinates import Times
99
+ from adam_core.coordinates import Origin
100
+ from adam_core.coordinates import CoordinateCovariances
101
+ from adam_core.orbits import Orbits
102
+
103
+ keplerian_elements = KeplerianCoordinates.from_kwargs(
104
+ times=Times.from_astropy(
105
+ Time([59000.0], scale="tdb", format="mjd")
106
+ ),
107
+ a=[1.0],
108
+ e=[0.002],
109
+ i=[10.],
110
+ raan=[50.0],
111
+ ap=[20.0],
112
+ M=[30.0],
113
+ covariances=CoordinateCovariances.from_sigmas(
114
+ np.array([[0.002, 0.001, 0.01, 0.01, 0.1, 0.1]])
115
+ ),
116
+ origin=Origin.from_kwargs(code=["SUN"]),
117
+ frame="ecliptic"
118
+ )
119
+
120
+ orbits = Orbits.from_kwargs(
121
+ orbit_ids=["1"],
122
+ object_ids=["Test Orbit with Uncertainties"],
123
+ coordinates=keplerian_elements.to_cartesian(),
124
+ )
125
+ orbits.to_dataframe(sigmas=True)
126
+ orbit_ids object_ids times.jd1 times.jd2 x y z vx vy vz ... cov_vy_y cov_vy_z cov_vy_vx cov_vy_vy cov_vz_x cov_vz_y cov_vz_z cov_vz_vx cov_vz_vy cov_vz_vz
127
+ 0 1 Test Orbit with Uncertainties 2459000.0 0.5 -0.166403 0.975273 0.133015 -0.016838 -0.003117 0.001921 ... 3.625729e-08 -1.059731e-08 -9.691716e-11 1.872922e-09 1.392222e-08 -1.759744e-09 -1.821839e-09 -7.865582e-11 2.237521e-10 3.971297e-11
128
+ ```
129
+
130
+ To query orbits from JPL Horizons:
131
+ ```python
132
+ from astropy.time import Time
133
+ from adam_core.orbits.query import query_horizons
134
+
135
+ times = Time([60000.0], scale="tdb", format="mjd")
136
+ object_ids = ["Duende", "Eros", "Ceres"]
137
+ orbits = query_horizons(object_ids, times)
138
+ ```
139
+
140
+ To query orbits from JPL SBDB:
141
+ ```python
142
+ from adam_core.orbits.query import query_sbdb
143
+
144
+ object_ids = ["Duende", "Eros", "Ceres"]
145
+ orbits = query_sbdb(object_ids)
146
+ ```
147
+
148
+ #### Orbital Element Conversions
149
+ Orbital elements can be accessed via the corresponding attribute. All conversions, including covariances, are done on demand and stored.
150
+
151
+ ```python
152
+ # Cartesian Elements
153
+ orbits.coordinates
154
+
155
+ # To convert to other representations
156
+ cometary_elements = orbits.coordinates.to_cometary()
157
+ keplerian_elements = orbits.coordinates.to_keplerian()
158
+ spherical_elements = orbits.coordinates.to_spherical()
159
+ ```
160
+
161
+ ### Propagator
162
+ The propagator class in `adam_core` provides a generalized interface to the supported orbit integrators and ephemeris generators. By default,
163
+ `adam_core` ships with PYOORB.
164
+
165
+ To propagate orbits with PYOORB (here we grab some orbits from Horizons first):
166
+ ```python
167
+ import numpy as np
168
+ from astropy.time import Time
169
+ from astropy import units as u
170
+ from adam_core.orbits.query import query_horizons
171
+ from adam_core.propagator import PYOORB
172
+
173
+ # Get orbit to propagate
174
+ initial_time = Time([60000.0], scale="tdb", format="mjd")
175
+ object_ids = ["Duende", "Eros", "Ceres"]
176
+ orbits = query_horizons(object_ids, initial_time)
177
+
178
+ # Make sure PYOORB is ready
179
+ propagator = PYOORB()
180
+
181
+ # Define propagation times
182
+ times = initial_time + np.arange(0, 100) * u.d
183
+
184
+ # Propagate orbits! This function supports multiprocessing for large
185
+ # propagation jobs.
186
+ propagated_orbits = propagator.propagate_orbits(
187
+ orbits,
188
+ times,
189
+ chunk_size=100,
190
+ num_jobs=1,
191
+ )
192
+ ```
193
+
194
+ ### Low-level APIs
195
+
196
+ Getting the heliocentric ecliptic state vector of a DE440 body at a given set of times (in this case the barycenter of the Jovian system):
197
+ ```python
198
+ import numpy as np
199
+ from astropy.time import Time
200
+
201
+ from adam_core.coordinates.origin import OriginCodes
202
+ from adam_core.utils.spice import get_perturber_state
203
+
204
+ states = get_perturber_state(
205
+ OriginCodes.JUPITER_BARYCENTER,
206
+ Time(np.arange(59000, 60000), format="mjd", scale="tdb"),
207
+ frame="ecliptic",
208
+ origin=OriginCodes.SUN,
209
+ )
210
+ ```
211
+
212
+ ## Package Structure
213
+
214
+ ```bash
215
+ adam_core
216
+ ├── constants.py # Shared constants
217
+ ├── coordinates # Coordinate classes and transformations
218
+ ├── dynamics # Numerical solutions
219
+ ├── orbits # Orbits class and query utilities
220
+ └── utils # Utility classes like Indexable or conversions like times_from_df
221
+ ```
222
+
223
+ ## Installation
224
+
225
+ ADAM Core is available on PyPI
226
+
227
+ ```bash
228
+ pip install adam_core
229
+ ```
230
+
231
+ ## Development
232
+
233
+ Development is made easy with our Docker container environment.
234
+
235
+ ```bash
236
+ # Build the container
237
+ docker compose build
238
+
239
+ # Run tests in the container
240
+ docker compose run adam_core pytest .
241
+
242
+ # Run a shell in the container
243
+ docker compose run adam_core bash
244
+ ```
@@ -0,0 +1,230 @@
1
+ # Asteroid Institute ADAM Core
2
+
3
+ A set of shared astrodynamics libraries and utilities.
4
+
5
+ `adam_core` is used by a variety of library and services at Asteroid Institute. Sharing these common classes, types, and conversions amongst our tools ensures consistency and accuracy.
6
+
7
+ ## Usage
8
+
9
+ ### Orbits
10
+
11
+ To define an orbit:
12
+ ```python
13
+ from astropy.time import Time
14
+ from adam_core.coordinates import KeplerianCoordinates
15
+ from adam_core.coordinates import Times
16
+ from adam_core.coordinates import Origin
17
+ from adam_core.orbits import Orbits
18
+
19
+ keplerian_elements = KeplerianCoordinates.from_kwargs(
20
+ times=Times.from_astropy(
21
+ Time([59000.0], scale="tdb", format="mjd")
22
+ ),
23
+ a=[1.0],
24
+ e=[0.002],
25
+ i=[10.],
26
+ raan=[50.0],
27
+ ap=[20.0],
28
+ M=[30.0],
29
+ origin=Origin.from_kwargs(code=["SUN"]),
30
+ frame="ecliptic"
31
+ )
32
+ orbits = Orbits.from_kwargs(
33
+ orbit_ids=["1"],
34
+ object_ids=["Test Orbit"],
35
+ coordinates=keplerian_elements.to_cartesian(),
36
+ )
37
+ ```
38
+ Note that internally, all orbits are stored in Cartesian coordinates. Cartesian coordinates do not have any
39
+ singularities and are thus more robust for numerical integration. Any orbital element conversions to Cartesian
40
+ can be done on demand by calling `to_cartesian()` on the coordinates object.
41
+
42
+ The underlying orbits class is 2 dimensional and can store elements and covariances for multiple orbits.
43
+
44
+ ```python
45
+ from astropy.time import Time
46
+ from adam_core.coordinates import KeplerianCoordinates
47
+ from adam_core.coordinates import Times
48
+ from adam_core.coordinates import Origin
49
+ from adam_core.orbits import Orbits
50
+
51
+ keplerian_elements = KeplerianCoordinates.from_kwargs(
52
+ times=Times.from_astropy(
53
+ Time([59000.0, 60000.0], scale="tdb", format="mjd")
54
+ ),
55
+ a=[1.0, 3.0],
56
+ e=[0.002, 0.0],
57
+ i=[10., 30.],
58
+ raan=[50.0, 32.0],
59
+ ap=[20.0, 94.0],
60
+ M=[30.0, 159.0],
61
+ origin=Origin.from_kwargs(code=["SUN", "SUN"]),
62
+ frame="ecliptic"
63
+ )
64
+ orbits = Orbits.from_kwargs(
65
+ orbit_ids=["1", "2"],
66
+ object_ids=["Test Orbit 1", "Test Orbit 2"],
67
+ coordinates=keplerian_elements.to_cartesian(),
68
+ )
69
+ ```
70
+
71
+ Orbits can be easily converted to a pandas DataFrame:
72
+ ```python
73
+ orbits.to_dataframe()
74
+ orbit_ids object_ids times.jd1 times.jd2 x y z vx vy vz ... cov_vy_y cov_vy_z cov_vy_vx cov_vy_vy cov_vz_x cov_vz_y cov_vz_z cov_vz_vx cov_vz_vy cov_vz_vz
75
+ 0 1 Test Orbit 1 2459000.0 0.5 -0.166403 0.975273 0.133015 -0.016838 -0.003117 0.001921 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
76
+ 1 2 Test Orbit 2 2460000.0 0.5 0.572777 -2.571820 -1.434457 0.009387 0.002900 -0.001452 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
77
+ ```
78
+
79
+ Orbits can also be defined with uncertainties.
80
+ ```python
81
+ import numpy as np
82
+ from astropy.time import Time
83
+ from adam_core.coordinates import KeplerianCoordinates
84
+ from adam_core.coordinates import Times
85
+ from adam_core.coordinates import Origin
86
+ from adam_core.coordinates import CoordinateCovariances
87
+ from adam_core.orbits import Orbits
88
+
89
+ keplerian_elements = KeplerianCoordinates.from_kwargs(
90
+ times=Times.from_astropy(
91
+ Time([59000.0], scale="tdb", format="mjd")
92
+ ),
93
+ a=[1.0],
94
+ e=[0.002],
95
+ i=[10.],
96
+ raan=[50.0],
97
+ ap=[20.0],
98
+ M=[30.0],
99
+ covariances=CoordinateCovariances.from_sigmas(
100
+ np.array([[0.002, 0.001, 0.01, 0.01, 0.1, 0.1]])
101
+ ),
102
+ origin=Origin.from_kwargs(code=["SUN"]),
103
+ frame="ecliptic"
104
+ )
105
+
106
+ orbits = Orbits.from_kwargs(
107
+ orbit_ids=["1"],
108
+ object_ids=["Test Orbit with Uncertainties"],
109
+ coordinates=keplerian_elements.to_cartesian(),
110
+ )
111
+ orbits.to_dataframe(sigmas=True)
112
+ orbit_ids object_ids times.jd1 times.jd2 x y z vx vy vz ... cov_vy_y cov_vy_z cov_vy_vx cov_vy_vy cov_vz_x cov_vz_y cov_vz_z cov_vz_vx cov_vz_vy cov_vz_vz
113
+ 0 1 Test Orbit with Uncertainties 2459000.0 0.5 -0.166403 0.975273 0.133015 -0.016838 -0.003117 0.001921 ... 3.625729e-08 -1.059731e-08 -9.691716e-11 1.872922e-09 1.392222e-08 -1.759744e-09 -1.821839e-09 -7.865582e-11 2.237521e-10 3.971297e-11
114
+ ```
115
+
116
+ To query orbits from JPL Horizons:
117
+ ```python
118
+ from astropy.time import Time
119
+ from adam_core.orbits.query import query_horizons
120
+
121
+ times = Time([60000.0], scale="tdb", format="mjd")
122
+ object_ids = ["Duende", "Eros", "Ceres"]
123
+ orbits = query_horizons(object_ids, times)
124
+ ```
125
+
126
+ To query orbits from JPL SBDB:
127
+ ```python
128
+ from adam_core.orbits.query import query_sbdb
129
+
130
+ object_ids = ["Duende", "Eros", "Ceres"]
131
+ orbits = query_sbdb(object_ids)
132
+ ```
133
+
134
+ #### Orbital Element Conversions
135
+ Orbital elements can be accessed via the corresponding attribute. All conversions, including covariances, are done on demand and stored.
136
+
137
+ ```python
138
+ # Cartesian Elements
139
+ orbits.coordinates
140
+
141
+ # To convert to other representations
142
+ cometary_elements = orbits.coordinates.to_cometary()
143
+ keplerian_elements = orbits.coordinates.to_keplerian()
144
+ spherical_elements = orbits.coordinates.to_spherical()
145
+ ```
146
+
147
+ ### Propagator
148
+ The propagator class in `adam_core` provides a generalized interface to the supported orbit integrators and ephemeris generators. By default,
149
+ `adam_core` ships with PYOORB.
150
+
151
+ To propagate orbits with PYOORB (here we grab some orbits from Horizons first):
152
+ ```python
153
+ import numpy as np
154
+ from astropy.time import Time
155
+ from astropy import units as u
156
+ from adam_core.orbits.query import query_horizons
157
+ from adam_core.propagator import PYOORB
158
+
159
+ # Get orbit to propagate
160
+ initial_time = Time([60000.0], scale="tdb", format="mjd")
161
+ object_ids = ["Duende", "Eros", "Ceres"]
162
+ orbits = query_horizons(object_ids, initial_time)
163
+
164
+ # Make sure PYOORB is ready
165
+ propagator = PYOORB()
166
+
167
+ # Define propagation times
168
+ times = initial_time + np.arange(0, 100) * u.d
169
+
170
+ # Propagate orbits! This function supports multiprocessing for large
171
+ # propagation jobs.
172
+ propagated_orbits = propagator.propagate_orbits(
173
+ orbits,
174
+ times,
175
+ chunk_size=100,
176
+ num_jobs=1,
177
+ )
178
+ ```
179
+
180
+ ### Low-level APIs
181
+
182
+ Getting the heliocentric ecliptic state vector of a DE440 body at a given set of times (in this case the barycenter of the Jovian system):
183
+ ```python
184
+ import numpy as np
185
+ from astropy.time import Time
186
+
187
+ from adam_core.coordinates.origin import OriginCodes
188
+ from adam_core.utils.spice import get_perturber_state
189
+
190
+ states = get_perturber_state(
191
+ OriginCodes.JUPITER_BARYCENTER,
192
+ Time(np.arange(59000, 60000), format="mjd", scale="tdb"),
193
+ frame="ecliptic",
194
+ origin=OriginCodes.SUN,
195
+ )
196
+ ```
197
+
198
+ ## Package Structure
199
+
200
+ ```bash
201
+ adam_core
202
+ ├── constants.py # Shared constants
203
+ ├── coordinates # Coordinate classes and transformations
204
+ ├── dynamics # Numerical solutions
205
+ ├── orbits # Orbits class and query utilities
206
+ └── utils # Utility classes like Indexable or conversions like times_from_df
207
+ ```
208
+
209
+ ## Installation
210
+
211
+ ADAM Core is available on PyPI
212
+
213
+ ```bash
214
+ pip install adam_core
215
+ ```
216
+
217
+ ## Development
218
+
219
+ Development is made easy with our Docker container environment.
220
+
221
+ ```bash
222
+ # Build the container
223
+ docker compose build
224
+
225
+ # Run tests in the container
226
+ docker compose run adam_core pytest .
227
+
228
+ # Run a shell in the container
229
+ docker compose run adam_core bash
230
+ ```
File without changes
@@ -0,0 +1,60 @@
1
+ import numpy as np
2
+
3
+ __all__ = [
4
+ "KM_P_AU",
5
+ "S_P_DAY",
6
+ "Constants",
7
+ "DE43X",
8
+ "DE44X",
9
+ ]
10
+
11
+ # km in an au
12
+ KM_P_AU = 149597870.700
13
+ # seconds in a day
14
+ S_P_DAY = 86400.0
15
+
16
+
17
+ class _Constants:
18
+ def __init__(self, C=None, MU=None, R_Earth=None, Obliquity=None):
19
+ self.C = C
20
+ self.MU = MU
21
+ self.R_EARTH = R_Earth
22
+ self.OBLIQUITY = Obliquity
23
+
24
+ # Transformation matrix from Equatorial J2000 to Ecliptic J2000
25
+ self.TRANSFORM_EQ2EC = np.array(
26
+ [
27
+ [1, 0, 0],
28
+ [0, np.cos(self.OBLIQUITY), np.sin(self.OBLIQUITY)],
29
+ [0, -np.sin(self.OBLIQUITY), np.cos(self.OBLIQUITY)],
30
+ ]
31
+ )
32
+
33
+ # Transformation matrix from Ecliptic J2000 to Equatorial J2000
34
+ self.TRANSFORM_EC2EQ = self.TRANSFORM_EQ2EC.T
35
+ return
36
+
37
+
38
+ DE43X_CONSTANTS = {
39
+ # Speed of Light : au / d (299792.458 km / s -- DE430/DE431)
40
+ "C": 299792.458 / KM_P_AU * S_P_DAY,
41
+ # Standard Gravitational Parameter -- Sun : au**3 / d**2 (0.295912208285591100E-3 -- DE431/DE430)
42
+ "MU": 0.295912208285591100e-3,
43
+ # Earth Equatorial Radius: au (6378.1363 km -- DE431/DE430)
44
+ "R_Earth": 6378.1363 / KM_P_AU,
45
+ # Mean Obliquity at J2000: radians (84381.448 arcseconds -- DE431/DE430)
46
+ "Obliquity": 84381.448 * np.pi / (180.0 * 3600.0),
47
+ }
48
+ Constants = DE43X = _Constants(**DE43X_CONSTANTS)
49
+
50
+ DE44X_CONSTANTS = {
51
+ # Speed of Light : au / d (299792.458 km / s -- DE430/DE431)
52
+ "C": 299792.458 / KM_P_AU * S_P_DAY,
53
+ # Standard Gravitational Parameter -- Sun : au**3 / d**2 (0.29591220828411956E-03 -- DE441/DE440)
54
+ "MU": 0.29591220828411956e-03,
55
+ # Earth Equatorial Radius: au (6378.1363 km -- DE431/DE430)
56
+ "R_Earth": 6378.1363 / KM_P_AU,
57
+ # Mean Obliquity at J2000: radians (84381.448 arcseconds -- DE431/DE430)
58
+ "Obliquity": 84381.448 * np.pi / (180.0 * 3600.0),
59
+ }
60
+ DE44X = _Constants(**DE44X_CONSTANTS)
@@ -0,0 +1,35 @@
1
+ # flake8: noqa: F401
2
+ from .cartesian import CARTESIAN_COLS, CARTESIAN_UNITS, CartesianCoordinates
3
+ from .cometary import COMETARY_COLS, COMETARY_UNITS, CometaryCoordinates
4
+ from .conversions import convert_coordinates
5
+ from .covariances import (
6
+ CoordinateCovariances,
7
+ covariances_from_df,
8
+ covariances_to_df,
9
+ covariances_to_table,
10
+ sample_covariance,
11
+ sigmas_from_df,
12
+ sigmas_to_df,
13
+ transform_covariances_jacobian,
14
+ transform_covariances_sampling,
15
+ )
16
+ from .io import coords_from_dataframe, coords_to_dataframe
17
+ from .jacobian import calc_jacobian
18
+ from .keplerian import KEPLERIAN_COLS, KEPLERIAN_UNITS, KeplerianCoordinates
19
+ from .origin import Origin
20
+ from .residuals import Residuals
21
+ from .spherical import SPHERICAL_COLS, SPHERICAL_UNITS, SphericalCoordinates
22
+ from .times import Times
23
+ from .transform import (
24
+ _cartesian_to_cometary,
25
+ _cartesian_to_keplerian,
26
+ _cartesian_to_keplerian6,
27
+ _cometary_to_cartesian,
28
+ _keplerian_to_cartesian_a,
29
+ _keplerian_to_cartesian_p,
30
+ _keplerian_to_cartesian_q,
31
+ cartesian_to_cometary,
32
+ cartesian_to_keplerian,
33
+ cometary_to_cartesian,
34
+ transform_coordinates,
35
+ )