NEID L2: querying and inspecting RV products
This is the most common NEID workflow: search the Level-2 holdings over a date range, keep just the columns you care about, and look at what comes back. By the end you will have an astropy Table of radial velocities ready to plot or fit.
Note
This notebook runs against the live NEID server. The published version here uses synthetic data so it builds without an archive account — the numbers shown are illustrative, not real observations.
What is NEID L2?
NEID is a high-precision radial velocity (RV) spectrograph. Its archive offers files at several data levels — a ladder of how far the data has been processed:
L0 — raw detector frames, straight off the CCD.
L1 — calibrated 1D extracted spectrum (flux vs. wavelength).
L2 — RV-ready products: the CCF (cross-correlation function) and the radial velocity derived from it.
Most science users want L2, because that is where the radial velocities live. The pipeline measures each RV by cross-correlating the star’s spectrum against a template of known stellar lines and finding the Doppler shift of the result; you never compute any of that yourself. For the full story see Data levels and Radial velocities and the CCF.
Build the archive client
NEIDArchive() with no arguments points at the IPAC production server. Public
L2 data is queryable without login().
from nexsci_rv import NEIDArchive
neid = NEIDArchive()
neid
<nexsci_rv.archives.neid.NEIDArchive at 0x77a206d40380>
Query by date range
All query methods return an astropy.table.Table. Use columns= to keep only
what you need; the package validates column names against the table’s static
schema before any HTTP request.
tbl = neid.query_datetime(
"l2",
("2024-11-01", "2024-11-06"),
columns=["l2filename", "obsdate", "object", "exptime", "ccfrvmod"],
maxrec=20,
)
tbl
| l2filename | obsdate | object | exptime | ccfrvmod |
|---|---|---|---|---|
| str22 | str19 | str9 | float64 | float64 |
| neid20241101_0001.fits | 2024-11-01T03:12:00 | HD 189733 | 300.0 | -2.276 |
| neid20241101_0002.fits | 2024-11-01T03:25:00 | HD 189733 | 300.0 | -2.279 |
| neid20241102_0001.fits | 2024-11-02T03:18:00 | HD 189733 | 300.0 | -2.281 |
Each row is one observation. The columns we asked for:
l2filename— the name of the L2 FITS file; you need it (withl2filepath) to download the data later.obsdate — the observation time stamp; this is the column query_datetime filters on.
object — the free-text target name the observer typed in.
exptime — exposure time in seconds.
ccfrvmod — the answer: the radial velocity in m/s, the number you would phase-fold and fit for a planet (its error bar is ccfnoise).
For the full column tour see Understanding your results; describe_table
(below) lists every column the table offers.
Tip
We searched by date range here because a time window is the safest first
query — it always works. When you know a star by name, RA/Dec, a catalog ID, a
program, or a PI instead, there is a dedicated query_* method for each. See
Choosing a query for picking the right one.
maxrec caps how many rows the server returns (here, 20). Keep it small while
you are still working out a query, then raise it once the results look right.
Most NEID data is public and needs no login. Reaching data still inside its
proprietary period requires neid.login() with IPAC NEID credentials —
see Querying vs downloading, and proprietary data.
Multi-criterion query in one round-trip
query_criteria composes constraints into a single ADQL query — one HTTP
request even with several filters.
from astropy import units as u
tbl2 = neid.query_criteria(
{
"data_level": "l2",
"datetime": ("2024-11-01", "2024-11-06"),
"object": "HD 189733",
"object_radius": 30 * u.arcsec,
},
columns=["l2filename", "obsdate", "object", "ccfrvmod"],
maxrec=20,
)
tbl2
| l2filename | obsdate | object | exptime | ccfrvmod |
|---|---|---|---|---|
| str22 | str19 | str9 | float64 | float64 |
| neid20241101_0001.fits | 2024-11-01T03:12:00 | HD 189733 | 300.0 | -2.276 |
| neid20241101_0002.fits | 2024-11-01T03:25:00 | HD 189733 | 300.0 | -2.279 |
| neid20241102_0001.fits | 2024-11-02T03:18:00 | HD 189733 | 300.0 | -2.281 |
Inspecting the schema
describe_table returns the server-side TAP_SCHEMA metadata for a given
table — useful for finding columns that aren’t in the package’s static map.
if not OFFLINE:
schema = neid.describe_table("neidl2")
schema[:10]
else:
print("(skipped in offline mode)")
(skipped in offline mode)
What next
You now have a table of NEID radial velocities. From here:
EXPRES solar: an RV time series — the same query pattern applied to the EXPRES solar RV time series.
Downloading FITS files and plotting a spectrum — turn a result table into FITS files on disk and open a spectrum.
Quickstart — every query pattern at a glance.