adam-core 0.1.0__py3-none-any.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.
- adam_core/__init__.py +0 -0
- adam_core/constants.py +60 -0
- adam_core/coordinates/__init__.py +35 -0
- adam_core/coordinates/cartesian.py +360 -0
- adam_core/coordinates/cometary.py +374 -0
- adam_core/coordinates/conversions.py +176 -0
- adam_core/coordinates/covariances.py +548 -0
- adam_core/coordinates/io.py +120 -0
- adam_core/coordinates/jacobian.py +69 -0
- adam_core/coordinates/keplerian.py +351 -0
- adam_core/coordinates/origin.py +111 -0
- adam_core/coordinates/residuals.py +214 -0
- adam_core/coordinates/spherical.py +301 -0
- adam_core/coordinates/tests/__init__.py +0 -0
- adam_core/coordinates/tests/test_benchmarks.py +39 -0
- adam_core/coordinates/tests/test_cartesian.py +32 -0
- adam_core/coordinates/tests/test_covariances.py +105 -0
- adam_core/coordinates/tests/test_origin.py +54 -0
- adam_core/coordinates/tests/test_residuals.py +194 -0
- adam_core/coordinates/tests/test_spherical.py +38 -0
- adam_core/coordinates/tests/test_transforms_spherical.py +93 -0
- adam_core/coordinates/times.py +28 -0
- adam_core/coordinates/transform.py +1324 -0
- adam_core/dynamics/__init__.py +4 -0
- adam_core/dynamics/barker.py +33 -0
- adam_core/dynamics/kepler.py +204 -0
- adam_core/dynamics/tests/__init__.py +0 -0
- adam_core/dynamics/tests/test_kepler.py +194 -0
- adam_core/dynamics/tests/test_tisserand.py +50 -0
- adam_core/dynamics/tisserand.py +65 -0
- adam_core/orbits/__init__.py +3 -0
- adam_core/orbits/classification.py +51 -0
- adam_core/orbits/orbits.py +70 -0
- adam_core/orbits/query/__init__.py +3 -0
- adam_core/orbits/query/horizons.py +238 -0
- adam_core/orbits/query/sbdb.py +237 -0
- adam_core/orbits/query/tests/__init__.py +43 -0
- adam_core/orbits/query/tests/test_sbdb.py +107 -0
- adam_core/orbits/tests/__init__.py +0 -0
- adam_core/orbits/tests/test_benchmarks.py +21 -0
- adam_core/orbits/tests/test_orbits.py +43 -0
- adam_core/propagator/__init__.py +4 -0
- adam_core/propagator/propagator.py +176 -0
- adam_core/propagator/pyoorb.py +288 -0
- adam_core/propagator/tests/__init__.py +0 -0
- adam_core/propagator/tests/test_utils.py +36 -0
- adam_core/propagator/utils.py +72 -0
- adam_core/utils/__init__.py +1 -0
- adam_core/utils/helpers/__init__.py +2 -0
- adam_core/utils/helpers/data/__init__.py +0 -0
- adam_core/utils/helpers/data/sample_orbits.csv +28 -0
- adam_core/utils/helpers/orbits.py +97 -0
- adam_core/utils/helpers/tests/__init__.py +0 -0
- adam_core/utils/helpers/tests/test_orbits.py +25 -0
- adam_core/utils/mpc.py +473 -0
- adam_core/utils/spice.py +105 -0
- adam_core/utils/tests/__init__.py +0 -0
- adam_core/utils/tests/test_mpc.py +213 -0
- adam_core-0.1.0.dist-info/LICENSE.md +60 -0
- adam_core-0.1.0.dist-info/METADATA +262 -0
- adam_core-0.1.0.dist-info/RECORD +63 -0
- adam_core-0.1.0.dist-info/WHEEL +5 -0
- adam_core-0.1.0.dist-info/top_level.txt +1 -0
adam_core/__init__.py
ADDED
|
File without changes
|
adam_core/constants.py
ADDED
|
@@ -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
|
+
)
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, Literal
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
from astropy import units as u
|
|
7
|
+
from quivr import Float64Column, StringAttribute, Table
|
|
8
|
+
|
|
9
|
+
from .covariances import CoordinateCovariances
|
|
10
|
+
from .io import coords_from_dataframe, coords_to_dataframe
|
|
11
|
+
from .origin import Origin
|
|
12
|
+
from .times import Times
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from .cometary import CometaryCoordinates
|
|
16
|
+
from .keplerian import KeplerianCoordinates
|
|
17
|
+
from .spherical import SphericalCoordinates
|
|
18
|
+
|
|
19
|
+
__all__ = ["CartesianCoordinates", "CARTESIAN_COLS", "CARTESIAN_UNITS"]
|
|
20
|
+
|
|
21
|
+
CARTESIAN_COLS = {}
|
|
22
|
+
CARTESIAN_UNITS = {}
|
|
23
|
+
for i in ["x", "y", "z"]:
|
|
24
|
+
CARTESIAN_COLS[i] = i
|
|
25
|
+
CARTESIAN_UNITS[i] = u.au
|
|
26
|
+
for i in ["vx", "vy", "vz"]:
|
|
27
|
+
CARTESIAN_COLS[i] = i
|
|
28
|
+
CARTESIAN_UNITS[i] = u.au / u.d
|
|
29
|
+
|
|
30
|
+
COVARIANCE_ROTATION_TOLERANCE = 1e-25
|
|
31
|
+
logger = logging.getLogger(__name__)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class CartesianCoordinates(Table):
|
|
35
|
+
|
|
36
|
+
x = Float64Column(nullable=True)
|
|
37
|
+
y = Float64Column(nullable=True)
|
|
38
|
+
z = Float64Column(nullable=True)
|
|
39
|
+
vx = Float64Column(nullable=True)
|
|
40
|
+
vy = Float64Column(nullable=True)
|
|
41
|
+
vz = Float64Column(nullable=True)
|
|
42
|
+
times = Times.as_column(nullable=True)
|
|
43
|
+
covariances = CoordinateCovariances.as_column(nullable=True)
|
|
44
|
+
origin = Origin.as_column(nullable=False)
|
|
45
|
+
frame = StringAttribute()
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def values(self) -> np.ndarray:
|
|
49
|
+
return np.array(self.table.select(["x", "y", "z", "vx", "vy", "vz"])).T
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def r(self) -> np.ndarray:
|
|
53
|
+
"""
|
|
54
|
+
Position vector.
|
|
55
|
+
"""
|
|
56
|
+
return np.array(self.table.select(["x", "y", "z"]))
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def r_mag(self) -> np.ndarray:
|
|
60
|
+
"""
|
|
61
|
+
Magnitude of the position vector.
|
|
62
|
+
"""
|
|
63
|
+
return np.linalg.norm(self.r, axis=1)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def r_hat(self) -> np.ndarray:
|
|
67
|
+
"""
|
|
68
|
+
Unit vector in the direction of the position vector.
|
|
69
|
+
"""
|
|
70
|
+
return self.r / self.r_mag[:, None]
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def v(self) -> np.ndarray:
|
|
74
|
+
"""
|
|
75
|
+
Velocity vector.
|
|
76
|
+
"""
|
|
77
|
+
return np.array(self.table.select(["vx", "vy", "vz"]))
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def v_mag(self) -> np.ndarray:
|
|
81
|
+
"""
|
|
82
|
+
Magnitude of the velocity vector.
|
|
83
|
+
"""
|
|
84
|
+
return np.linalg.norm(self.v, axis=1)
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def v_hat(self) -> np.ndarray:
|
|
88
|
+
"""
|
|
89
|
+
Unit vector in the direction of the velocity vector.
|
|
90
|
+
"""
|
|
91
|
+
return self.v / self.v_mag[:, None]
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def sigma_x(self) -> np.ndarray:
|
|
95
|
+
"""
|
|
96
|
+
1-sigma uncertainty in the X-coordinate.
|
|
97
|
+
"""
|
|
98
|
+
return self.covariances.sigmas[:, 0]
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def sigma_y(self) -> np.ndarray:
|
|
102
|
+
"""
|
|
103
|
+
1-sigma uncertainty in the Y-coordinate.
|
|
104
|
+
"""
|
|
105
|
+
return self.covariances.sigmas[:, 1]
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def sigma_z(self) -> np.ndarray:
|
|
109
|
+
"""
|
|
110
|
+
1-sigma uncertainty in the Z-coordinate.
|
|
111
|
+
"""
|
|
112
|
+
return self.covariances.sigmas[:, 2]
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def sigma_vx(self) -> np.ndarray:
|
|
116
|
+
"""
|
|
117
|
+
1-sigma uncertainty in the X-coordinate velocity.
|
|
118
|
+
"""
|
|
119
|
+
return self.covariances.sigmas[:, 3]
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def sigma_vy(self) -> np.ndarray:
|
|
123
|
+
"""
|
|
124
|
+
1-sigma uncertainty in the Y-coordinate velocity.
|
|
125
|
+
"""
|
|
126
|
+
return self.covariances.sigmas[:, 4]
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def sigma_vz(self) -> np.ndarray:
|
|
130
|
+
"""
|
|
131
|
+
1-sigma uncertainty in the Z-coordinate velocity.
|
|
132
|
+
"""
|
|
133
|
+
return self.covariances.sigmas[:, 5]
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def sigma_r(self) -> np.ndarray:
|
|
137
|
+
"""
|
|
138
|
+
1-sigma uncertainties in the position vector.
|
|
139
|
+
"""
|
|
140
|
+
return np.sqrt(self.covariances.sigmas[:, 0:3])
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def sigma_r_mag(self) -> np.ndarray:
|
|
144
|
+
"""
|
|
145
|
+
1-sigma uncertainty in the position.
|
|
146
|
+
"""
|
|
147
|
+
return np.sqrt(np.sum(self.covariances.sigmas[:, 0:3] ** 2, axis=1))
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
def sigma_v(self) -> np.ndarray:
|
|
151
|
+
"""
|
|
152
|
+
1-sigma uncertainties in the velocity vector.
|
|
153
|
+
"""
|
|
154
|
+
return np.sqrt(self.covariances.sigmas[:, 3:6])
|
|
155
|
+
|
|
156
|
+
@property
|
|
157
|
+
def sigma_v_mag(self) -> np.ndarray:
|
|
158
|
+
"""
|
|
159
|
+
1-sigma uncertainty in the velocity vector.
|
|
160
|
+
"""
|
|
161
|
+
return np.sqrt(np.sum(self.covariances.sigmas[:, 3:6] ** 2, axis=1))
|
|
162
|
+
|
|
163
|
+
def rotate(
|
|
164
|
+
self, rotation_matrix: np.ndarray, frame_out: str
|
|
165
|
+
) -> "CartesianCoordinates":
|
|
166
|
+
"""
|
|
167
|
+
Rotate Cartesian coordinates and their covariances by the given rotation matrix.
|
|
168
|
+
|
|
169
|
+
Covariance matrices are also rotated. Rotations will sometimes result
|
|
170
|
+
in covariance matrix elements very near zero but not exactly zero. Any
|
|
171
|
+
elements that are smaller than +-1e-25 are rounded down to 0.
|
|
172
|
+
|
|
173
|
+
Parameters
|
|
174
|
+
----------
|
|
175
|
+
matrix : `~numpy.ndarray` (6, 6)
|
|
176
|
+
Rotation matrix.
|
|
177
|
+
frame_out : str
|
|
178
|
+
Name of the frame to which coordinates are being rotated.
|
|
179
|
+
|
|
180
|
+
Returns
|
|
181
|
+
-------
|
|
182
|
+
CartesianCoordinates : `~adam_core.coordinates.cartesian.CartesianCoordinates`
|
|
183
|
+
Rotated Cartesian coordinates and their covariances.
|
|
184
|
+
"""
|
|
185
|
+
# Extract coordinate values into a masked array and mask NaNss
|
|
186
|
+
masked_coords = np.ma.masked_array(self.values, fill_value=np.NaN)
|
|
187
|
+
masked_coords.mask = np.isnan(masked_coords.data)
|
|
188
|
+
|
|
189
|
+
# Rotate coordinates
|
|
190
|
+
coords_rotated = np.ma.dot(masked_coords, rotation_matrix.T, strict=False)
|
|
191
|
+
|
|
192
|
+
# Extract covariances
|
|
193
|
+
masked_covariances = np.ma.masked_array(
|
|
194
|
+
self.covariances.to_matrix(), fill_value=0.0
|
|
195
|
+
)
|
|
196
|
+
masked_covariances.mask = np.isnan(masked_covariances.data)
|
|
197
|
+
|
|
198
|
+
# Rotate covariances
|
|
199
|
+
covariances_rotated = (
|
|
200
|
+
rotation_matrix @ masked_covariances.filled() @ rotation_matrix.T
|
|
201
|
+
)
|
|
202
|
+
# Reset the mask to the original mask
|
|
203
|
+
covariances_rotated[masked_covariances.mask] = np.NaN
|
|
204
|
+
|
|
205
|
+
# Check if any covariance elements are near zero, if so set them to zero
|
|
206
|
+
near_zero = len(
|
|
207
|
+
covariances_rotated[
|
|
208
|
+
np.abs(covariances_rotated) < COVARIANCE_ROTATION_TOLERANCE
|
|
209
|
+
]
|
|
210
|
+
)
|
|
211
|
+
if near_zero > 0:
|
|
212
|
+
logger.debug(
|
|
213
|
+
f"{near_zero} covariance elements are within {COVARIANCE_ROTATION_TOLERANCE:.0e}"
|
|
214
|
+
" of zero after rotation, setting these elements to 0."
|
|
215
|
+
)
|
|
216
|
+
covariances_rotated = np.where(
|
|
217
|
+
np.abs(covariances_rotated) < COVARIANCE_ROTATION_TOLERANCE,
|
|
218
|
+
0,
|
|
219
|
+
covariances_rotated,
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
coords = self.from_kwargs(
|
|
223
|
+
x=coords_rotated[:, 0],
|
|
224
|
+
y=coords_rotated[:, 1],
|
|
225
|
+
z=coords_rotated[:, 2],
|
|
226
|
+
vx=coords_rotated[:, 3],
|
|
227
|
+
vy=coords_rotated[:, 4],
|
|
228
|
+
vz=coords_rotated[:, 5],
|
|
229
|
+
times=self.times,
|
|
230
|
+
covariances=CoordinateCovariances.from_matrix(covariances_rotated),
|
|
231
|
+
origin=self.origin,
|
|
232
|
+
frame=frame_out,
|
|
233
|
+
)
|
|
234
|
+
return coords
|
|
235
|
+
|
|
236
|
+
def translate(self, vector: np.ndarray, origin_out: str) -> "CartesianCoordinates":
|
|
237
|
+
"""
|
|
238
|
+
Translate Cartesian coordinates by the given vector.
|
|
239
|
+
|
|
240
|
+
Parameters
|
|
241
|
+
----------
|
|
242
|
+
vector : `~numpy.ndarray` (6,) or (N, 6)
|
|
243
|
+
Translation vector. If a single vector is given, it is applied to all coordinates.
|
|
244
|
+
If an array of vectors is given, each vector is applied to the corresponding coordinate.
|
|
245
|
+
origin_out : str
|
|
246
|
+
Name of the origin to which coordinates are being translated.
|
|
247
|
+
|
|
248
|
+
Returns
|
|
249
|
+
-------
|
|
250
|
+
CartesianCoordinates : `~adam_core.coordinates.cartesian.CartesianCoordinates`
|
|
251
|
+
Translated Cartesian coordinates and their covariances.
|
|
252
|
+
"""
|
|
253
|
+
N = len(self)
|
|
254
|
+
if vector.shape == (6,):
|
|
255
|
+
vector_ = vector.reshape(1, 6)
|
|
256
|
+
elif vector.shape == (N, 6):
|
|
257
|
+
vector_ = vector
|
|
258
|
+
else:
|
|
259
|
+
raise ValueError(f"Expected vector to have shape (6,) or ({N}, 6).")
|
|
260
|
+
|
|
261
|
+
# Extract coordinate values into a masked array and mask NaNss
|
|
262
|
+
masked_coords = np.ma.masked_array(self.values, fill_value=np.NaN)
|
|
263
|
+
masked_coords.mask = np.isnan(masked_coords.data)
|
|
264
|
+
|
|
265
|
+
# Translate coordinates
|
|
266
|
+
coords_translated = (masked_coords + vector_).filled()
|
|
267
|
+
|
|
268
|
+
coords = self.from_kwargs(
|
|
269
|
+
x=coords_translated[:, 0],
|
|
270
|
+
y=coords_translated[:, 1],
|
|
271
|
+
z=coords_translated[:, 2],
|
|
272
|
+
vx=coords_translated[:, 3],
|
|
273
|
+
vy=coords_translated[:, 4],
|
|
274
|
+
vz=coords_translated[:, 5],
|
|
275
|
+
times=self.times,
|
|
276
|
+
covariances=self.covariances,
|
|
277
|
+
origin=Origin.from_kwargs(code=[origin_out] * len(self)),
|
|
278
|
+
frame=self.frame,
|
|
279
|
+
)
|
|
280
|
+
return coords
|
|
281
|
+
|
|
282
|
+
def to_cometary(self) -> "CometaryCoordinates":
|
|
283
|
+
from .cometary import CometaryCoordinates
|
|
284
|
+
|
|
285
|
+
return CometaryCoordinates.from_cartesian(self)
|
|
286
|
+
|
|
287
|
+
@classmethod
|
|
288
|
+
def from_cometary(cls, cometary: "CometaryCoordinates") -> "CartesianCoordinates":
|
|
289
|
+
return cometary.to_cartesian()
|
|
290
|
+
|
|
291
|
+
def to_keplerian(self) -> "KeplerianCoordinates":
|
|
292
|
+
from .keplerian import KeplerianCoordinates
|
|
293
|
+
|
|
294
|
+
return KeplerianCoordinates.from_cartesian(self)
|
|
295
|
+
|
|
296
|
+
@classmethod
|
|
297
|
+
def from_keplerian(
|
|
298
|
+
cls, keplerian: "KeplerianCoordinates"
|
|
299
|
+
) -> "CartesianCoordinates":
|
|
300
|
+
return keplerian.to_cartesian()
|
|
301
|
+
|
|
302
|
+
def to_spherical(self) -> "SphericalCoordinates":
|
|
303
|
+
from .spherical import SphericalCoordinates
|
|
304
|
+
|
|
305
|
+
return SphericalCoordinates.from_cartesian(self)
|
|
306
|
+
|
|
307
|
+
@classmethod
|
|
308
|
+
def from_spherical(
|
|
309
|
+
cls, spherical: "SphericalCoordinates"
|
|
310
|
+
) -> "CartesianCoordinates":
|
|
311
|
+
return spherical.to_cartesian()
|
|
312
|
+
|
|
313
|
+
def to_dataframe(
|
|
314
|
+
self, sigmas: bool = False, covariances: bool = True
|
|
315
|
+
) -> pd.DataFrame:
|
|
316
|
+
"""
|
|
317
|
+
Convert coordinates to a pandas DataFrame.
|
|
318
|
+
|
|
319
|
+
Parameters
|
|
320
|
+
----------
|
|
321
|
+
sigmas : bool, optional
|
|
322
|
+
If True, include 1-sigma uncertainties in the DataFrame.
|
|
323
|
+
covariances : bool, optional
|
|
324
|
+
If True, include covariance matrices in the DataFrame. Covariance matrices
|
|
325
|
+
will be split into 21 columns, with the lower triangular elements stored.
|
|
326
|
+
|
|
327
|
+
Returns
|
|
328
|
+
-------
|
|
329
|
+
df : `~pandas.Dataframe`
|
|
330
|
+
DataFrame containing coordinates.
|
|
331
|
+
"""
|
|
332
|
+
return coords_to_dataframe(
|
|
333
|
+
self,
|
|
334
|
+
["x", "y", "z", "vx", "vy", "vz"],
|
|
335
|
+
sigmas=sigmas,
|
|
336
|
+
covariances=covariances,
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
@classmethod
|
|
340
|
+
def from_dataframe(
|
|
341
|
+
cls, df: pd.DataFrame, frame: Literal["ecliptic", "equatorial"]
|
|
342
|
+
) -> "CartesianCoordinates":
|
|
343
|
+
"""
|
|
344
|
+
Create coordinates from a pandas DataFrame.
|
|
345
|
+
|
|
346
|
+
Parameters
|
|
347
|
+
----------
|
|
348
|
+
df : `~pandas.Dataframe`
|
|
349
|
+
DataFrame containing coordinates.
|
|
350
|
+
frame : {"ecliptic", "equatorial"}
|
|
351
|
+
Frame in which coordinates are defined.
|
|
352
|
+
|
|
353
|
+
Returns
|
|
354
|
+
-------
|
|
355
|
+
coords : `~adam_core.coordinates.cartesian.CartesianCoordinates`
|
|
356
|
+
Cartesian coordinates.
|
|
357
|
+
"""
|
|
358
|
+
return coords_from_dataframe(
|
|
359
|
+
cls, df, coord_names=["x", "y", "z", "vx", "vy", "vz"], frame=frame
|
|
360
|
+
)
|