This week, let's talk about something exciting and positive: The Artemis II mission (https://en.wikipedia.org/wiki/Artemis_II), currently on its way home to Earth after going around the moon, and farther from Earth than anyone has ever travelled before. Artemis is NASA's successor to the Apollo program, and is meant to get astronauts back onto the moon for the first time in more than 50 years. (In Greek mythology, Artemis was the twin sister of Apollo.)
On Monday, I spent the better part of an hour watching NASA's live stream on YouTube (https://www.youtube.com/watch?v=m3kR2KK8TEs), as the astronauts on board their Orion spacecraft prepared to circle around the moon. As someone who grew up reading about the Apollo program as history, and following all of NASA's various probes, spacecraft, and adventures over the years, it was truly astonishing to see these astronauts, in real-time, color video, traveling to the moon.
(My first paid writing gig, BTW, was as a book reviewer for Odyssey, a wonderful magazine about astronomy and space for children, back when I was about 12 years old. I earned $25!)
This week, we'll use NASA's own data to track Orion, relative to Earth and the moon.
Paid subscribers, both to Bamboo Weekly and to my LernerPython+data membership program (https://LernerPython.com) get all of the questions and answers, as well as downloadable data files, downloadable versions of my notebooks, one-click access to my notebooks, and invitations to monthly office hours.
Learning goals for this week include reading working with APIs, working with dates and times, joins, and plotting.
Data and six questions
This week's data comes from NASA's Horizons API (https://ssd-api.jpl.nasa.gov/doc/horizons.html). This system has been around for many years, and the API reflects that. You'll need to make a GET request to https://ssd.jpl.nasa.gov/api/horizons.api. (No API key or registration is needed.) You'll need to pass a number of parameters to the API, most easily done via the following Python dict:
```python
horizons_params = {
'format': 'text',
'COMMAND': f"'{command}'",
'EPHEM_TYPE': "'VECTORS'",
'START_TIME': f"'{start_time}'",
'STOP_TIME': f"'{stop_time}'",
'STEP_SIZE': "'1h'",
'VEC_TABLE': "'2'",
'CSV_FORMAT': "'YES'",
}
``` The dict reflects the parameters that you need to pass. Note that all of them must be put inside of single quotes! It's not enough for them to be strings:
formatof'text'returns a string with some CSV inside of it. You can also give'json'as a value... but that just returns a very small JSON object which contains the text inside of one element! It's just not worthwhile.COMMANDindicates what body you want to track with an integer. Natural bodies (e.g., planets and moons) get positive numbers, and spacecraft get negative numbers. So the moon is 301, and Orion is -1024. If you ask for Orion data outside of its launch time, you'll get an error. But if you ask for Orion data within its time in space, but before it has landed (as is the case as I'm writing this), you'll get its expected/predicted information. Information about the moon has no limitations.EPHEM_TYPEindcates whether we want information relative to Earth or in another format that's more appropriate for telescopes. We'll stick with'VECTORS', to give us information relative to Earth.- The
START_TIMEandSTOP_TIMEparameters are exactly what you might expect. - The
STEP_SIZEparameter describes the granularity with which we want to get results. We'll ask for'1h', for one-hour granularity. - The
VEC_TABLEindicates which values (column names) we want to get back. By specifying'2', you get:JDTDB, the Julian day (https://en.wikipedia.org/wiki/Julian_day) as a float, where.0marks noon, not midnight,datetime_str, the date and time of the observation,X,Y, andZ, for the locations relative to the center of Earth,VX,VY, andVZ, for the velocity (in km/h) along each axis- There is one more junk column that we have to read in, because of a trailing comma on each line, but we don't care about.
CSV_FORMAT: We'll say'YES', to avoid getting fix-width fields.
Here are my six questions for this week. I'll be back tomorrow with solutions and explanations:
- Write a function,
get_horizons_data, that takes three arguments: A command number, a starting time, and a stopping time. The function should return a Pandas data frame with the colummn names described inVEC_TABLE, above. Thedatetime_strshould be adatetimevalue. - Get data frames for Orion (command
'-1024') and the moon (command'301'), starting at April 2, 2026 at 02:00 and ending on April 10, 2026 at 23:00. Join them together into a single data frame, with the datetime values as the index.