Skip to main content

ztforce logo

ztforce

Forced PSF photometry on ZTF science images — measures flux at a fixed sky position in every available epoch, even below the detection threshold, producing a calibrated AB-magnitude lightcurve.

Template

PyPI GitHub Workflow Status Codecov Read The Docs DOI

Installation

pip install ztforce

Python 3.10–3.13 is supported.

Credentials

ztforce downloads ZTF science images from IRSA and requires an IRSA account (free at irsa.ipac.caltech.edu). Set your credentials in one of three ways:

Environment variables (recommended for scripts/CI):

export ZTFORCE_IRSA_USER=your_username
export ZTFORCE_IRSA_PASS=your_password

Config file at ~/.ztforce/config.toml:

[credentials]
irsa_user = "your_username"
irsa_pass = "your_password"

Direct argument:

from ztforce import build_config
config = build_config(irsa_user="your_username", irsa_pass="your_password")

Quick start

from ztforce import run_forced_photometry

# Measure flux at a fixed position across all ZTF g- and r-band epochs.
# A tqdm progress bar tracks downloads and PSF fitting; results are cached
# on disk so repeated calls return instantly.
lcs = run_forced_photometry(ra=210.08, dec=-6.88, bands=["g", "r"])

lcs["g"].df              # pandas DataFrame of all epochs
lcs["g"].stack()         # inverse-variance weighted stack of all good epochs
lcs["g"].save("my_source_g.ecsv")   # save to ECSV

Batch processing

from astropy.coordinates import SkyCoord
from ztforce import run_forced_photometry_batch

targets = SkyCoord(ra=[210.08, 130.13], dec=[-6.88, 19.70], unit="deg")

# Processes targets in parallel; downloads are shared across all workers.
results = run_forced_photometry_batch(targets, bands=["g", "r"], n_workers=4)

results[0]["g"].stack()  # stacked photometry for first target, g-band

Quality cuts, stacking, and uncertainties

Epochs failing the ZFPS quality cuts (bad calibration, noisy image, seeing > 4″) are flagged and never counted as detections or stacked. Stacks follow the ZFPS recipe: all good epochs, rescaled to a common zero point, inverse-variance averaged, and reported as a 5σ upper limit below S/N 3.

Uncertainties are statistical only and so underestimated, especially for bright sources (calibration/PSF systematics) and sources on extended hosts (the fit is on science images, not difference images).

Several official ZTF services offer complementary photometry — ztforce fills a gap none of them cover:

Service What it does Why you'd use ztforce instead
ZTF Forced Photometry Service (ZFPS) (Masci et al. 2023) Forced PSF photometry on ZTF difference images at user positions Science-image photometry avoids subtraction artifacts; no account/queue required; runs locally
ZTF DR lightcurves (IRSA) Catalog lightcurves for sources detected in ZTF data releases Forced photometry works for transients and sub-threshold sources not in any catalog and at any arbitrary position
ZuberCal Ubercalibrated PSF photometry catalog for PS1-matched ZTF sources Only covers sources detected in PS1; ztforce works at any arbitrary position

ztforce is designed for cases where the source may not appear in any existing catalog — supernovae, kilonova, flares, or any transient — and you need calibrated flux measurements at a fixed sky position across every available epoch, including non-detections.

Citation

If you find ztforce useful for your work, please cite the Zenodo release:

@software{Boesky2026_ztforce,
  author       = {Adam Boesky},
  title        = {Adam-Boesky/ztforce: v0.1.2},
  month        = may,
  year         = 2026,
  publisher    = {Zenodo},
  version      = {v0.1.2},
  doi          = {10.5281/zenodo.20434975},
  url          = {https://doi.org/10.5281/zenodo.20434975},
}

Dev Guide - Getting Started

Before installing any dependencies or writing code, it's a great idea to create a virtual environment. LINCC-Frameworks engineers primarily use conda to manage virtual environments. If you have conda installed locally, you can run the following to create and activate a new environment.

>> conda create -n <env_name> python=3.11
>> conda activate <env_name>

Once you have created a new environment, you can install this project for local development using the following commands:

>> ./.setup_dev.sh
>> conda install pandoc

Notes:

  1. ./.setup_dev.sh will initialize pre-commit for this local repository, so that a set of tests will be run prior to completing a local commit. For more information, see the Python Project Template documentation on pre-commit
  2. Install pandoc allows you to verify that automatic rendering of Jupyter notebooks into documentation for ReadTheDocs works as expected. For more information, see the Python Project Template documentation on Sphinx and Python Notebooks

Metadata

Release files for ztforce 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ztforce 0.3.0
File Size Uploaded
ztforce-0.3.0.tar.gz 95.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ztforce 0.3.0
File Interpreter ABI Platform
ztforce-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 123.0 kB

Release files / ztforce-0.3.0.tar.gz

Download URL ztforce-0.3.0.tar.gz
Size 95.4 kB
Tags Source
SHA-256 checksum
How to use checksums
f50e44044cce63f17e845a03b91923e5fcf039d05ec0d496a2f43c37f6e562cf
BLAKE2b-256 checksum
How to use checksums
8591c781b1799a6f978fd5a7b0a527674c0eb073b7e6e5f673efe777b0011cea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.

Transparency log

Release files / ztforce-0.3.0-py3-none-any.whl

Download URL ztforce-0.3.0-py3-none-any.whl
Size 27.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9641ab023155dc0e0920c1631204fd36a7bb39ff9d9b5bf1b5dea573921d4306
BLAKE2b-256 checksum
How to use checksums
1ef5aaeafec6ab19b79ff5bc2be1388885af08250198c8f3f3d84cd55bdf0ca9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.0

2 release files

This release

0.3.0 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page