Skip to content

feat: add Pan-STARRS (PS1) survey - #138

Merged
aboucaud merged 3 commits into
mainfrom
add-panstarrs-survey
Oct 1, 2026
Merged

aboucaud merged 3 commits into
mainfrom
add-panstarrs-survey

Conversation

@aboucaud

Copy link
Copy Markdown
Member

Summary

Adds Pan-STARRS1 (PS1) as a new survey: surveycodex/data/PanSTARRS.yaml (filename/survey name confirmed with the maintainer — no hyphen, unlike the mission's "Pan-STARRS" branding). Telescope: the 1.8m PS1 telescope at Haleakala, Hawaii. Instrument: Gigapixel Camera #1 (GPC1). Filters: g, r, i, z, y, plus the wide w filter. zeropoint/effective_wavelength are computed with speclite's panstarrs filter group, which was confirmed to resolve for all 6 bands.

Also adds "PanSTARRS": "panstarrs" to SPECLITE_SURVEY_PREFIXES in scripts/check_zeropoints.py and scripts/check_effective_wavelengths.py.

Sourced values and citations

Field Value(s) Source
pixel_scale 0.258 arcsec/px Chambers et al. 2016 (arXiv:1612.05560), Section 2.4 / Table 3
mirror_diameter 1.8 m Chambers et al. 2016, Table 2 ("Primary mirror 1800 mm diameter")
obscuration 0.32078172 Derived from Chambers et al. 2016 Table 2, which quotes the effective aperture directly as 0.65 × π × (92.2 cm)² = 17284 cm² "including diffraction and obscuration"; obscuration = 1 − 17284 cm² / (π × 90 cm²) relative to the 1.8 m primary
gain 0.97 e⁻/ADU Tonry et al. 2012 (arXiv:1203.0297), Section 2.5 (p. 15): measured gain of the OTA34/cell33 amplifier used for standard-star calibration
zeropoint_airmass 1.2 Tonry et al. 2012, text preceding Table 4: PS1 natural-system zeropoints are explicitly defined as "the AB magnitude of a neutral color... star that would produce 1 e⁻/sec in the detector with 1.2 airmasses of extinction"
sky_brightness (g/r/i/z/y/w) 21.92 / 20.83 / 19.79 / 19.24 / 18.24 / 20.62 Tonry et al. 2012, Table 4, column µ_obs (observed sky brightness) — one consistent source covering all 6 filters, including w, which has no entry in Chambers et al. 2016's 3π-survey-only tables
full_exposure_time (g/r/i/z/y) 516 / 480 / 540 / 360 / 360 s Chambers et al. 2016 Table 11 nominal single-exposure time (43/40/45/30/30 s) × 12 dithered visits over the survey lifetime (Section 3.2.3: "Over 3.5 years this would give ... 12 exposures in each band")
full_exposure_time (w) 45 s Denneau et al. 2013 (arXiv:1302.7281), Table 1 ("Exposure times as of October 2012"). Chambers et al. 2016 Section 3.4 (Solar System Survey) is unpopulated in that paper and no stacked-visit design is documented for wP1, so the single nominal exposure is used rather than a guessed total
psf_fwhm (g/r/i/z/y) 1.47 / 1.31 / 1.19 / 1.14 / 1.09 arcsec Chambers et al. 2016 Table 11, median of the PSF FWHM distribution
psf_fwhm (w) 1.31 arcsec No wP1 row exists in Table 11; approximated with rP1's median FWHM since wP1's effective wavelength (608 nm, Tonry et al. 2012 Table 4) is closest to rP1 (617 nm) among the tabulated 3π filters, and no direct wP1 seeing measurement was found in the literature
zeropoint, effective_wavelength computed speclite's panstarrs-* filters

On zeropoint_airmass specifically

Unlike decam2014/sdss2010, speclite's panstarrs filters carry no airmass metadata (load_filter('panstarrs-r').meta.get('airmass') returns None). Rather than reuse another survey's airmass or guess, I went to the primary source defining the PS1 photometric system (Tonry et al. 2012) and found the reference airmass explicitly stated as 1.2 in the text describing Table 4's zeropoint definition. This is a real, citable value, not an assumption.

Methodology validation

Before trusting the compute_zeropoint_mag / speclite code path for PS1, I reproduced DES's already-shipped decam2014-g/r/i/z zeropoints and effective wavelengths using DES.yaml's own mirror_diameter/obscuration, and got an exact match (e.g. g: 26.72 mag / 489.004 nm) before applying the same method to panstarrs-*.

Test plan

  • pytest --cov — 36 passed
  • pre-commit run --all-files — all hooks pass (isort, black, flake8, pyupgrade, etc.)
  • python -m surveycodex — PanSTARRS prints correctly with all 6 filters
  • surveycodex --refs — references block prints correctly
  • python scripts/check_zeropoints.py — speclite vs surveycodex match exactly for all 6 filters (g/r/i/z/y/w)
  • python scripts/check_effective_wavelengths.py — speclite vs surveycodex match exactly for all 6 filters

🤖 Generated with Claude Code

@aboucaud

aboucaud commented Oct 1, 2026

Copy link
Copy Markdown
Member Author

Addressed code review findings:

  • Fixed a worked-example arithmetic error in the obscuration comment: it quoted the radius as "92.2 cm" but Chambers et al. 2016 Table 2 actually states "92 cm" (0.65×π×92² = 17284 cm², matching the paper's own stated area). The shipped obscuration value was already numerically correct since it used the paper's final area directly — only the comment's worked derivation was wrong.
  • Fixed zeropoint_airmass's section citation: "Section 2.6" → "Section 3" (Tonry et al. 2012) — Section 2.6 is an unrelated "Photometry Refinement" section; the quoted PS1 natural-system definition is in Section 3.
  • Narrowed the try/except ValueError added to scripts/check_zeropoints.py/check_effective_wavelengths.py so it only swallows speclite's "No such group" error (meaning the installed speclite version lacks the filter group entirely), re-raising anything else. Previously it would have also silently swallowed a genuine "No such filter in this group" error for any survey using this shared code — e.g. masking a future filter-name mapping bug instead of failing loudly.

All validation re-run and clean (pytest, pre-commit, all 6 filters match speclite exactly).

aboucaud and others added 3 commits October 1, 2026 02:10
Adds surveycodex/data/PanSTARRS.yaml for the Pan-STARRS1 (PS1) wide-field
survey (1.8m telescope, GPC1 camera, Haleakala), with g/r/i/z/y/w filters.

Sourcing highlights:
- pixel_scale, mirror_diameter, obscuration: Chambers et al. 2016
  (arXiv:1612.05560), Table 2. Obscuration derived from the paper's quoted
  effective aperture (0.65 x pi x 92.2cm^2 = 17284 cm^2) relative to the
  1.8m primary mirror.
- gain: Tonry et al. 2012 (arXiv:1203.0297), Section 2.5, measured
  0.97 e-/ADU for the calibration amplifier.
- zeropoint_airmass: 1.2, explicitly stated in Tonry et al. 2012 as the
  reference airmass for the PS1 natural-system zeropoints (speclite's
  panstarrs filters carry no airmass metadata, unlike decam2014/sdss2010).
- sky_brightness: Tonry et al. 2012, Table 4 (mu_obs), a single source
  covering all 6 filters including w.
- full_exposure_time: Chambers et al. 2016 Table 11 nominal exposure x 12
  dithered visits (Section 3.2.3) for g/r/i/z/y; w uses the single nominal
  exposure from Denneau et al. 2013 (arXiv:1302.7281) since the Solar
  System Survey has no documented stacked-visit design for wP1.
- psf_fwhm: Chambers et al. 2016 Table 11 median FWHM for g/r/i/z/y; w
  approximated from rP1 (closest effective wavelength) since Table 11 has
  no wP1 row.
- zeropoint / effective_wavelength: computed with speclite (panstarrs
  filter group), validated to reproduce DES's shipped values exactly
  before trusting the same code path for PS1.

Also adds "PanSTARRS": "panstarrs" to SPECLITE_SURVEY_PREFIXES in
scripts/check_zeropoints.py and scripts/check_effective_wavelengths.py;
both scripts now match speclite exactly for all 6 filters.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The panstarrs filter group was only added in speclite 1.0.0, which
requires Python >=3.10. CI's Python 3.7/3.8/3.9 jobs install speclite
0.20 (the latest release compatible with those interpreters), which
does not ship the panstarrs group, causing check_zeropoints.py and
check_effective_wavelengths.py to crash with a ValueError instead of
printing the usual "not available" message.

Both scripts now catch that ValueError and print an informative
message instead of crashing, without changing behavior for any survey
whose filter group is present in the installed speclite version.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- surveycodex/data/PanSTARRS.yaml: fix two reference-comment inaccuracies
  caught by code review. The obscuration derivation quoted "92.2 cm" but
  Chambers et al. 2016 Table 2 actually states the radius as "92 cm"
  (0.65 x pi x 92^2 = 17284 cm^2, matching the paper's own stated area;
  the shipped obscuration value was already numerically correct since it
  used the paper's final area directly, only the worked-example text was
  wrong). The zeropoint_airmass comment cited "Section 2.6" but the quoted
  PS1 natural-system definition is actually in Section 3 of Tonry et al.
  2012 (Section 2.6 is an unrelated "Photometry Refinement" section).

- scripts/check_zeropoints.py, scripts/check_effective_wavelengths.py:
  narrow the try/except ValueError added for PanSTARRS so it only swallows
  speclite's "No such group" error (meaning this speclite version lacks the
  filter group entirely, e.g. panstarrs on speclite<1.0.0/Python<3.10) and
  re-raises anything else. Previously any ValueError from load_filter was
  silently treated as "filter group unavailable," which would also swallow
  a genuine "No such filter in this group" error -- e.g. a future survey's
  filter-name mapping bug -- and misreport it as a speclite-version issue
  for every survey using this shared validation code, not just PanSTARRS.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@aboucaud
aboucaud force-pushed the add-panstarrs-survey branch from fa3f31f to 429e20c Compare October 1, 2026 00:10
@aboucaud
aboucaud merged commit 0d52370 into main Oct 1, 2026
7 checks passed
@aboucaud
aboucaud deleted the add-panstarrs-survey branch October 1, 2026 00:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant