From c6f481360b8ac8752084235d2a204d664f0f75ae Mon Sep 17 00:00:00 2001 From: Alexandre Boucaud Date: Thu, 1 Oct 2026 01:19:05 +0200 Subject: [PATCH] feat: add Euclid NISP survey (Y, J, H photometric bands) Euclid carries two instruments: VIS (already in Euclid_VIS.yaml) and NISP (near-infrared spectrometer and photometer), whose photometric channel images in Y, J, H -- previously completely absent from surveycodex. speclite ships all three NISP filter curves (Euclid-Y, Euclid-J, Euclid-H), so zeropoint and effective_wavelength are computed with speclite exactly like Euclid_VIS's IE filter, and validated by reproducing the existing Euclid_VIS zeropoint (25.92) and effective_wavelength (750.64 nm) with the same formula before trusting it for the new filters. NISP shares Euclid's 1.2 m telescope with VIS (same mirror_diameter/ obscuration), but has its own pixel scale, gain, and per-band sky_brightness/psf_fwhm/full_exposure_time, sourced from: - Scaramella et al. 2022 (arXiv:2108.01201), the Euclid Wide Survey definition paper, for pixel_scale (0.3"/px) and full_exposure_time (112s per band -- the single-pointing exposure in the reference observing sequence, matching the per-dither convention already used for Euclid_VIS's full_exposure_time=565s, its sibling instrument in the same survey). - The Euclid ERO compact/diffuse-emission photometry pipeline paper (arXiv:2405.13496), Table 2 and Sect. 4.3.7, for gain (2 e-/ADU, in-flight measured), sky_brightness, and psf_fwhm (both median in-flight values measured on stacked ERO survey images, per band). Also generalises the Euclid_VIS-only "IE" -> "VIS" filter-name mapping in scripts/check_zeropoints.py and check_effective_wavelengths.py into an EUCLID_FILTER_NAMES dict covering NISP's YE/JE/HE -> Y/J/H too, and wires Euclid_NISP into SPECLITE_SURVEY_PREFIXES so both scripts (run in CI) validate it against speclite, same as Euclid_VIS. Co-Authored-By: Claude Sonnet 5 --- scripts/check_effective_wavelengths.py | 8 ++-- scripts/check_zeropoints.py | 8 ++-- surveycodex/data/Euclid_NISP.yaml | 60 ++++++++++++++++++++++++++ surveycodex/rich.py | 8 +++- 4 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 surveycodex/data/Euclid_NISP.yaml diff --git a/scripts/check_effective_wavelengths.py b/scripts/check_effective_wavelengths.py index 9ada30b..ec943a3 100644 --- a/scripts/check_effective_wavelengths.py +++ b/scripts/check_effective_wavelengths.py @@ -6,10 +6,13 @@ SPECLITE_SURVEY_PREFIXES = { "DES": "decam2014", "Euclid_VIS": "Euclid", + "Euclid_NISP": "Euclid", "HSC": "hsc2017", "LSST": "lsst2016", } +EUCLID_FILTER_NAMES = {"IE": "VIS", "YE": "Y", "JE": "J", "HE": "H"} + def check_effective_wavelengths(survey_name): """Compare current effective wavelengths with speclite @@ -29,10 +32,7 @@ def check_effective_wavelengths(survey_name): print("------- | --------- | ---------") for filter_name in survey.available_filters: - if filter_name == "IE": - old_filter_name = "VIS" - else: - old_filter_name = filter_name + old_filter_name = EUCLID_FILTER_NAMES.get(filter_name, filter_name) speclite_filter_name = f"{speclite_prefix}-{old_filter_name}" speclite_filter = load_filter(speclite_filter_name) speclite_eff_wl = speclite_filter.effective_wavelength.to(u.nm) diff --git a/scripts/check_zeropoints.py b/scripts/check_zeropoints.py index a31c4a0..51f3f16 100644 --- a/scripts/check_zeropoints.py +++ b/scripts/check_zeropoints.py @@ -8,10 +8,13 @@ SPECLITE_SURVEY_PREFIXES = { "DES": "decam2014", "Euclid_VIS": "Euclid", + "Euclid_NISP": "Euclid", "HSC": "hsc2017", "LSST": "lsst2016", } +EUCLID_FILTER_NAMES = {"IE": "VIS", "YE": "Y", "JE": "J", "HE": "H"} + def compute_zeropoint_mag(band_name, effective_area, exposure_time=1 * u.s): """Compute the zeropoint of a given filter with speclite""" @@ -42,10 +45,7 @@ def check_zeropoints(survey_name): print("------- | --------- | ---------") for filter_name in survey.available_filters: - if filter_name == "IE": - old_filter_name = "VIS" - else: - old_filter_name = filter_name + old_filter_name = EUCLID_FILTER_NAMES.get(filter_name, filter_name) speclite_filter_name = f"{speclite_prefix}-{old_filter_name}" speclite_zp = compute_zeropoint_mag( speclite_filter_name, survey.effective_area diff --git a/surveycodex/data/Euclid_NISP.yaml b/surveycodex/data/Euclid_NISP.yaml new file mode 100644 index 0000000..a9ed556 --- /dev/null +++ b/surveycodex/data/Euclid_NISP.yaml @@ -0,0 +1,60 @@ +name: "Euclid_NISP" +description: "Euclid wide-field survey done with the Euclid space telescope and the near-infrared spectrometer and photometer (NISP), photometric channel" +pixel_scale: 0.30 +gain: 2.0 +mirror_diameter: 1.2 +obscuration: 0.13 +zeropoint_airmass: 0.0 +filters: + YE: + name: "YE" + sky_brightness: 22.1 + full_exposure_time: 112 + zeropoint: 24.99 + psf_fwhm: 0.477 + effective_wavelength: 1089.014 + JE: + name: "JE" + sky_brightness: 22.2 + full_exposure_time: 112 + zeropoint: 25.17 + psf_fwhm: 0.486 + effective_wavelength: 1379.127 + HE: + name: "HE" + sky_brightness: 22.3 + full_exposure_time: 112 + zeropoint: 25.11 + psf_fwhm: 0.492 + effective_wavelength: 1785.975 +references: + pixel_scale: + link: "https://arxiv.org/abs/2108.01201" + comment: "Euclid preparation I. The Euclid Wide Survey (Scaramella et al. 2022), Sect. 3.2: NISP has a plate scale of 0.3 arcsec/pixel" + gain: + link: "https://arxiv.org/abs/2405.13496" + comment: "Euclid: ERO -- compact- and diffuse-emission photometry pipeline, Sect. 4.3.7: NISP's average gain is 2 electrons per ADU" + mirror_diameter: + link: "https://arxiv.org/abs/1608.08603" + comment: "(v1) See section 3.1 -- NISP shares the same 1.2 m Euclid telescope as VIS, split by a dichroic" + obscuration: + link: "https://arxiv.org/abs/1608.08603" + comment: "(v1) See section 3.1 -- same shared telescope as VIS" + zeropoint_airmass: + link: "" + comment: "Space telescope" + sky_brightness: + link: "https://arxiv.org/abs/2405.13496" + comment: "Euclid: ERO -- compact- and diffuse-emission photometry pipeline, Table 2: median in-flight sky background per band from the 17 ERO fields" + full_exposure_time: + link: "https://arxiv.org/abs/2108.01201" + comment: "Euclid preparation I. The Euclid Wide Survey (Scaramella et al. 2022), Sect. 4.1: each of the three NISP photometric images (Y, J, H) in the reference observing sequence lasts 112 s -- single-pointing exposure, matching the convention used for Euclid_VIS's full_exposure_time" + zeropoint: + link: "https://speclite.readthedocs.io/en/latest/filters.html" + comment: "computed with speclite – see scripts/check_zeropoints.py" + psf_fwhm: + link: "https://arxiv.org/abs/2405.13496" + comment: "Euclid: ERO -- compact- and diffuse-emission photometry pipeline, Table 2: median in-flight FWHM per band, measured on stacked ERO survey images" + effective_wavelength: + link: "https://speclite.readthedocs.io/en/latest/filters.html" + comment: "computed with speclite – see scripts/check_effective_wavelength.py" diff --git a/surveycodex/rich.py b/surveycodex/rich.py index 0f0d4dc..41795fd 100644 --- a/surveycodex/rich.py +++ b/surveycodex/rich.py @@ -7,7 +7,13 @@ def _rich_survey_name(survey): - if survey.name in ["Euclid_VIS", "COSMOS", "Roman_WFI", "Roman_WFI_Deep"]: + if survey.name in [ + "Euclid_VIS", + "Euclid_NISP", + "COSMOS", + "Roman_WFI", + "Roman_WFI_Deep", + ]: icon = _SATELLITE else: icon = _TELESCOPE