Start with recorded positions
Before we can calculate a chart, we need positions for the Sun, Moon, planets and other bodies at the time we’re interested in. Astronomers combine observations with calculations of motion to build models that provide these positions across a range of dates. Our first task is to understand where those positions come from and what they mean before we use them in a chart.
Before this lesson
Start with orientation. A vector here is just an ordered list of three numbers; no trigonometry is needed.
What you will learn
You will be able to explain how an ephemeris supplies positions, interpret a position and velocity relative to a chosen origin, and count samples across a time interval.
Dotted-underlined terms open a definition beside the text. Select one to read more, then close it to continue.
Each step has its own check. Pass every step to complete the lesson. Your answers and checked steps are saved in this browser, so you can continue after leaving or reloading.
1. Where astronomical positions come from
Imagine calculating a chart for a date many years ago. We need a way to find where each body was at that time, even though we cannot observe that moment now. Astronomers use observations to constrain models of motion, then calculate positions for times within the models’ supported ranges. A table or model that supplies positions over time is called an A model of positions over time An ephemeris is a table or model describing where celestial bodies are at different times. The positions used here are calculated from such a model, rather than measured directly from a photograph. Park and colleagues (2021): the DE440 and DE441 ephemeridesJet Propulsion Laboratory Horizons manual: vectors, centers, frames and time.
This project uses source data from the Jet Propulsion Laboratory (JPL). There are two ways we obtain it. For the planets and Moon, we download DE440s, a compact file of planetary and lunar model data. The file is a kernel: it contains data from which positions can be reconstructed locally. For Ceres and Chiron, we use JPL’s Horizons online service to calculate tables of positions and velocities at selected times.
These are two ways of accessing calculated motion: a model we can evaluate on our computer, and a service that evaluates motion for us and returns a table. In Horizons, we choose the body, dates and coordinate conventions. Those choices are the request; the resulting table is the response. The rows are calculated positions, rather than a collection of direct observations at each requested time.
The eventual chart needs directions relative to Earth, expressed in the coordinates used by the chart. Our source data is an earlier stage of that calculation. For Ceres and Chiron, we begin with positions relative to the Sun. Later lessons will follow how the preparation converts source positions into Earth-relative directions and then into chart coordinates. Keeping these stages distinct helps us understand what each calculation accomplishes.
The people and services behind the inputs
JPL is a NASA laboratory managed by the California Institute of Technology (Caltech). Its origins lie in rocket experiments by Caltech researchers and amateur enthusiasts in the 1930s; it became part of NASA in 1958.
DE440 means Development Ephemeris 440, a particular version of the planetary and lunar model. Ryan S. Park, a JPL scientist and engineer who develops models of planetary motion, led its 2021 paper. The model combines observations with calculations of motion and adds seven years of data beyond DE430.
Horizons calculates positions and velocities for requested times. JPL’s Solar System Dynamics group developed the service and introduced it to the astronomical community in 1996.
- Jet Propulsion Laboratory: laboratory origins and history
- Park and colleagues (2021): the DE440 and DE441 ephemerides
- Jet Propulsion Laboratory: Ryan S. Park, scientist and engineer working on planetary ephemerides
- Jet Propulsion Laboratory Horizons manual: vectors, centers, frames and time
- Jet Propulsion Laboratory Horizons news: October 22, 1996 introduction to the astronomical community
To repeat a calculation later, keep the source data and the choices that give it meaning. Horizons can update its underlying solutions, so asking for the same dates again may produce different numbers. Its solution header, the text before the numerical rows, identifies the calculation behind the table. Saving that context lets us tell which source we used.
For example, a saved table may describe Ceres relative to Earth while the next calculation expects Ceres relative to the Sun. The file can be intact and readable, but its coordinates answer a different question. We must obtain the required Sun-relative positions or explicitly transform the coordinates; changing a label cannot move their origin.
Optional implementation: recording the downloaded inputs
The repository’s Python preparation program, tools/regenerate.py, saves downloaded bytes with the URL, parameters, retrieval time and byte count. For Horizons it also saves the solution header.
It records a A fingerprint of saved bytes SHA stands for Secure Hash Algorithm. SHA-256 produces a 256-bit fingerprint from a sequence of bytes; a bit is one binary digit, either 0 or 1. Comparing a recorded digest with a newly computed one checks the saved response against its record. It does not check whether the astronomical model is accurate. National Institute of Standards and Technology FIPS 180-4: Secure Hash Standard to check that the saved bytes still agree with their record. Reuse requires both the raw file and metadata, a matching digest, and matching request choices. New downloads also receive format checks before the input manifest is written. These checks establish agreement with the record, not astronomical accuracy.
Connect this step to the source
tools/regenerate.py
recorded_get; acquire
Paths refer to the astrology-engine repository. Examples use invented inputs; a successful exercise is not an astronomical-accuracy test.
Sources for this section
- Jet Propulsion Laboratory: laboratory origins and history
- Park and colleagues (2021): the DE440 and DE441 ephemerides
- Jet Propulsion Laboratory: Ryan S. Park, scientist and engineer working on planetary ephemerides
- Jet Propulsion Laboratory Horizons manual: vectors, centers, frames and time
- Jet Propulsion Laboratory Horizons news: October 22, 1996 introduction to the astronomical community
- National Institute of Standards and Technology FIPS 180-4: Secure Hash Standard
Apply this step
Answer every part, then check. You can retry as often as you like.
2. What a position and velocity mean
A saved row becomes useful only when we know what its numbers mean. Think of three perpendicular rulers meeting at zero. A position is three signed readings along them, written (x, y, z). A negative reading places the object on the negative side of that ruler; it does not mean the object has a negative distance from the Sun.
Take the invented row “2451545.0, calendar label, 3000, −4000, 0, 1, 2, 0”. The three position readings are (3000, −4000, 0) kilometers. The y reading places the target 4,000 kilometers on the negative y side. The next three readings, (1, 2, 0) kilometers per second, are its velocity: how quickly each position coordinate changes. These are teaching numbers, not a Ceres observation, longitude or latitude.
position = (x, y, z) km
velocity = (vx, vy, vz) km/s
We still need to place those rulers. For our Ceres and Chiron tables, the Sun’s center is zero: the coordinate origin. This makes the positions heliocentric, meaning Sun-centered. A position relative to Earth’s center would instead be geocentric, meaning Earth-centered. The origin says where the readings begin; it is a separate choice from which way the rulers point.
The directions of the rulers form a reference frame. Here we use the axes of the Reference directions for the axes A reference frame supplies agreed directions for coordinate axes. Here the request selects the ICRF axes while choosing the Sun as the origin. The frame and origin are separate choices: changing where zero is does not by itself change which way the axes point. Jet Propulsion Laboratory Horizons manual: vectors, centers, frames and time. Those axes are distinct from the tilted ecliptic coordinates used later in a chart. Moving the origin from the Sun to Earth does not rotate the axes into the chart’s coordinate system; changing the origin and changing the axes are separate operations.
Each row also needs units and a time. Our positions are in kilometers and velocities in kilometers per second. The first field is a Julian date, a continuous count of days, expressed on the scale called The time scale of the supplied rows TDB is a time scale used to model motion in the solar system. Keep this label with the Julian dates in the response: a continuous day count alone does not identify its time scale. The next lesson follows the time conversions. Jet Propulsion Laboratory Horizons manual: vectors, centers, frames and time. Keeping the time-scale label is as necessary as keeping the kilometer label: the day count alone does not say which time scale it belongs to. The next lesson explains these time and unit conventions.
There is one more choice to make. Do we want the body’s position relative to the Sun at the same instant, or do we want to account for the time light takes to travel? Our source rows use the first choice, called a geometric state. Each row describes position and velocity at one instant, without a light-travel correction. Later calculations handle light travel when forming Earth-relative directions. Together, the body, origin, axes, time, units and correction choices tell us what every row means.
Optional implementation: the Horizons settings and row layout
CENTER=500@10 selects the Sun’s center. REF_SYSTEM=ICRF and REF_PLANE=FRAME select ICRF axes. OUT_UNITS=KM-S selects kilometers and kilometers per second, and TIME_TYPE=TDB selects the time scale. VEC_CORR=NONE requests geometric states; VEC_TABLE=2 requests both position and velocity.
The parser reads between $$SOE and $$EOE, the start and end markers. It takes the first field as Julian date, skips the calendar label, and reads x, y, z, vx, vy and vz. The settings supply the meaning that the numbers alone cannot convey.
Connect this step to the source
tools/jpl/horizons.py
_fetch_window; _parse_vectors
Paths refer to the astrology-engine repository. Examples use invented inputs; a successful exercise is not an astronomical-accuracy test.
Sources for this section
Apply this step
Answer every part, then check. You can retry as often as you like.
3. Follow motion across a time interval
A chart asks for a position at one particular time. To support many possible chart dates, we need a representation of motion across a whole interval. For Ceres and Chiron, we begin with Horizons rows at selected times and later fit curves to those positions. The curves will let us calculate positions between the sampled times.
Choosing sample times means choosing how much of that motion we give the fitter to work with. We arrange them in a sample grid: a sequence of dates spanning the interval. Missing dates leave less information about part of the motion. Counting the spaces between dates is a useful first check that the expected samples are present, although it cannot establish the accuracy of the fitted curve.
Start at JD 2451545 and stop at JD 2451553, taking a row every two days. The span is eight days, which contains four two-day gaps. Including the first endpoint gives five rows: 2451545, 2451547, 2451549, 2451551 and 2451553. Five rows have four gaps, because each new gap connects the next row to one already counted.
N = (2451553 − 2451545) / 2 + 1 = 5 rows
When the span divides exactly by the step, divide to count the gaps and add one for the first endpoint:
N = (stop − start) / step + 1
Here start, stop and step are in days, so division leaves a count rather than a duration. This equation assumes a positive step and a span exactly divisible by it. It describes the evenly spaced worked grid; it does not choose how fine the sampling needs to be for an accurate fit.
Suppose our five-row grid contains a repeated 2451549. Six received rows then contain only five distinct sample times. That is enough to pass the count check. If 2451551 is missing and only four distinct times remain, the preparation rejects the incomplete grid before fitting. Repeating a position at one time cannot supply the missing information at another.
Once the source positions have a consistent meaning and cover the intended times, we can prepare them for the later calculations. The next lesson puts their dates and distances on the scales used by the fitting tools. Later lessons will measure how closely the fitted curves reproduce the source positions; having enough rows alone does not answer that question.
Optional implementation: counting and combining samples
The current Python implementation computes N = round((stop − start) / step) + 1. Python rounds exact halfway values to the nearest even integer. When the span does not divide exactly, the last epoch can differ from the supplied stop. Our worked example divides exactly.
Requests are divided into pages of at most 70,000 rows. A page of m rows uses the bare integer STEP_SIZE=m−1 to ask Horizons for that many intervals, rather than a duration in days.
After combining pages, the script rounds Julian dates to nine decimal places to identify duplicates, keeps the first occurrence and preserves input order. It rejects fewer distinct epochs than expected. This count check does not verify every gap or establish that the epochs are the intended ones; the rounding rule is not an accuracy claim.
Connect this step to the source
tools/jpl/horizons.py
fetch_states
Paths refer to the astrology-engine repository. Examples use invented inputs; a successful exercise is not an astronomical-accuracy test.
Sources for this section
Apply this step
Answer every part, then check. You can retry as often as you like.
Your lesson checks
0 of 3 steps passed.
Use the feedback beside each check to retry any unfinished step.