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:

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
Table length=3
l2filenameobsdateobjectexptimeccfrvmod
str22str19str9float64float64
neid20241101_0001.fits2024-11-01T03:12:00HD 189733300.0-2.276
neid20241101_0002.fits2024-11-01T03:25:00HD 189733300.0-2.279
neid20241102_0001.fits2024-11-02T03:18:00HD 189733300.0-2.281

Each row is one observation. The columns we asked for:

  • l2filename — the name of the L2 FITS file; you need it (with l2filepath) 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
Table length=3
l2filenameobsdateobjectexptimeccfrvmod
str22str19str9float64float64
neid20241101_0001.fits2024-11-01T03:12:00HD 189733300.0-2.276
neid20241101_0002.fits2024-11-01T03:25:00HD 189733300.0-2.279
neid20241102_0001.fits2024-11-02T03:18:00HD 189733300.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: