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.query module is a Python wrapper around the IRSA ZTF web API. It lets you search the ZTF archive by sky position, SQL filter, or both, retrieve a metadata table describing every matching image, and then download the actual data products — all in a few lines of Python. The underlying workflow is always two steps: first fetch metadata to identify which files exist, then download the ones you want.
Public ZTF data is available without a private account. See the ZTF Data Release 3 announcement. For partnership or proprietary data, your IRSA account must be associated with ZTF. Create a free account at irsa.ipac.caltech.edu.

ZTFQuery class

ZTFQuery is the main entry point. It combines metadata search (via the IRSA API) with URL construction and file download into a single object.
from ztfquery import query

zquery = query.ZTFQuery()
The class exposes two primary methods — load_metadata() and download_data() — that represent the two mandatory steps of every data-retrieval workflow.

Two-step workflow

1

Load metadata

Call load_metadata() to query the IRSA ZTF archive. This populates the metatable property with a pandas DataFrame describing every matching image. No files are downloaded at this stage.
zquery.load_metadata(
    kind="sci",
    radec=[276.107960, 44.130398],
    size=0.01,
    sql_query="seeing<2 and obsjd>2458252.5"
)

# Inspect what was found
print(zquery.metatable[["obsjd", "seeing", "filtercode"]])
2

Download data

Call download_data() to fetch the actual files. Pass a suffix string to choose which data product to retrieve for each row in the metatable.
zquery.download_data("psfcat.fits", show_progress=False)
Files are saved locally following the IRSA directory structure, rooted at your $ZTFDATA path.

load_metadata() parameters

load_metadata() accepts both spatial constraints and an arbitrary SQL WHERE clause. Either a spatial constraint or a SQL query is required (or both).
kind
str
default:"sci"
The category of ZTF data to search. Accepted values:
ValueDescription
"sci"Science exposures and derived products (default)
"raw"Raw images as acquired from the camera
"ref"Reference (co-added) images
"cal"Calibration frames: bias (bias) or high-frequency flat (hifreqflat)
radec
list[float, float]
ICRS sky position [ra, dec] in decimal degrees. Identifies the center of the spatial search region. Must be combined with size to define a finite search area.
size
float
Full-width of the search region in decimal degrees, measured along the east axis at radec. If a single value is given it is used for both axes. A value of zero means a point search. Negative values are not allowed.
sql_query
str
A SQL WHERE clause applied server-side to filter results. Supports AND, OR, NOT, IN, BETWEEN, LIKE, and standard comparison operators. Function calls and subqueries are not supported. Required when no spatial constraint is provided.
# Seeing better than 2 arcsec, specific date window
sql_query="seeing<2 and obsjd BETWEEN 2458239.5 AND 2458254.5"

# i-band only (filter ID 3), since a given Julian Date
sql_query="fid=3 and obsjd>2458252.5"

# g-band by filter code (note the single quotes around the string)
sql_query="filtercode='zg'"

# Field 600 with airmass > 2 and quadrant 1 or 3
sql_query="field=600 AND airmass>2 AND qid IN (1,3)"
auth
list[str, str]
Inline IRSA credentials as [username, password]. When provided, the stored ~/.ztfquery credentials are ignored.

metatable property

After a successful load_metadata() call, results are stored as a pandas DataFrame accessible via zquery.metatable. Each row corresponds to one matching image. Columns include observational parameters such as obsjd, seeing, filtercode, ccdid, field, and qid.
# View selected columns
zquery.metatable[["obsjd", "seeing", "filtercode"]]

# Example output
#         obsjd   seeing filtercode
# 0  2.458277e+06  1.839     zr
# 1  2.458277e+06  1.849     zr
# ...

get_metadata() module function

A module-level convenience wrapper that creates a ZTFQuery internally and returns the metatable directly as a DataFrame.
from ztfquery import query

df = query.get_metadata(
    kind="sci",
    radec=[276.107960, 44.130398],
    size=0.01,
    sql_query="seeing<2 and obsjd>2458252.5"
)
It accepts the same parameters as load_metadata().

download_data() parameters

download_data() must be called after load_metadata(). It constructs download URLs from the metatable and fetches each file.
suffix
str
The data product to download. Selects which file type to retrieve for each entry in the metatable. See the accordion below for the full list of science image suffixes.
show_progress
bool
default:"True"
Display a progress bar during download. When nprocess > 1, this shows overall batch progress.
nprocess
int
default:"None"
Number of parallel download processes. When None or 1, downloads are sequential. Set to a higher integer (e.g. 4) to use multiprocessing for large batches.
overwrite
bool
default:"False"
When False, files that already exist locally are skipped. Set to True to force re-download of all files.
indexes
list[int]
A list of row indexes from metatable to download. Only those rows will be processed. When omitted, all rows are downloaded.
Each science exposure (kind="sci") has up to eleven associated data products. Pass any of the following strings as the suffix argument to download_data():
SuffixDescription
sciimg.fitsPrimary science image (default)
mskimg.fitsBit-mask image
psfcat.fitsPSF-fit photometry catalog
sexcat.fitsNested-aperture photometry catalog
sciimgdao.psfSpatially varying PSF estimate in DAOPhot lookup table format
sciimgdaopsfcent.fitsPSF estimate at the science image center as a FITS image
sciimlog.txtLog output from the instrumental calibration pipeline
scimrefdiffimg.fits.fzDifference image: science minus reference (fpack-compressed)
diffimgpsf.fitsPSF estimate for the difference image as a FITS image
diffimlog.txtLog output from the image subtraction and extraction pipeline
log.txtOverall system summary log from the realtime pipeline

Code examples

Generic SQL query — no coordinates

Query all observations with seeing better than 2 arcsec between two dates, then visualise the sky coverage of the results.
from ztfquery import query
from astropy import time

zquery = query.ZTFQuery()

# Convert calendar dates to Julian Dates
jdstart = time.Time("2018-05-01").jd
jdend   = time.Time("2018-05-15").jd

# Query metadata — may take a moment for large result sets
zquery.load_metadata(
    sql_query=f"seeing<2 and obsjd BETWEEN {jdstart} AND {jdend}"
)

print(zquery.metatable)  # ~50 000 entries

# Visualise observed fields on the sky (main grid only)
zquery.show_gri_fields(
    title="1 May 2018 – 15 May 2018\nseeing < 2 arcsec",
    grid="main"
)

Coordinate query with filter and time constraints

Retrieve i-band observations (filter ID 3) within 0.01 degree of a target since 14 May 2018.
from ztfquery import query
from astropy import time

zquery = query.ZTFQuery()

starttime = time.Time("2018-05-14").jd

zquery.load_metadata(
    radec=[276.107960, +44.130398],
    size=0.01,
    sql_query=f"fid=3 and obsjd>{starttime}"
)

print(zquery.metatable[["obsjd", "ccdid", "filtercode"]])
# obsjd             ccdid  filtercode
# 2.458268e+06      1      zi
# 2.458268e+06     15      zi
# ...

Reference image query

Find reference images for a sky position. Use sql_query="fid=1" (or filtercode='zg') to restrict to a single filter.
from ztfquery import query

zquery = query.ZTFQuery()

zquery.load_metadata(
    kind="ref",
    radec=[276.107960, +44.130398],
    size=0.0001
)

print(zquery.metatable[["field", "filtercode", "ccdid", "qid"]])
# field  filtercode  ccdid  qid
#   764          zg      1    3
#   726          zr     15    2
# ...

# g-band only
zquery.load_metadata(
    kind="ref",
    radec=[276.107960, +44.130398],
    size=0.0001,
    sql_query="fid=1"
)

Basic download

After loading metadata, download PSF-fit photometry catalogs for all matched entries.
from ztfquery import query

zquery = query.ZTFQuery()

zquery.load_metadata(
    radec=[276.107960, +44.130398],
    size=0.01,
    sql_query="seeing<2 and obsjd>2458252.5"
)

# Download all 42 catalogs sequentially
zquery.download_data("psfcat.fits", show_progress=False)

Parallel download with nprocess

Speed up large downloads by running multiple processes simultaneously.
zquery.download_data(
    "psfcat.fits",
    show_progress=True,
    nprocess=4,
    overwrite=True
)

Partial download using indexes

Download only specific rows from the metatable by passing their integer index values.
zquery.download_data("psfcat.fits", indexes=[4, 6, 12, 40])

Retrieve paths to local data

After downloading, get the local file paths for the data you have on disk.
local_files = zquery.get_local_data("psfcat.fits")
print(local_files)
# ['/path/to/ztfdata/sci/.../ztf_..._psfcat.fits', ...]
If you close your Python session, you must call load_metadata() again before calling get_local_data(). The metatable is needed to reconstruct the IRSA directory structure and locate the files on disk.

Download a file directly from its filename

If you have an IRSA filename string, you can download it without going through a metadata query.
from ztfquery import io

io.download_from_filename(ztfdata_filename)

Additional utilities

show_gri_fields()

Visualise the sky footprint of the queried fields as a sky map. The method signature is show_gri_fields(sizeentry="visits", grid="main", **kwargs). Additional keyword arguments (such as title) are forwarded to the underlying fields.show_gri_fields() function.
zquery.show_gri_fields(
    title="My Query Footprint",
    grid="main"       # "main" or "secondary"
)
  • sizeentry: what to encode as the field marker size — "visits" (default, observation count) or any column name present in metatable.
  • grid: "main" (primary ZTF grid, default) or "secondary" to include secondary grid fields.
Pass grid="secondary" to include secondary grid fields alongside the primary grid.

metatable_to_url()

A module-level function that converts any ZTF IRSA metatable DataFrame directly into a list of download URLs, without needing a ZTFQuery instance.
from ztfquery.query import metatable_to_url

urls = metatable_to_url(
    metatable=zquery.metatable,
    suffix="sciimg.fits"
)
This is useful when you have saved a metatable to disk and want to regenerate URLs later.

Build docs developers (and LLMs) love