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.fritz module provides Python wrappers around the fritz.science SkyPortal API. It covers photometry (light curves), spectra, alerts, and group-level source management. Every download function follows the same convention: pass get_object=True to receive a rich Python object with plotting and filtering methods, or omit it to get the raw data structure. All objects store data locally so subsequent calls are fast.
You need a fritz.science account and a personal API token from your profile page. The first time you call any download_ function, ztfquery will prompt you for the token and save it to ~/.ztfquery. You need ztfquery >= 1.12.0 for Fritz support.

Getting a light curve for a ZTF source

1

Download the light curve and get a FritzPhotometry object

from ztfquery import fritz

lc = fritz.download_lightcurve("ZTF20acmzoxo", get_object=True)
Setting get_object=True wraps the downloaded data in a FritzPhotometry instance. Without it the function returns a bare pandas DataFrame.
2

Plot the light curve

lc.show()
The plot shows detections as error-bar points (colour-coded by filter) and non-detections as downward-pointing triangles. The y-axis is inverted so brighter magnitudes appear higher.
3

Inspect the data columns

print(lc.data.columns)
Index(['obj_id', 'ra', 'dec', 'filter', 'mjd', 'instrument_id',
       'instrument_name', 'ra_unc', 'dec_unc', 'origin', 'id', 'groups', 'mag',
       'magerr', 'magsys', 'limiting_mag'],
      dtype='object')
The full photometry table is available as lc.data, a standard pandas DataFrame you can slice and export normally.

Extracting coordinates from a light curve

The get_coordinates() method aggregates the per-epoch RA/Dec measurements that Fritz reports alongside each photometry point.
# Return the full table of per-epoch coordinates (detected points only)
lc.get_coordinates(full=True)
              ra        dec
0     331.205290  16.856651
2     331.205307  16.856643
4     331.205307  16.856643
5     331.205293  16.856643
6     331.205317  16.856641
...          ...        ...
289   331.205293  16.856636
290   331.205293  16.856636
291   331.205295  16.856650
292   331.205303  16.856639
293   331.205295  16.856650
To get a single best-estimate position, apply a robust statistic across all epochs:
# Median RA and Dec as a two-element NumPy array
lc.get_coordinates(method="nanmedian")
# array([331.2052937,  16.8566374])
The method argument accepts any NumPy reduction function name that operates column-wise, such as "nanmean", "nanmedian", "nanmin", or "nanmax".

Filtering photometry

Use get_data() to slice the photometry table by filter name, detection status, and time range without modifying the underlying lc.data DataFrame.
# i-band detections only, between 22 Oct and 15 Nov 2020
filtered = lc.get_data(
    filters="ztfi",
    detected=True,
    time_range=["2020-10-22", "2020-11-15"]
)
Pass the same arguments directly to show() via the filtering keyword to visualise the filtered subset without creating a separate variable:
lc.show(
    filtering=dict(
        filters="ztfi",
        detected=True,
        time_range=["2020-10-22", "2020-11-15"]
    )
)
Key get_data() parameters:
ParameterTypeDescription
detectedbool or NoneTrue = detections only; False = upper limits only; None = all
filtersstr or listFilter name(s) such as "ztfg", "ztfr", "ztfi", or ["ztfg","ztfr"]; "*" means no filter
time_range[start, end]ISO-format date strings; use None for an open boundary
querystr or listAdditional pandas query() expressions applied last

Storing and loading locally

Every FritzPhotometry object can be saved to disk and reloaded without hitting the Fritz API again.
# Save — the file format is determined by the extension
lc.store("my_lightcurves/ZTF20acmzoxo.csv")    # CSV
lc.store("my_lightcurves/ZTF20acmzoxo.h5")     # HDF5
lc.store("my_lightcurves/ZTF20acmzoxo.json")   # JSON
To reload from the default ztfquery storage location (used when lc.store() was called after download):
lc = fritz.FritzPhotometry.from_name("ZTF20acmzoxo")
The default storage path is $ZTFDATA/fritz/lightcurve/fritz_lightcurve_ZTF20acmzoxo.csv. Call lc.store() after the initial download to write the file; subsequent calls to FritzPhotometry.from_name() will load from disk without hitting the Fritz API.

Spectra

The download_spectra() function follows the same pattern as download_lightcurve() but returns a FritzSpectrum object (or a list of them if the source has multiple spectra).
1

Download a spectrum

from ztfquery import fritz

spec = fritz.download_spectra(
    "ZTF20acmzoxo",
    get_object=True,
    store=True         # store locally for fast future access
)
If the source has already been downloaded and stored you can reload it with:
spec = fritz.FritzSpectrum.from_name("ZTF20acmzoxo")
2

Plot the spectrum

spec.show()
This plots flux versus wavelength (in Ångströms) with a shaded error envelope if uncertainties are available.
3

Inspect the raw Fritz dictionary

The complete JSON payload from Fritz is always available as spec.fritzdict:
print(spec.fritzdict.keys())
dict_keys(['created_at', 'followup_request_id', 'modified', 'assignment_id',
           'wavelengths', 'altdata', 'fluxes', 'original_file_string', 'errors',
           'original_file_filename', 'obj_id', 'owner_id', 'observed_at', 'id',
           'origin', 'instrument_id', 'groups', 'instrument_name', 'reducers',
           'observers'])
4

Save the spectrum

spec.store("spectra/ZTF20acmzoxo_sedm.fits")    # FITS
spec.store("spectra/ZTF20acmzoxo_sedm.ascii")   # ASCII text (wavelength, flux, error)
spec.store("spectra/ZTF20acmzoxo_sedm.json")    # JSON (raw Fritz dict)
spec.store("spectra/ZTF20acmzoxo_sedm.txt")     # Text
The output format is selected automatically from the file extension.

FritzAccess: working with groups

FritzAccess provides a higher-level interface for managing collections of sources organised into Fritz science groups.
1

Create a FritzAccess instance and load your groups

from ztfquery import fritz

faccess = fritz.FritzAccess()
faccess.load_groups()
2

List the groups you have access to

print(faccess.groups.accessible)
  nickname                   modified   id                  name  single_user_group                created_at
0   infant  2020-10-21T06:20:34.549465   49  Infant Supernovae             False  2020-10-21T06:20:34.549465
...
4    SNeIa  2020-11-15T09:33:18.151551  177  Type Ia Supernovae            False  2020-11-15T09:33:18.151551
3

Download sources for a group

# Download all sources in the "SNeIa" group (may be slow for large groups)
faccess.load_samples("SNeIa")

# Or load multiple groups at once
faccess.load_samples(["infant", "SNeIa"])
4

Access source metadata for a group

source_df = faccess.get_sample("SNeIa").data
print(source_df.keys())
Index(['id', 'origin', 'dist_nearest_source', 'ra_dis', 'internal_key',
       'mag_nearest_source', 'dec_dis', 'detect_photometry_count',
       'e_mag_nearest_source', 'ra_err', 'created_at', 'transient', 'dec_err',
       'modified', 'varstar', 'offset', 'ra', 'is_roid', 'redshift', 'dec',
       'score', 'redshift_history', 'altdata', 'thumbnails', 'comments',
       'classifications', 'annotations', 'last_detected', 'gal_lon', 'gal_lat',
       'luminosity_distance', 'dm', 'angular_diameter_distance', 'groups'],
      dtype='object')
5

Fast reload from local storage

Downloading sources can be slow for large groups. Once you have fetched them, every subsequent session can reload from disk:
faccess = fritz.FritzAccess.load_local()
Local files are stored at $ZTFDATA/fritz/{groupname}_sources.csv. You can still force an update at any time with faccess.load_samples(groupname), which overwrites the cached file.
6

Get an IRSA metadata query for a source

get_target_metaquery(name) produces a keyword-argument dictionary that can be passed directly to ZTFQuery.load_metadata() to download IRSA images for a Fritz source:
from ztfquery import query

# Build the query dict for a named source (e.g. in the SNeIa group)
meta_query = faccess.get_target_metaquery("ZTF20acmzoxo")

# Feed it straight into ZTFQuery
zquery = query.ZTFQuery()
zquery.load_metadata(**meta_query)
zquery.download_data("sciimg.fits")
The query dict contains radec, size, and a sql_query built from the source’s creation date and last detection date (with ±100 day buffers by default).

Per-source FritzSource methods

Access a single source via source = faccess.get_sample("SNeIa").get_source("ZTF20acmzoxo"):source.get_classification() — spectral classificationsource.get_coordinates() — RA/Dec positionsource.get_redshift() — redshift valuesource.get_metaquery() — IRSA query dict

Bulk downloading

Use fritz.bulk_download(fobject, names) with nprocess=4 for multiprocessed batch downloads of light curves, spectra, or alerts across many targets at once. Pass a Dask client for cluster-scale parallelism.

Build docs developers (and LLMs) love