ephessos 1.0.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.
- ephessos-1.0.0/LICENSE +21 -0
- ephessos-1.0.0/PKG-INFO +154 -0
- ephessos-1.0.0/README.md +116 -0
- ephessos-1.0.0/ephessos/__init__.py +8 -0
- ephessos-1.0.0/ephessos/core.py +197 -0
- ephessos-1.0.0/ephessos.egg-info/PKG-INFO +154 -0
- ephessos-1.0.0/ephessos.egg-info/SOURCES.txt +11 -0
- ephessos-1.0.0/ephessos.egg-info/dependency_links.txt +1 -0
- ephessos-1.0.0/ephessos.egg-info/requires.txt +11 -0
- ephessos-1.0.0/ephessos.egg-info/top_level.txt +1 -0
- ephessos-1.0.0/pyproject.toml +66 -0
- ephessos-1.0.0/setup.cfg +4 -0
- ephessos-1.0.0/setup.py +12 -0
ephessos-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 A. S. Borlaff
|
|
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, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
ephessos-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ephessos
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Ephemeris for Solar System Objects with JPL/Horizons
|
|
5
|
+
Author-email: "Alejandro S. Borlaff" <a.s.borlaff@nasa.gov>, Jessie Dotson <jessie.dotson@nasa.gov>
|
|
6
|
+
License: BSD
|
|
7
|
+
Project-URL: Homepage, https://github.com/Borlaff/EPHESSOS
|
|
8
|
+
Project-URL: Repository, https://github.com/Borlaff/EPHESSOS
|
|
9
|
+
Project-URL: Tracker, https://github.com/Borlaff/EPHESSOS/issues
|
|
10
|
+
Project-URL: Documentation, https://ephessos.readthedocs.io/en/stable/
|
|
11
|
+
Project-URL: Source Code, https://github.com/Borlaff/EPHESSOS
|
|
12
|
+
Keywords: HWO,SSOs,Horizons,JPL
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Topic :: Utilities
|
|
16
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: numpy
|
|
27
|
+
Requires-Dist: tqdm
|
|
28
|
+
Requires-Dist: pandas
|
|
29
|
+
Requires-Dist: astroquery
|
|
30
|
+
Requires-Dist: matplotlib
|
|
31
|
+
Requires-Dist: astropy
|
|
32
|
+
Requires-Dist: pytest
|
|
33
|
+
Requires-Dist: ipython
|
|
34
|
+
Requires-Dist: sphinx
|
|
35
|
+
Requires-Dist: sphinx-rtd-dark-mode
|
|
36
|
+
Requires-Dist: sphinxcontrib-video
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# EPHESSOS
|
|
40
|
+
Ephemeris for Solar System Objects with JPL/Horizons
|
|
41
|
+
|
|
42
|
+
[](https://pypi.org/project/ephessos/)
|
|
43
|
+
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
44
|
+
|
|
45
|
+
EPHESSOS is a Python library for querying ephemeris data of solar system objects from NASA's JPL Horizons system. It provides an easy interface to retrieve positional and observational data for asteroids, comets, and planets.
|
|
46
|
+
|
|
47
|
+
## Features
|
|
48
|
+
|
|
49
|
+
- Query JPL Horizons using orbital elements or object designations
|
|
50
|
+
- Parse MPC NEA (Near-Earth Asteroid) data files
|
|
51
|
+
- Retrieve comprehensive ephemeris data including RA, Dec, distance, and more
|
|
52
|
+
- Support for custom time ranges and step sizes
|
|
53
|
+
- Integration with Astropy for astronomical calculations
|
|
54
|
+
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
Install EPHESSOS using pip:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install ephessos
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Or from source:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
git clone https://github.com/Borlaff/EPHESSOS.git
|
|
67
|
+
cd EPHESSOS
|
|
68
|
+
pip install .
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
Here's a simple example showing how to query the ephemeris of asteroid (433) Eros:
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import ephessos as ep
|
|
77
|
+
from astropy.time import Time
|
|
78
|
+
|
|
79
|
+
# Define time range
|
|
80
|
+
mjd_start = Time('2024-01-01T00:00:00', format='isot', scale='utc').mjd
|
|
81
|
+
mjd_end = Time('2024-01-15T00:00:00', format='isot', scale='utc').mjd
|
|
82
|
+
|
|
83
|
+
# Query Horizons for Eros (designation: 00433)
|
|
84
|
+
eros_data = ep.core.sso_query_to_horizons(
|
|
85
|
+
designation="00433",
|
|
86
|
+
mjd_start=mjd_start,
|
|
87
|
+
mjd_end=mjd_end,
|
|
88
|
+
step_size="1d",
|
|
89
|
+
verbose=True
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
print(eros_data.head())
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
This will return a pandas DataFrame containing ephemeris data including:
|
|
96
|
+
- Right Ascension (RA) and Declination (Dec) in degrees
|
|
97
|
+
- Distance from observer
|
|
98
|
+
- Magnitude and other observational quantities
|
|
99
|
+
- Modified Julian Date (MJD)
|
|
100
|
+
|
|
101
|
+
## Advanced Usage
|
|
102
|
+
|
|
103
|
+
### Reading MPC Data Files
|
|
104
|
+
|
|
105
|
+
EPHESSOS can parse MPC-formatted NEA files:
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
# Read MPC NEA data
|
|
109
|
+
nea_table = ep.core.read_mpc_nea_file("path/to/nea.txt")
|
|
110
|
+
|
|
111
|
+
# Query ephemeris for the first object
|
|
112
|
+
first_object = nea_table.iloc[0]
|
|
113
|
+
data = ep.core.sso_query_to_horizons(
|
|
114
|
+
designation=first_object["Designation"],
|
|
115
|
+
epoch=first_object["Epoch"],
|
|
116
|
+
eccentricity=first_object["Eccentricity"],
|
|
117
|
+
node=first_object["Node"],
|
|
118
|
+
arg_perihelion=first_object["Arg_Perihelion"],
|
|
119
|
+
inclination=first_object["Inclination"],
|
|
120
|
+
mean_anomaly=first_object["Mean_Anomaly"],
|
|
121
|
+
semimajor_axis=first_object["Semimajor_Axis"],
|
|
122
|
+
mean_motion=first_object["Mean_Motion"],
|
|
123
|
+
mjd_start=mjd_start,
|
|
124
|
+
mjd_end=mjd_end,
|
|
125
|
+
step_size="1d"
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
## Documentation
|
|
131
|
+
|
|
132
|
+
Full documentation is available at: [https://ephessos.readthedocs.io/](https://ephessos.readthedocs.io/)
|
|
133
|
+
|
|
134
|
+
## Contributing
|
|
135
|
+
|
|
136
|
+
Contributions are welcome! Please see our [contributing guidelines](CONTRIBUTING.md) for details.
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
EPHESSOS is licensed under the BSD 3-Clause License. See [LICENSE](LICENSE) for details.
|
|
141
|
+
|
|
142
|
+
## Citation
|
|
143
|
+
|
|
144
|
+
If you use EPHESSOS in your research, please cite:
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
Borlaff, A. S., & Dotson, J. (2026). EPHESSOS: Ephemeris for Solar System Objects with JPL/Horizons.
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Contact
|
|
151
|
+
|
|
152
|
+
- **Authors**: Alejandro S. Borlaff, Jessie Dotson
|
|
153
|
+
- **Email**: a.s.borlaff@nasa.gov, jessie.dotson@nasa.gov
|
|
154
|
+
- **Repository**: [https://github.com/Borlaff/EPHESSOS](https://github.com/Borlaff/EPHESSOS)
|
ephessos-1.0.0/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# EPHESSOS
|
|
2
|
+
Ephemeris for Solar System Objects with JPL/Horizons
|
|
3
|
+
|
|
4
|
+
[](https://pypi.org/project/ephessos/)
|
|
5
|
+
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
6
|
+
|
|
7
|
+
EPHESSOS is a Python library for querying ephemeris data of solar system objects from NASA's JPL Horizons system. It provides an easy interface to retrieve positional and observational data for asteroids, comets, and planets.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- Query JPL Horizons using orbital elements or object designations
|
|
12
|
+
- Parse MPC NEA (Near-Earth Asteroid) data files
|
|
13
|
+
- Retrieve comprehensive ephemeris data including RA, Dec, distance, and more
|
|
14
|
+
- Support for custom time ranges and step sizes
|
|
15
|
+
- Integration with Astropy for astronomical calculations
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
Install EPHESSOS using pip:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install ephessos
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Or from source:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
git clone https://github.com/Borlaff/EPHESSOS.git
|
|
29
|
+
cd EPHESSOS
|
|
30
|
+
pip install .
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
Here's a simple example showing how to query the ephemeris of asteroid (433) Eros:
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
import ephessos as ep
|
|
39
|
+
from astropy.time import Time
|
|
40
|
+
|
|
41
|
+
# Define time range
|
|
42
|
+
mjd_start = Time('2024-01-01T00:00:00', format='isot', scale='utc').mjd
|
|
43
|
+
mjd_end = Time('2024-01-15T00:00:00', format='isot', scale='utc').mjd
|
|
44
|
+
|
|
45
|
+
# Query Horizons for Eros (designation: 00433)
|
|
46
|
+
eros_data = ep.core.sso_query_to_horizons(
|
|
47
|
+
designation="00433",
|
|
48
|
+
mjd_start=mjd_start,
|
|
49
|
+
mjd_end=mjd_end,
|
|
50
|
+
step_size="1d",
|
|
51
|
+
verbose=True
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
print(eros_data.head())
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
This will return a pandas DataFrame containing ephemeris data including:
|
|
58
|
+
- Right Ascension (RA) and Declination (Dec) in degrees
|
|
59
|
+
- Distance from observer
|
|
60
|
+
- Magnitude and other observational quantities
|
|
61
|
+
- Modified Julian Date (MJD)
|
|
62
|
+
|
|
63
|
+
## Advanced Usage
|
|
64
|
+
|
|
65
|
+
### Reading MPC Data Files
|
|
66
|
+
|
|
67
|
+
EPHESSOS can parse MPC-formatted NEA files:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
# Read MPC NEA data
|
|
71
|
+
nea_table = ep.core.read_mpc_nea_file("path/to/nea.txt")
|
|
72
|
+
|
|
73
|
+
# Query ephemeris for the first object
|
|
74
|
+
first_object = nea_table.iloc[0]
|
|
75
|
+
data = ep.core.sso_query_to_horizons(
|
|
76
|
+
designation=first_object["Designation"],
|
|
77
|
+
epoch=first_object["Epoch"],
|
|
78
|
+
eccentricity=first_object["Eccentricity"],
|
|
79
|
+
node=first_object["Node"],
|
|
80
|
+
arg_perihelion=first_object["Arg_Perihelion"],
|
|
81
|
+
inclination=first_object["Inclination"],
|
|
82
|
+
mean_anomaly=first_object["Mean_Anomaly"],
|
|
83
|
+
semimajor_axis=first_object["Semimajor_Axis"],
|
|
84
|
+
mean_motion=first_object["Mean_Motion"],
|
|
85
|
+
mjd_start=mjd_start,
|
|
86
|
+
mjd_end=mjd_end,
|
|
87
|
+
step_size="1d"
|
|
88
|
+
)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
## Documentation
|
|
93
|
+
|
|
94
|
+
Full documentation is available at: [https://ephessos.readthedocs.io/](https://ephessos.readthedocs.io/)
|
|
95
|
+
|
|
96
|
+
## Contributing
|
|
97
|
+
|
|
98
|
+
Contributions are welcome! Please see our [contributing guidelines](CONTRIBUTING.md) for details.
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
|
|
102
|
+
EPHESSOS is licensed under the BSD 3-Clause License. See [LICENSE](LICENSE) for details.
|
|
103
|
+
|
|
104
|
+
## Citation
|
|
105
|
+
|
|
106
|
+
If you use EPHESSOS in your research, please cite:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
Borlaff, A. S., & Dotson, J. (2026). EPHESSOS: Ephemeris for Solar System Objects with JPL/Horizons.
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Contact
|
|
113
|
+
|
|
114
|
+
- **Authors**: Alejandro S. Borlaff, Jessie Dotson
|
|
115
|
+
- **Email**: a.s.borlaff@nasa.gov, jessie.dotson@nasa.gov
|
|
116
|
+
- **Repository**: [https://github.com/Borlaff/EPHESSOS](https://github.com/Borlaff/EPHESSOS)
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
from astropy.time import Time
|
|
2
|
+
from astropy.table import vstack
|
|
3
|
+
import astropy.units as u
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
def sso_query_to_horizons(designation, epoch=None, eccentricity=None, node=None, arg_perihelion=None, inclination=None, mean_anomaly=None, semimajor_axis=None, mean_motion=None, mjd_start=58849.0, mjd_end=61042.0, step_size="1d", verbose=False):
|
|
8
|
+
# Example of a HTTP API Request to Horizons:
|
|
9
|
+
request_url = "https://ssd.jpl.nasa.gov/api/horizons.api?format=text&"
|
|
10
|
+
# request_url = "https://ssd.jpl.nasa.gov/api/horizons.api?"
|
|
11
|
+
# 00433 10.38 0.15 K25BL 310.55432 178.92978 304.27008 10.82847 0.2228360 0.55977529 1.4581210 0 E2025-YE5 16519 59 1893-2025 0.52 M-v 3Ek MPCORBFIT 1804 (433) Eros 20251222
|
|
12
|
+
"""
|
|
13
|
+
OBJECT = df.iloc[0]["Designation"] # Name of user input object
|
|
14
|
+
EPOCH = df.iloc[0]["Epoch"] # Julian Day number (JDTDB) of osculating elements
|
|
15
|
+
ECLIP = "J2000" # Reference ecliptic frame of elements: J2000 or B1950. J2000 assumes the IAU76/80 J2000 obliquity of 84381.448 arcsec relative to the ICRF reference frame. B1950 assumes FK4/B1950 obliquity of 84404.8362512 arcsec.
|
|
16
|
+
EC = str(df.iloc[0]["Eccentricity"]) # Eccentricity
|
|
17
|
+
# QR = # au Perihelion distance (see note above)
|
|
18
|
+
# TP = # Perihelion Julian Day number (see note above)
|
|
19
|
+
OM = str(df.iloc[0]["Node"]) # deg Longitude of ascending node wrt ecliptic
|
|
20
|
+
W = str(df.iloc[0]["Arg_Perihelion"]) # deg Argument of perihelion wrt ecliptic
|
|
21
|
+
IN = str(df.iloc[0]["Inclination"]) # deg Inclination wrt ecliptic
|
|
22
|
+
MA = str(df.iloc[0]["Mean_Anomaly"]) # deg Mean anomaly (see note above)
|
|
23
|
+
A = str(df.iloc[0]["Semimajor_Axis"]) # au Semi-major axis (see note above)
|
|
24
|
+
N = str(df.iloc[0]["Mean_Motion"]) # deg/d Mean motion (see note above)
|
|
25
|
+
"""
|
|
26
|
+
OBJECT = designation # Name of user input object
|
|
27
|
+
EPOCH = epoch # Julian Day number (JDTDB) of osculating elements
|
|
28
|
+
ECLIP = "J2000" # Reference ecliptic frame of elements: J2000
|
|
29
|
+
EC = str(eccentricity) # Eccentricity
|
|
30
|
+
# QR = # au Perihelion distance (see note above
|
|
31
|
+
# TP = # Perihelion Julian Day number (see note above)
|
|
32
|
+
OM = str(node) # deg Longitude of ascending node wrt ecliptic
|
|
33
|
+
W = str(arg_perihelion) # deg Argument of perihelion wrt ecliptic
|
|
34
|
+
IN = str(inclination) # deg Inclination wrt ecliptic
|
|
35
|
+
MA = str(mean_anomaly) # deg Mean anomaly (see note above)
|
|
36
|
+
A = str(semimajor_axis) # au Semi-major axis
|
|
37
|
+
N = str(mean_motion) # deg/d Mean motion (see note above)
|
|
38
|
+
|
|
39
|
+
# HEOE = ';TEST,2460400.5,1.5,0.2,10.5,45.0,30.0,20240401,1.0,J2000'
|
|
40
|
+
|
|
41
|
+
# Process time range for ephemeris query
|
|
42
|
+
from astropy.time import Time
|
|
43
|
+
t_start = Time(mjd_start, format='mjd')
|
|
44
|
+
t_end = Time(mjd_end, format='mjd')
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
"""
|
|
49
|
+
# request_url = request_url + "&COMMAND='1'"
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
if eccentricity is None and node is None and arg_perihelion is None and inclination is None and mean_anomaly is None and semimajor_axis is None:
|
|
53
|
+
request_url = request_url + "COMMAND='" + OBJECT + "'"
|
|
54
|
+
else:
|
|
55
|
+
request_url = request_url + "COMMAND=';'"
|
|
56
|
+
if designation is not None: request_url = request_url + "&OBJECT="+OBJECT
|
|
57
|
+
if epoch is not None: request_url = request_url + "&EPOCH=2461000.83333"#+EPOCH
|
|
58
|
+
request_url = request_url + "&ECLIP="+ECLIP
|
|
59
|
+
if eccentricity is not None: request_url = request_url + "&EC="+EC
|
|
60
|
+
if node is not None: request_url = request_url + "&OM="+OM
|
|
61
|
+
if arg_perihelion is not None: request_url = request_url + "&W="+W
|
|
62
|
+
if inclination is not None: request_url = request_url + "&IN="+IN
|
|
63
|
+
if mean_anomaly is not None: request_url = request_url + "&MA="+MA
|
|
64
|
+
if semimajor_axis is not None: request_url = request_url + "&A="+A
|
|
65
|
+
# request_url = request_url + "&N="+N
|
|
66
|
+
|
|
67
|
+
# request_url = request_url + "&COMMAND='499'"
|
|
68
|
+
request_url = request_url + "&OBJ_DATA='YES'"
|
|
69
|
+
request_url = request_url + "&MAKE_EPHEM='YES'"
|
|
70
|
+
request_url = request_url + "&EPHEM_TYPE='OBSERVER'"
|
|
71
|
+
request_url = request_url + "&CENTER='500@399'"
|
|
72
|
+
request_url = request_url + "&START_TIME='" + t_start.isot + "'"
|
|
73
|
+
request_url = request_url + "&STOP_TIME='"+ t_end.isot + "'"
|
|
74
|
+
request_url = request_url + "&STEP_SIZE='" + step_size + "'"
|
|
75
|
+
request_url = request_url + "&CSV_FORMAT='YES'"
|
|
76
|
+
request_url = request_url + "&QUANTITIES='1,2,3,4,5,6,7,8,9,10,20,23,24,25,27,29'"
|
|
77
|
+
# request_url = request_url.replace(",", "%3B")
|
|
78
|
+
|
|
79
|
+
import urllib.request
|
|
80
|
+
if verbose: print(request_url)
|
|
81
|
+
|
|
82
|
+
request_url = request_url.replace(";","%3B")
|
|
83
|
+
|
|
84
|
+
fp = urllib.request.urlopen(request_url)
|
|
85
|
+
mybytes = fp.read()
|
|
86
|
+
|
|
87
|
+
mystr = mybytes.decode("utf8")
|
|
88
|
+
fp.close()
|
|
89
|
+
|
|
90
|
+
lines_horizons_query = np.array(mystr.split('\n'))
|
|
91
|
+
id_start_of_table = np.where(lines_horizons_query == '$$SOE')[0][0]
|
|
92
|
+
id_end_of_table = np.where(lines_horizons_query == '$$EOE')[0][0]
|
|
93
|
+
id_column_names = id_start_of_table - 2
|
|
94
|
+
horizons_column_names = lines_horizons_query[id_column_names]
|
|
95
|
+
horizons_data_table = lines_horizons_query[id_start_of_table+1:id_end_of_table]
|
|
96
|
+
n_rows = len(lines_horizons_query[id_start_of_table+1:id_end_of_table])
|
|
97
|
+
|
|
98
|
+
csv_table_list = []
|
|
99
|
+
# csv_table_list = csv_table_list + [horizons_column_names.split(',')]
|
|
100
|
+
|
|
101
|
+
for i in range(n_rows):
|
|
102
|
+
csv_table_list = csv_table_list + [horizons_data_table[i].split(',')]
|
|
103
|
+
|
|
104
|
+
# print(csv_table_list)
|
|
105
|
+
|
|
106
|
+
horizons_dataframe = pd.DataFrame(np.array(csv_table_list), columns=horizons_column_names.split(','))
|
|
107
|
+
|
|
108
|
+
ra_icrf = np.zeros(len(horizons_dataframe), dtype=object)
|
|
109
|
+
dec_icrf = np.zeros(len(horizons_dataframe), dtype=object)
|
|
110
|
+
date_hms = np.zeros(len(horizons_dataframe), dtype=object)
|
|
111
|
+
mjd = np.zeros(len(horizons_dataframe))
|
|
112
|
+
|
|
113
|
+
time_column_name = horizons_dataframe.columns[0]
|
|
114
|
+
|
|
115
|
+
for i in range(len(horizons_dataframe)):
|
|
116
|
+
ra_icrf[i] = horizons_dataframe[" R.A._(ICRF)"].iloc[i][1:].replace(" ",":")
|
|
117
|
+
dec_icrf[i] = horizons_dataframe[" DEC__(ICRF)"].iloc[i][1:].replace(" ",":")
|
|
118
|
+
date_hms[i] = translate_horizons_date_to_date_hms(horizons_dataframe[time_column_name].iloc[i])[1:]
|
|
119
|
+
mjd[i] = Time(date_hms[i], format='iso').mjd
|
|
120
|
+
|
|
121
|
+
print(date_hms)
|
|
122
|
+
|
|
123
|
+
from astropy.coordinates import SkyCoord # High-level coordinates
|
|
124
|
+
coords = SkyCoord(ra_icrf, dec_icrf, unit=(u.hourangle, u.deg))
|
|
125
|
+
horizons_dataframe["RA_deg_ICRF"] = coords.ra.deg
|
|
126
|
+
horizons_dataframe["DEC_deg_ICRF"] = coords.dec.deg
|
|
127
|
+
horizons_dataframe["MJD"] = mjd
|
|
128
|
+
return(horizons_dataframe)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def translate_horizons_date_to_date_hms(horizons_date):
|
|
132
|
+
# Example input: "2025-Jan-22 00:00"
|
|
133
|
+
# Convert to ISO format: "2025-01-22T00:00:00"
|
|
134
|
+
date_hms = horizons_date.replace("Jan","01").replace("Feb","02").replace("Mar","03").replace("Apr","04").replace("May","05").replace("Jun","06").replace("Jul","07").replace("Aug","08").replace("Sep","09").replace("Oct","10").replace("Nov","11").replace("Dec","12")
|
|
135
|
+
return date_hms
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def read_mpc_nea_file(file_path):
|
|
142
|
+
# Define the exact character ranges based on the MPC schema
|
|
143
|
+
# Note: pandas uses 0-based indexing and the 'stop' value is exclusive
|
|
144
|
+
col_specification = [
|
|
145
|
+
(0, 7), # Designation
|
|
146
|
+
(8, 13), # H (Absolute Mag)
|
|
147
|
+
(14, 19), # G (Slope Parameter)
|
|
148
|
+
(20, 25), # Epoch
|
|
149
|
+
(26, 35), # Mean Anomaly
|
|
150
|
+
(37, 46), # Argument of Perihelion
|
|
151
|
+
(48, 57), # Longitude of Ascending Node
|
|
152
|
+
(59, 68), # Inclination
|
|
153
|
+
(70, 79), # Eccentricity
|
|
154
|
+
(80, 91), # Mean Daily Motion
|
|
155
|
+
(92, 103), # Semimajor Axis
|
|
156
|
+
(105, 106), # Uncertainty (U)
|
|
157
|
+
(107, 116), # Reference
|
|
158
|
+
(117, 122), # Num observations
|
|
159
|
+
(123, 126), # Num oppositions
|
|
160
|
+
(127, 131), # First year / Arc
|
|
161
|
+
(132, 136), # Last year / 'days'
|
|
162
|
+
(137, 141), # r.m.s residual
|
|
163
|
+
(142, 145), # Perturbers (Coarse)
|
|
164
|
+
(146, 149), # Perturbers (Precise)
|
|
165
|
+
(150, 160), # Computer Name
|
|
166
|
+
(161, 165), # Flags (Hex)
|
|
167
|
+
(166, 174), # Numerical ID
|
|
168
|
+
(175, 194), # Readable Designation
|
|
169
|
+
(194, 202) # Last Observation Date
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
column_names = [
|
|
173
|
+
"Designation", "H", "G", "Epoch", "Mean_Anomaly", "Arg_Perihelion",
|
|
174
|
+
"Node", "Inclination", "Eccentricity", "Mean_Motion", "Semimajor_Axis",
|
|
175
|
+
"Uncertainty", "Ref", "Obs_Count", "Opp_Count", "First_Obs", "Last_Obs_Arc",
|
|
176
|
+
"RMS_Resid", "Pert_Coarse", "Pert_Precise", "Comp_Name", "Flags", "Num_ID",
|
|
177
|
+
"Full_Name", "Last_Obs_Date"
|
|
178
|
+
]
|
|
179
|
+
|
|
180
|
+
# Read the file
|
|
181
|
+
# Replace 'NEA.txt' with the path to your downloaded file
|
|
182
|
+
df = pd.read_fwf(
|
|
183
|
+
file_path,
|
|
184
|
+
colspecs=col_specification,
|
|
185
|
+
names=column_names,
|
|
186
|
+
header=None
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# Optional: Convert numeric columns that might have been read as strings
|
|
190
|
+
df['H'] = pd.to_numeric(df['H'], errors='coerce')
|
|
191
|
+
df['Semimajor_Axis'] = pd.to_numeric(df['Semimajor_Axis'], errors='coerce')
|
|
192
|
+
#df[['ID', 'Name']] = df['Full_Name'].str.extract(r'(\(.*\))\s+(.*)')
|
|
193
|
+
df["Designation"] = df["Designation"].astype(str)
|
|
194
|
+
|
|
195
|
+
# Preview the first few rows
|
|
196
|
+
print(df.head())
|
|
197
|
+
return(df)
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ephessos
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Ephemeris for Solar System Objects with JPL/Horizons
|
|
5
|
+
Author-email: "Alejandro S. Borlaff" <a.s.borlaff@nasa.gov>, Jessie Dotson <jessie.dotson@nasa.gov>
|
|
6
|
+
License: BSD
|
|
7
|
+
Project-URL: Homepage, https://github.com/Borlaff/EPHESSOS
|
|
8
|
+
Project-URL: Repository, https://github.com/Borlaff/EPHESSOS
|
|
9
|
+
Project-URL: Tracker, https://github.com/Borlaff/EPHESSOS/issues
|
|
10
|
+
Project-URL: Documentation, https://ephessos.readthedocs.io/en/stable/
|
|
11
|
+
Project-URL: Source Code, https://github.com/Borlaff/EPHESSOS
|
|
12
|
+
Keywords: HWO,SSOs,Horizons,JPL
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Topic :: Utilities
|
|
16
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: numpy
|
|
27
|
+
Requires-Dist: tqdm
|
|
28
|
+
Requires-Dist: pandas
|
|
29
|
+
Requires-Dist: astroquery
|
|
30
|
+
Requires-Dist: matplotlib
|
|
31
|
+
Requires-Dist: astropy
|
|
32
|
+
Requires-Dist: pytest
|
|
33
|
+
Requires-Dist: ipython
|
|
34
|
+
Requires-Dist: sphinx
|
|
35
|
+
Requires-Dist: sphinx-rtd-dark-mode
|
|
36
|
+
Requires-Dist: sphinxcontrib-video
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# EPHESSOS
|
|
40
|
+
Ephemeris for Solar System Objects with JPL/Horizons
|
|
41
|
+
|
|
42
|
+
[](https://pypi.org/project/ephessos/)
|
|
43
|
+
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
44
|
+
|
|
45
|
+
EPHESSOS is a Python library for querying ephemeris data of solar system objects from NASA's JPL Horizons system. It provides an easy interface to retrieve positional and observational data for asteroids, comets, and planets.
|
|
46
|
+
|
|
47
|
+
## Features
|
|
48
|
+
|
|
49
|
+
- Query JPL Horizons using orbital elements or object designations
|
|
50
|
+
- Parse MPC NEA (Near-Earth Asteroid) data files
|
|
51
|
+
- Retrieve comprehensive ephemeris data including RA, Dec, distance, and more
|
|
52
|
+
- Support for custom time ranges and step sizes
|
|
53
|
+
- Integration with Astropy for astronomical calculations
|
|
54
|
+
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
Install EPHESSOS using pip:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install ephessos
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Or from source:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
git clone https://github.com/Borlaff/EPHESSOS.git
|
|
67
|
+
cd EPHESSOS
|
|
68
|
+
pip install .
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
Here's a simple example showing how to query the ephemeris of asteroid (433) Eros:
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import ephessos as ep
|
|
77
|
+
from astropy.time import Time
|
|
78
|
+
|
|
79
|
+
# Define time range
|
|
80
|
+
mjd_start = Time('2024-01-01T00:00:00', format='isot', scale='utc').mjd
|
|
81
|
+
mjd_end = Time('2024-01-15T00:00:00', format='isot', scale='utc').mjd
|
|
82
|
+
|
|
83
|
+
# Query Horizons for Eros (designation: 00433)
|
|
84
|
+
eros_data = ep.core.sso_query_to_horizons(
|
|
85
|
+
designation="00433",
|
|
86
|
+
mjd_start=mjd_start,
|
|
87
|
+
mjd_end=mjd_end,
|
|
88
|
+
step_size="1d",
|
|
89
|
+
verbose=True
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
print(eros_data.head())
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
This will return a pandas DataFrame containing ephemeris data including:
|
|
96
|
+
- Right Ascension (RA) and Declination (Dec) in degrees
|
|
97
|
+
- Distance from observer
|
|
98
|
+
- Magnitude and other observational quantities
|
|
99
|
+
- Modified Julian Date (MJD)
|
|
100
|
+
|
|
101
|
+
## Advanced Usage
|
|
102
|
+
|
|
103
|
+
### Reading MPC Data Files
|
|
104
|
+
|
|
105
|
+
EPHESSOS can parse MPC-formatted NEA files:
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
# Read MPC NEA data
|
|
109
|
+
nea_table = ep.core.read_mpc_nea_file("path/to/nea.txt")
|
|
110
|
+
|
|
111
|
+
# Query ephemeris for the first object
|
|
112
|
+
first_object = nea_table.iloc[0]
|
|
113
|
+
data = ep.core.sso_query_to_horizons(
|
|
114
|
+
designation=first_object["Designation"],
|
|
115
|
+
epoch=first_object["Epoch"],
|
|
116
|
+
eccentricity=first_object["Eccentricity"],
|
|
117
|
+
node=first_object["Node"],
|
|
118
|
+
arg_perihelion=first_object["Arg_Perihelion"],
|
|
119
|
+
inclination=first_object["Inclination"],
|
|
120
|
+
mean_anomaly=first_object["Mean_Anomaly"],
|
|
121
|
+
semimajor_axis=first_object["Semimajor_Axis"],
|
|
122
|
+
mean_motion=first_object["Mean_Motion"],
|
|
123
|
+
mjd_start=mjd_start,
|
|
124
|
+
mjd_end=mjd_end,
|
|
125
|
+
step_size="1d"
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
## Documentation
|
|
131
|
+
|
|
132
|
+
Full documentation is available at: [https://ephessos.readthedocs.io/](https://ephessos.readthedocs.io/)
|
|
133
|
+
|
|
134
|
+
## Contributing
|
|
135
|
+
|
|
136
|
+
Contributions are welcome! Please see our [contributing guidelines](CONTRIBUTING.md) for details.
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
EPHESSOS is licensed under the BSD 3-Clause License. See [LICENSE](LICENSE) for details.
|
|
141
|
+
|
|
142
|
+
## Citation
|
|
143
|
+
|
|
144
|
+
If you use EPHESSOS in your research, please cite:
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
Borlaff, A. S., & Dotson, J. (2026). EPHESSOS: Ephemeris for Solar System Objects with JPL/Horizons.
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Contact
|
|
151
|
+
|
|
152
|
+
- **Authors**: Alejandro S. Borlaff, Jessie Dotson
|
|
153
|
+
- **Email**: a.s.borlaff@nasa.gov, jessie.dotson@nasa.gov
|
|
154
|
+
- **Repository**: [https://github.com/Borlaff/EPHESSOS](https://github.com/Borlaff/EPHESSOS)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
setup.py
|
|
5
|
+
ephessos/__init__.py
|
|
6
|
+
ephessos/core.py
|
|
7
|
+
ephessos.egg-info/PKG-INFO
|
|
8
|
+
ephessos.egg-info/SOURCES.txt
|
|
9
|
+
ephessos.egg-info/dependency_links.txt
|
|
10
|
+
ephessos.egg-info/requires.txt
|
|
11
|
+
ephessos.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ephessos
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "Cython >=0.29.21", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ephessos"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Ephemeris for Solar System Objects with JPL/Horizons"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = {text = "BSD"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Alejandro S. Borlaff", email = "a.s.borlaff@nasa.gov"}, {name = "Jessie Dotson", email = "jessie.dotson@nasa.gov"}
|
|
14
|
+
]
|
|
15
|
+
keywords = ["HWO", "SSOs", "Horizons", "JPL"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Science/Research",
|
|
19
|
+
"Topic :: Utilities",
|
|
20
|
+
"License :: OSI Approved :: BSD License",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
dependencies = [
|
|
30
|
+
"numpy",
|
|
31
|
+
"tqdm",
|
|
32
|
+
"pandas",
|
|
33
|
+
"astroquery",
|
|
34
|
+
"matplotlib",
|
|
35
|
+
"astropy",
|
|
36
|
+
"pytest",
|
|
37
|
+
"ipython",
|
|
38
|
+
"sphinx", "sphinx-rtd-dark-mode", "sphinxcontrib-video",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[project.urls]
|
|
42
|
+
Homepage = "https://github.com/Borlaff/EPHESSOS"
|
|
43
|
+
Repository = "https://github.com/Borlaff/EPHESSOS"
|
|
44
|
+
Tracker = "https://github.com/Borlaff/EPHESSOS/issues"
|
|
45
|
+
Documentation = "https://ephessos.readthedocs.io/en/stable/"
|
|
46
|
+
"Source Code" = "https://github.com/Borlaff/EPHESSOS"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
[tool.setuptools]
|
|
50
|
+
packages = ["ephessos"]
|
|
51
|
+
|
|
52
|
+
[tool.setuptools.package-data]
|
|
53
|
+
rosalia = ["*.mplstyle", "*.csv", "*.txt", "images/*", "bin/*"]
|
|
54
|
+
|
|
55
|
+
[tool.pytest.ini_options]
|
|
56
|
+
testpaths = ["ephessos"]
|
|
57
|
+
python_files = ["test_*.py", "*_test.py"]
|
|
58
|
+
addopts = "-v"
|
|
59
|
+
|
|
60
|
+
[tool.black]
|
|
61
|
+
line-length = 100
|
|
62
|
+
target-version = ["py39", "py310", "py311", "py312", "py313"]
|
|
63
|
+
|
|
64
|
+
[tool.isort]
|
|
65
|
+
profile = "black"
|
|
66
|
+
line_length = 100
|
ephessos-1.0.0/setup.cfg
ADDED
ephessos-1.0.0/setup.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from setuptools import setup, Extension
|
|
3
|
+
from Cython.Build import cythonize
|
|
4
|
+
from Cython.Compiler import Options
|
|
5
|
+
|
|
6
|
+
Options.docstrings = True
|
|
7
|
+
Options.annotate = False
|
|
8
|
+
|
|
9
|
+
scripts = [str(s) for s in Path('bin/').iterdir()
|
|
10
|
+
if s.is_file() and s.name != '__pycache__']
|
|
11
|
+
|
|
12
|
+
setup(scripts=scripts)
|