Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 47 additions & 2 deletions config/calibration/mask_v1.X.6_ppv1.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Config file for masking and calibration.
# Standard cuts without halo masks, type v1.X.6.
# Joint ShapePipe + PhotoPipe catalogue.
# SP: Standard cuts without halo masks, type v1.X.6.
# PP" Standard selection.

# General parameters (can also given on command line)
params:
input_path: unions_shapepipe_comprehensive_struc_2024_v1.X.c.hdf5
input_path: unions_shapepipe_comprehensive_struc_ugriz_2024_v1.X.c.hdf5
cmatrices: False
sky_regions: False
verbose: True
Expand Down Expand Up @@ -99,12 +101,44 @@ dat:
kind: equal
value: False

# u-band footprint
- col_name: MASK_16_u
label: "u-band imaging"
kind: equal
value: False

# g-band footprint
- col_name: MASK_32_g
label: "g-band imaging"
kind: equal
value: False

# r-band footprint
- col_name: MASK_64_r
label: "r-band imaging"
kind: equal
value: False

# i-band footprint
- col_name: MASK_128_i
label: "i-band imaging"
kind: equal
value: False

# z-band footprint, both z surveys: 256_z is WISHES (Subaru HSC), 2048_z2 is
# Pan-STARRS (the deeper data, not the shallow all-sky survey). Told apart by
# depth: median MAG_LIM_z = 25.54 vs MAG_LIM_z2 = 24.88.
# Each bit is only required where its own band has a magnitude: asking for
# both at once keeps only the overlap of the two surveys, which costs ~85% of
# the sample. Pairs with the MAG_GAAP_0p7_z / _z2 two-band cut in `dat`.
- col_name: MASK_256_z
col_name2: MASK_2048_z2
mag_col: MAG_GAAP_0p7_z
mag_col2: MAG_GAAP_0p7_z2
label: "z-band imaging"
kind: covered_2bands

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MASK_256_z is in SPATIAL_CUTS in scripts/masking.py, so with footprint_only=True this cut gets sent to apply_condition(), which only handles single-column cuts. The result is ValueError: Unknown mask condition kind: 'covered_2bands'.

It's worth deciding what footprint-only should mean for this cut. One option reproduces the catalogue selection, magnitude checks included. The other is purely geometric: the union of the two imaging footprints, with bad = bad_z & bad_z2. demo_create_footprint_mask.py has the same gap, since it ignores col_name2.

value: -99

# Maximask
- col_name: MASK_1024_Maximask
label: "maximask"
Expand Down Expand Up @@ -135,3 +169,14 @@ metacal:

# Weight for global response matrix, None for unweighted mean
global_R_weight: w

# Binned footprint mask
binned_mask:
# Resolution
nside: 8192

# Mask value for "good" (observed) area
good: False

# Output file path base
output_base: "footprint_binned"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this section present, calibrate_comprehensive_cat.py reads cbm["output_path"] (line 170), so it'll KeyError before writing anything. output_base is what create_binned_mask_comprehensive.py reads, so keeping both is the smallest fix:

Suggested change
output_base: "footprint_binned"
output_base: "footprint_binned"
output_path: "footprint_binned_8192.fits"

14 changes: 13 additions & 1 deletion scripts/calibration/calibrate_comprehensive_cat.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,21 @@
"FLUX_RADIUS",
"MAGERR_AUTO",
"NGMIX_T_NOSHEAR",
"NGMIX_T_PSF_RECONV_NOSHEAR",
"NGMIX_Tpsf_NOSHEAR",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

read_cat() already maps v1 catalogues onto the canonical names (through grammar), and it hides NGMIX_Tpsf_NOSHEAR in the process. So this lookup raises KeyError even on v1.6 inputs. The canonical column also carries the adapter's NGMIX_Tpsf_1P correction, so it's the one we want anyway:

Suggested change
"NGMIX_Tpsf_NOSHEAR",
"NGMIX_T_PSF_RECONV_NOSHEAR",

(The first_present() fallback in fill_cat_gal() then isn't needed for this.)

"fwhm_PSF",
]

# PhotoPipe photo-z and multi-band photometry, when fill_photoz_bands.py has
# put them in the input. Selected against what the input actually holds, for
# two reasons: no catalogue carries every key (v1.6.c.3 has no Z_ML), and the
# image-simulation runs share this script with none of these columns at all.
photoz_cols = [key for key in cat.PHOTOZ_KEYS if key in set(dat.dtype.names or ())]
if photoz_cols:
print(f"Copying {len(photoz_cols)} PhotoPipe columns to the output catalogue")
else:
print("No PhotoPipe columns found in the input; none copied")
add_cols = add_cols + photoz_cols

add_cols_data = {}
for key in add_cols:
add_cols_data[key] = cat.get_col(dat, key, mask_combined._mask, mask_metacal)
Expand Down
48 changes: 27 additions & 21 deletions scripts/calibration/demo_apply_hsp_masks.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@

# +
import os
import re
import tracemalloc

from sp_validation import catalog_builders as sp_joint
Expand All @@ -39,41 +38,48 @@
obj = sp_joint.ApplyHspMasks()


# Bits set for non-tomographic catalogues
bit_list = [1, 2, 4, 8, 64, 1024]

# +
# Set parameters
base = "unions_shapepipe_comprehensive"

# Major version
ver_maj = "v1.6"

# Mask release, subdirectory of the mask directory
mask_release = "dr6-2026-08"

year = 2022 if ver_maj == "v1.3" else 2024

# $HOME/masks is a link to the shared UNIONS mask directory
mask_base = f"{os.environ['HOME']}/masks"

if ver_maj in ("v1.5", "v1.6"):
# Multi-band (tomographic)
bit_list = [1, 2, 4, 8, 16, 32, 64, 128, 256, 1024, 2048]
obj._params["mask_dir"] = f"{mask_base}/{mask_release}"
obj._params["file_base"] = "mask_ugriz_"
else:
# r-band (non-tomographic)
bit_list = [1, 2, 4, 8, 64, 1024]
obj._params["mask_dir"] = mask_base
obj._params["file_base"] = "mask_r_"

# combine bit list with & operator
# equivalent to bits = sum(bit_list)
# if elements in bit_list are of type 2^n

bits = 0
for b in bit_list:
bits = bits | b
print(bits)

# +
# Set parameters
base = "unions_shapepipe_comprehensive"
ver = "v1.3.c"

if ver == "v1.3.c":
year = 2022
else:
year = 2024
ver_maj = "v1.5"

obj._params["input_path"] = f"{base}_{year}_{ver_maj}.c.hdf5"
obj._params["output_path"] = f"{base}_struc_{year}_{ver_maj}.c.hdf5"
obj._params["mask_dir"] = f"{os.environ['HOME']}/{ver_maj}.x/masks"

obj._params["nside"] = 131072
obj._params["file_base"] = "mask_r_"
obj._params["bits"] = bits

obj._params["aux_mask_files"] = f"{obj._params['mask_dir']}/coverage_{ver_maj}.x.hsp"
ver_x = re.sub(r"c$", "x", ver)
obj._params["aux_mask_files"] = f"{obj._params['mask_dir']}/coverage_{ver_x}.hsp"
# Coverage map is in the mask base directory, not in the mask release one
obj._params["aux_mask_files"] = f"{mask_base}/coverage_{ver_maj}.x.hsp"
obj._params["aux_mask_labels"] = "npoint3"
obj._params["verbose"] = True
# -
Expand Down
2 changes: 1 addition & 1 deletion scripts/examples/create_binned_mask_comprehensive.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

# %%
# Read configuration file and set parameters
config = obj.read_config_set_params("config_for_compr_mask.yaml")
config = obj.read_config_set_params("config_mask.yaml")

# %%
# Get data. Set load_into_memory to False for very large files
Expand Down
89 changes: 8 additions & 81 deletions scripts/fill_photoz_bands.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
from cs_util import args as cs_args
from cs_util import logging

import sp_validation.catalog as sp_cat

FITS_HDU = 1
EMPTY_VALUE = -199
COPY_CHUNK = 2_000_000 # rows per chunk when copying input → output
Expand All @@ -59,86 +61,9 @@
("X_WORLD", "Y_WORLD"),
]

REQUESTED_KEYS = [
"Z_B",
"Z_B_MIN",
"Z_B_MAX",
"T_B",
"Z_ML",
"MAG_GAAP_u",
"MAGERR_GAAP_u",
"MAG_GAAP_0p7_u",
"MAGERR_GAAP_0p7_u",
"MAG_GAAP_1p0_u",
"MAGERR_GAAP_1p0_u",
"FLAG_GAAP_u",
"MAG_LIM_u",
"FLUX_GAAP_u",
"FLUXERR_GAAP_u",
"EXTINCTION_u",
"MAG_GAAP_g",
"MAGERR_GAAP_g",
"MAG_GAAP_0p7_g",
"MAGERR_GAAP_0p7_g",
"MAG_GAAP_1p0_g",
"MAGERR_GAAP_1p0_g",
"FLAG_GAAP_g",
"MAG_LIM_g",
"FLUX_GAAP_g",
"FLUXERR_GAAP_g",
"EXTINCTION_g",
"MAG_GAAP_r",
"MAGERR_GAAP_r",
"MAG_GAAP_0p7_r",
"MAGERR_GAAP_0p7_r",
"MAG_GAAP_1p0_r",
"MAGERR_GAAP_1p0_r",
"FLAG_GAAP_r",
"MAG_LIM_r",
"FLUX_GAAP_r",
"FLUXERR_GAAP_r",
"EXTINCTION_r",
"MAG_GAAP_i",
"MAGERR_GAAP_i",
"MAG_GAAP_0p7_i",
"MAGERR_GAAP_0p7_i",
"MAG_GAAP_1p0_i",
"MAGERR_GAAP_1p0_i",
"FLAG_GAAP_i",
"MAG_LIM_i",
"FLUX_GAAP_i",
"FLUXERR_GAAP_i",
"EXTINCTION_i",
"MAG_GAAP_z",
"MAGERR_GAAP_z",
"MAG_GAAP_0p7_z",
"MAGERR_GAAP_0p7_z",
"MAG_GAAP_1p0_z",
"MAGERR_GAAP_1p0_z",
"FLAG_GAAP_z",
"MAG_LIM_z",
"FLUX_GAAP_z",
"FLUXERR_GAAP_z",
"EXTINCTION_z",
"MAG_GAAP_z2",
"MAGERR_GAAP_z2",
"MAG_GAAP_0p7_z2",
"MAGERR_GAAP_0p7_z2",
"MAG_GAAP_1p0_z2",
"MAGERR_GAAP_1p0_z2",
"FLAG_GAAP_z2",
"MAG_LIM_z2",
"FLUX_GAAP_z2",
"FLUXERR_GAAP_z2",
"EXTINCTION_z2",
"EXTINCTION",
"ODDS",
"CHI_SQUARED_BPZ",
"M_0",
"BPZ_FILT",
"BPZ_NONDETFILT",
"BPZ_FLAGFILT",
]
# The one list, shared with the calibration script so the two cannot
# drift (see sp_validation.catalog.PHOTOZ_KEYS).
REQUESTED_KEYS = sp_cat.PHOTOZ_KEYS


def params_default():
Expand Down Expand Up @@ -681,7 +606,9 @@ def main(argv=None):
) as pbar:
for start in range(0, n_total, SCAN_CHUNK):
end = min(start + SCAN_CHUNK, n_total)
tile_chunk = dset[start:end]["TILE_ID"]
# .fields() reads only TILE_ID; dset[start:end]["TILE_ID"]
# would materialise all columns first (~3 GB per chunk)
tile_chunk = dset.fields("TILE_ID")[start:end]
for local_i, tid in enumerate(tile_chunk):
tile_index_map_lists[tid].append(start + local_i)
pbar.update(end - start)
Expand Down
30 changes: 28 additions & 2 deletions src/sp_validation/calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,13 @@ def fill_cat_gal(cat_gal, dat, g_uncorr, gal_metacal, mask1, mask2, purpose="wei
cat_gal["R_g22"] = gal_metacal.R22

cat_gal["NGMIX_T_NOSHEAR"] = sp_cat.get_col(dat, "NGMIX_T_NOSHEAR", mask1, mask2)
# v1.6 writes NGMIX_Tpsf_NOSHEAR, ShapePipe v2 NGMIX_T_PSF_RECONV_NOSHEAR;
# the output column keeps one name either way.
cat_gal["NGMIX_T_PSF_RECONV_NOSHEAR"] = sp_cat.get_col(
dat, "NGMIX_T_PSF_RECONV_NOSHEAR", mask1, mask2
dat,
first_present(dat, "NGMIX_T_PSF_RECONV_NOSHEAR", "NGMIX_Tpsf_NOSHEAR"),
mask1,
mask2,
)
cat_gal["size_ratio"] = (
cat_gal["NGMIX_T_NOSHEAR"] / cat_gal["NGMIX_T_PSF_RECONV_NOSHEAR"]
Expand Down Expand Up @@ -690,6 +695,27 @@ def get_calibrate_no_leakage_e_from_cat(path_cat_gal, weight_type="des", verbose
return e1_noleak, e2_noleak


def first_present(data, *candidates):
"""Return the first of `candidates` present in `data`.

ngmix columns come in two grammars: v1.6 and earlier catalogues use
NGMIX_ELL_<shear>_<comp> and NGMIX_Tpsf_<shear>, ShapePipe v2 writes
NGMIX_G<n>_<shear> and NGMIX_T_PSF_RECONV_<shear>.
"""
names = getattr(getattr(data, "dtype", None), "names", None)
if names is None:
names = getattr(data, "colnames", None)
if names is None:
names = list(data.keys())
for candidate in candidates:
if candidate in names:
return candidate
raise KeyError(
f"none of {list(candidates)} in the catalogue; it has neither ngmix"
f" column grammar"
)


class metacal:
"""Metacal.

Expand Down Expand Up @@ -804,7 +830,7 @@ def _read_data_ngmix(self, masked_data, m1, p1, m2, p2, ns):

dict_tmp["flag"] = masked_data[f"NGMIX_FLAGS_{name_shear}"]

# Ellipticity in named scalar components (ShapePipe-v2 grammar)
# Either ngmix grammar (see first_present)
for comp in (0, 1):
dict_tmp[f"g{comp + 1}"] = masked_data[
f"NGMIX_G{comp + 1}_{name_shear}"
Expand Down
Loading
Loading