Quantum
Quest

Algorithms, Math, and Physics

Extracting accurate orbital data using NASA JPL Horizons API

In my recent endeavors, I have focused on leveraging the NASA JPL Horizons API to extract accurate and up-to-date orbital data for celestial bodies in our solar system. This data is crucial for my simulations and computational models in astrophysics and quantum physics.

Motivation

Understanding the precise mechanics of celestial bodies requires accurate data regarding their orbits, mass, and physical characteristics. Traditional methods often involve manual calculations and estimations that can introduce errors. Therefore, I decided to automate this process using a Python program, enhancing both accuracy and efficiency.

Methodology

The core of my project involves several Python functions that handle API requests, parse responses, and calculate necessary values from the data obtained. Below is a brief overview of the essential functions within my program:

1. Mass extraction

To determine the mass of celestial bodies, I use the following function:


def get_mass(response_text):
    mass_match = re.search(
        r"Mass\s*x\s*10\^(\d+)\s*\(g|kg\)\s*=\s*([\d\.]+)",
        response_text, re.IGNORECASE
    )
    if mass_match:
        exponent = int(mass_match.group(1))
        mass_value = float(mass_match.group(2)) * (10 ** exponent)
        return mass_value
    else:
        raise ValueError("Mass not found in the response.")

2. Radius extraction

The radius is extracted using a similar regex-based approach:


def get_radius(response_text):
    radius_match = re.search(
        r"vol\.\s*mean\s*radius\s*\(km\)\s*=\s*([\d\.]+)",
        response_text, re.IGNORECASE)
    if radius_match:
        mean_radius_km = float(radius_match.group(1))
        mean_radius_m = mean_radius_km * 1000
        return mean_radius_m
    else:
        raise ValueError("Mean radius not found in the response.")

3. Position and velocity

The position and velocity of celestial bodies are extracted and converted to more manageable units:


def get_position_velocity(response_text, start_date):
    # convert start date to Julian date as float
    start_jd = float(to_julian_date(start_date))

    # Regular expression to find the first set of position and velocity values
    pv_match = re.search(
        r"^\s*(\d+\.\d+)\s*=\s*[A-Za-z0-9\.\-\s:]+TDB\s+"
        r"X\s*=\s*([-\d\.E+]+)\s*Y\s*=\s*([-\d\.E+]+"
        r")\s*Z\s*=\s*([-\d\.E+]+)\s*"
        r"VX\s*=\s*([-\d\.E+]+)\s*VY\s*=\s*([-\d\.E+]+"
        r")\s*VZ\s*=\s*([-\d\.E+]+)",
        response_text, re.IGNORECASE | re.MULTILINE
    )

    if pv_match:
        jd = float(pv_match.group(1))
        # allow a small tolerance for JD matching
        if abs(jd - start_jd) > 1e-5:
            raise ValueError(f"Julian Date {jd} does not match the"
                             f"start date JD {start_jd}")

        position = [
            float(pv_match.group(2)) * 1000,
            float(pv_match.group(3)) * 1000,
            float(pv_match.group(4)) * 1000
        ]
        velocity = [
            float(pv_match.group(5)) * 1000,
            float(pv_match.group(6)) * 1000,
            float(pv_match.group(7)) * 1000
        ]
        return position, velocity
    else:
        raise ValueError("Position and velocity not found in the response.")

4. API request construction

The construction of API requests is crucial for fetching the data:


for body in bodies:
    print(f'processing {body}')
    body_info = data[body]
    query_params = {
        "format": "json",
        "COMMAND": f"'{body_info['code']}'",
        "CSV_FORMAT": "NO",
        "OBJ_DATA": "'YES'",
        "MAKE_EPHEM": "'YES'",
        "EPHEM_TYPE": "'VECTOR'",
        "CENTER": f"'{center_code}'",
        "OUT_UNITS": "KM-S",
        "START_TIME": f"'{start_date}'",
        "STOP_TIME": f"'{end_date}'",
        "STEP_SIZE": f"'{step}'",
        "VEC_TABLE": "'3'"
    }
    url = f"{base_url}?{urlencode(query_params)}"
    response = requests.get(url)
    response_data = response.json()

Results and discussion

Through my program, I’ve been able to streamline the process of obtaining orbital data, which has significantly enhanced the reliability of my simulations. The precision of the extracted data allows for more accurate modeling of celestial mechanics, which is indispensable for my research in quantum physics related to celestial phenomena.

The use of regex for parsing and JSON for handling data ensures that the program remains efficient and effective, capable of handling large volumes of data seamlessly.

For more insights into this topic, you can find the details here

For access to the complete simulation code, please visit the GitHub repository here.

The Horizons system is available on NASA’s website here.