Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/MickaelRigault/ztfquery/llms.txt

Use this file to discover all available pages before exploring further.

The ztfquery.sedm module connects to Pharos, the Caltech archive for the SED Machine (SEDM) integral-field spectrograph mounted on the Palomar 60-inch telescope. SEDM provides low-resolution (R ≈ 100) spectra for ZTF transient classification. The SEDMQuery class handles the full lifecycle: discovering which data exist, downloading the files to your local $ZTFDATA/sedm/redux/ tree, and surfacing them as local paths ready for analysis with pysedm.
You need a Pharos account to access SEDM data. If you are a ZTF member and do not have an account, email Richard Walters (rsw@astro.caltech.edu). Your credentials are stored in ~/.ztfquery after the first authentication prompt.

Downloading IFU cubes for a ZTF target

1

Create a SEDMQuery instance

from ztfquery import sedm

squery = sedm.SEDMQuery()
On the very first call, SEDMQuery loads the local “whatfiles” index — the nightly logs of what SEDM observed each night. If this is your first time using the module, the index needs to be built from scratch, which downloads history back to June 2018.
First use is slow. Building the complete whatfiles index for the first time can take several minutes because it fetches every nightly summary file since SEDM began systematic ZTF follow-up. On subsequent uses only the missing recent nights are fetched, making startup nearly instant.
2

Download IFU cubes

# Downloads all e3d cubes associated with this target (kind='e3d' selects cube files)
squery.download_target_data("ZTF18abqlpgq", kind="e3d")
Files are stored under $ZTFDATA/sedm/redux/YYYYMMDD/ where YYYYMMDD is the observation date. Each night with data for the target gets its own subdirectory.
3

List downloaded cube paths

cube_paths = squery.get_target_cubes("ZTF18abqlpgq")
print(cube_paths)
# ['/path/to/ZTFDATA/sedm/redux/20181012/e3d_crr_b_ifu20181012_...ZTF18abqlpgq.fits', ...]
get_target_cubes() returns only files that exist on disk. Pass exist=False to get the expected paths whether or not they have been downloaded.

Downloading spectra in TXT format

SEDM also produces extracted 1-D spectra. These are available as FITS files (default) or in the plain-text format used by the ZTF Marshal.
1

Download spectra as FITS files

from ztfquery import sedm

squery = sedm.SEDMQuery()
squery.download_target_data(
    "ZTF18abqlpgq",
    kind="spec",
    extension=".fits"
)
2

Retrieve local paths

spec_paths = squery.get_target_spectra("ZTF18abqlpgq")
print(spec_paths)
# ['/path/to/ZTFDATA/sedm/redux/20181012/spec_auto_robot_lstep1__crr_b_...ZTF18abqlpgq.fits', ...]
You can also fetch spectra in the original TXT format (as downloaded from the ZTF Marshal) by passing kind="spec" and extension=".txt" to download_target_data() (if available from Pharos for that night).

Reading and visualising with pysedm

Once you have a cube path, pysedm provides a complete analysis environment for SEDM data.
1

Install pysedm

# pysedm is not bundled with ztfquery — install it separately
# pip install pysedm
# or from source: https://github.com/MickaelRigault/pysedm
2

Load and display an IFU cube

import pysedm
from ztfquery import sedm

squery = sedm.SEDMQuery()

# get_target_cubes returns a list; [0] picks the first cube
cube_path = squery.get_target_cubes("ZTF18abqlpgq")[0]

cube = pysedm.get_sedmcube(cube_path)
cube.show(interactive=True)
cube.show(interactive=True) opens an interactive display where you can click on individual IFU spaxels to inspect their spectra, and drag to sum a region.
Citation required. If you use a SEDM spectrum obtained since July 2018 (inclusive) in a publication, please cite the pysedm pipeline paper: Rigault et al. 2019 (arXiv:1902.08526).

Understanding whatfiles

Every night SEDM writes a what.list log file recording which targets were observed, at what airmass, with what exposure time. ztfquery.sedm mirrors these logs locally as the whatfiles index.

Storage location

Whatfiles are stored as individual .parquet files at $ZTFDATA/sedm/whatfiles/what_YYYYMMDD.parquet and as a merged store at $ZTFDATA/sedm/whatfiles/stored_data.parquet.

Automatic updates

Every time you call SEDMQuery() it checks whether any recent nights are missing from the local index and downloads only those. You never need to manage updates manually.
The nightly whatfile drives all target lookups. When you call download_target_data("ZTF18abqlpgq", kind="e3d"), the library first searches the whatfiles index for every night on which that target was observed, then builds the correct Pharos URLs for those nights, and finally downloads only the files that are not already on disk.
The first time you import ztfquery.sedm the library needs to download the complete whatfiles history (June 2018 to today). This is a one-time cost. After that, each call only fetches the new nights since your last update.

IRSA light curves with LCQuery

As a bonus, the ztfquery.lightcurve module provides access to the IRSA ZTF Light Curve API. These are catalog-matched light curves derived from epochal science images — entirely independent of alert packets, and well-suited for variable star and AGN science.

Query by sky position

from ztfquery import lightcurve

# RA, Dec in degrees, search radius in arcsec
lcq = lightcurve.LCQuery.from_position(197.501495, +75.721959, 5)

# The full light curve table is a pandas DataFrame
print(lcq.data.head())

# Plot the multi-band light curve
lcq.show()

Query by ZTF object ID

from ztfquery import lightcurve

lcq = lightcurve.LCQuery.from_id([686103400067717, 686103400106565])
lcq.show()

Download with advanced parameters

from ztfquery import lightcurve

# CIRCLE query (RA, Dec, radius in degrees) filtered to g-band only
data = lightcurve.LCQuery.download_data(
    circle=[298.0025, 29.87147, 0.0014],
    bandname="g"
)
The download_data() static method returns a pandas DataFrame directly. If you already have a DataFrame (e.g. loaded from a CSV), wrap it in LCQuery to access .show():
from ztfquery import lightcurve

lcq = lightcurve.LCQuery(data)  # data is an existing DataFrame
lcq.show()
IRSA light curves are built from matching the epochal PSF-fit catalogs against reference coadd sources. They are not generated from ZTF alert packets. The same source may appear under a different oid in the alert stream. For the highest-cadence, alert-based light curves use the Fritz API (see the Fritz Light Curves guide).

Build docs developers (and LLMs) love