diff --git a/config/calibration/mask_v1.X.12.yaml b/config/calibration/mask_v1.X.12.yaml new file mode 100644 index 00000000..39679dc7 --- /dev/null +++ b/config/calibration/mask_v1.X.12.yaml @@ -0,0 +1,113 @@ +# Config file for masking and calibration. +# Standard cuts without halo masks, type v1.X.12. + +# General parameters (can also given on command line) +params: + input_path: unions_shapepipe_comprehensive_struc_2024_v1.X.c.hdf5 + cmatrices: False + sky_regions: False + verbose: True + +# Masks +## Using columns in 'dat' group (ShapePipe flags) +dat: + # SExtractor flags + - col_name: FLAGS + label: SE FLAGS + kind: equal + value: 0 + + # Duplicate objects + - col_name: overlap + label: tile overlap + kind: equal + value: True + + # ShapePipe flags + - col_name: IMAFLAGS_ISO + label: SP mask + kind: equal + value: 0 + + # Number of epochs + - col_name: N_EPOCH + label: r"$n_{\rm epoch}$" + kind: greater_equal + value: 2 + + # Magnitude range + - col_name: mag + label: r + kind: range + value: [15, 30] + + # ngmix flags + - col_name: NGMIX_MOM_FAIL + label: "ngmix moments failure" + kind: equal + value: 0 + + # invalid PSF ellipticities + - col_name: NGMIX_ELL_PSFo_NOSHEAR_0 + label: "bad PSF ellipticity comp 1" + kind: not_equal + value: -10 + - col_name: NGMIX_ELL_PSFo_NOSHEAR_1 + label: "bad PSF ellipticity comp 2" + kind: not_equal + value: -10 + +## Using columns in 'dat_ext' group (post-processing flags) +dat_ext: + + # Stars + - col_name: 4_Stars + label: "Stars" + kind: equal + value: False + + # Manual mask + - col_name: 8_Manual + label: "manual mask" + kind: equal + value: False + + # r-band footprint + - col_name: 64_r + label: "r-band imaging" + kind: equal + value: False + + # Maximask + - col_name: 1024_Maximask + label: "maximask" + kind: equal + value: False + + # Rough pointing coverage + - col_name: npoint3 + label: r"$n_{\rm pointing}$" + kind: greater_equal + value: 3 + +# Metacal parameters +metacal: + # Ellipticity dispersion + sigma_eps_prior: 0.34 + + # Signal-to-noise range + gal_snr_min: 10 + gal_snr_max: 500 + + # Relative-size (hlr / hlr_psf) range + gal_rel_size_min: 0.707 + gal_rel_size_max: 3 + + # Ellipticity cut + eps_max: 0.7 + + # Correct relative size for ellipticity? + gal_size_corr_ell: False + + # Weight for global response matrix, None for unweighted mean + global_R_weight: w diff --git a/config/calibration/mask_v1.X.13.yaml b/config/calibration/mask_v1.X.13.yaml new file mode 100644 index 00000000..179075cf --- /dev/null +++ b/config/calibration/mask_v1.X.13.yaml @@ -0,0 +1,113 @@ +# Config file for masking and calibration. +# Standard cuts without halo masks, type v1.X.13. + +# General parameters (can also given on command line) +params: + input_path: unions_shapepipe_comprehensive_struc_2024_v1.X.c.hdf5 + cmatrices: False + sky_regions: False + verbose: True + +# Masks +## Using columns in 'dat' group (ShapePipe flags) +dat: + # SExtractor flags + - col_name: FLAGS + label: SE FLAGS + kind: smaller_equal + value: 3 + + # Duplicate objects + - col_name: overlap + label: tile overlap + kind: equal + value: True + + # ShapePipe flags + - col_name: IMAFLAGS_ISO + label: SP mask + kind: equal + value: 0 + + # Number of epochs + - col_name: N_EPOCH + label: r"$n_{\rm epoch}$" + kind: greater_equal + value: 2 + + # Magnitude range + - col_name: mag + label: r + kind: range + value: [15, 30] + + # ngmix flags + - col_name: NGMIX_MOM_FAIL + label: "ngmix moments failure" + kind: equal + value: 0 + + # invalid PSF ellipticities + - col_name: NGMIX_ELL_PSFo_NOSHEAR_0 + label: "bad PSF ellipticity comp 1" + kind: not_equal + value: -10 + - col_name: NGMIX_ELL_PSFo_NOSHEAR_1 + label: "bad PSF ellipticity comp 2" + kind: not_equal + value: -10 + +## Using columns in 'dat_ext' group (post-processing flags) +dat_ext: + + # Stars + - col_name: 4_Stars + label: "Stars" + kind: equal + value: False + + # Manual mask + - col_name: 8_Manual + label: "manual mask" + kind: equal + value: False + + # r-band footprint + - col_name: 64_r + label: "r-band imaging" + kind: equal + value: False + + # Maximask + - col_name: 1024_Maximask + label: "maximask" + kind: equal + value: False + + # Rough pointing coverage + - col_name: npoint3 + label: r"$n_{\rm pointing}$" + kind: greater_equal + value: 3 + +# Metacal parameters +metacal: + # Ellipticity dispersion + sigma_eps_prior: 0.34 + + # Signal-to-noise range + gal_snr_min: 10 + gal_snr_max: 500 + + # Relative-size (hlr / hlr_psf) range + gal_rel_size_min: 0.707 + gal_rel_size_max: 3 + + # Ellipticity cut + eps_max: 0.7 + + # Correct relative size for ellipticity? + gal_size_corr_ell: False + + # Weight for global response matrix, None for unweighted mean + global_R_weight: w diff --git a/scripts/calibration/calibrate_comprehensive_cat.py b/scripts/calibration/calibrate_comprehensive_cat.py index c5248c3e..f8463d92 100644 --- a/scripts/calibration/calibrate_comprehensive_cat.py +++ b/scripts/calibration/calibrate_comprehensive_cat.py @@ -80,6 +80,9 @@ # Call metacal cm = config["metacal"] +# Cut on ellipticity +eps_max = cm.get("eps_max", None) + # %% gal_metacal = metacal( dat, @@ -89,6 +92,7 @@ rel_size_min=cm["gal_rel_size_min"], rel_size_max=cm["gal_rel_size_max"], size_corr_ell=cm["gal_size_corr_ell"], + eps_max=eps_max, sigma_eps=cm["sigma_eps_prior"], global_R_weight=cm["global_R_weight"], verbose=True, diff --git a/scripts/calibration/demo_apply_hsp_masks.py b/scripts/calibration/demo_apply_hsp_masks.py index e47c4d47..2a9fb901 100644 --- a/scripts/calibration/demo_apply_hsp_masks.py +++ b/scripts/calibration/demo_apply_hsp_masks.py @@ -55,13 +55,13 @@ # + # Set parameters base = "unions_shapepipe_comprehensive" -ver = "v1.3.c" +ver = "v1.6.c" if ver == "v1.3.c": year = 2022 else: year = 2024 -ver_maj = "v1.5" +ver_maj = "v1.6" obj._params["input_path"] = f"{base}_{year}_{ver_maj}.c.hdf5" obj._params["output_path"] = f"{base}_struc_{year}_{ver_maj}.c.hdf5" diff --git a/scripts/print_matrix_from_fits.py b/scripts/print_matrix_from_fits.py index d3b96ce0..8d8cbd4b 100755 --- a/scripts/print_matrix_from_fits.py +++ b/scripts/print_matrix_from_fits.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -"""Read matrix entries from FITS header and print in tex or pdf format.""" +"""Read matrix entries from FITS header and print in txt, tex, or pdf format.""" import os import subprocess @@ -64,6 +64,34 @@ def get_matrix_from_header(header, prefix): return matrix +def matrix_to_txt(matrix, prec): + """Convert matrix to ASCII format. + + Parameters + ---------- + matrix : numpy.ndarray + 2x2 matrix + prec : int + number of significant digits + + Returns + ------- + str + ASCII-formatted matrix string + + """ + col_widths = [] + for j in range(2): + col_widths.append(max(len(f"{matrix[i, j]:.{prec}g}") for i in range(2))) + + lines = [] + for i in range(2): + vals = [f"{matrix[i, j]:.{prec}g}".rjust(col_widths[j]) for j in range(2)] + lines.append("[ " + " ".join(vals) + " ]") + + return "\n".join(lines) + + def matrix_to_tex(matrix, prec, exp_thresh): """Convert matrix to LaTeX format.""" rows = [] @@ -160,7 +188,7 @@ def main(): help_strings = { "input": "Input FITS file", "prefix": "Prefix for matrix entries (default: {})", - "format": "Output format: tex or pdf (default: {})", + "format": "Output format: txt, tex or pdf (default: {})", "prec": "Number of significant digits (default: {})", "exp_thresh": "Exponent threshold for scientific notation (default: {})", "output": "Output file path (extension added based on format)", @@ -172,8 +200,8 @@ def main(): if options["input"] is None: raise ValueError("Input FITS file (-i) is required") - if options["format"] not in ["tex", "pdf"]: - raise ValueError("Format must be 'tex' or 'pdf'") + if options["format"] not in ["txt", "tex", "pdf"]: + raise ValueError("Format must be 'txt', 'tex', or 'pdf'") # Read FITS header with fits.open(options["input"]) as hdu: @@ -190,7 +218,14 @@ def main(): if options["output"]: output_path = f"{options['output']}.{options['format']}" - if options["format"] == "tex": + if options["format"] == "txt": + txt_content = matrix_to_txt(matrix, options["prec"]) + print(txt_content) + if output_path: + with open(output_path, "w") as f: + f.write(txt_content + "\n") + print(f"Written to {output_path}") + elif options["format"] == "tex": full_tex = ( r"""\documentclass[preview,border=2pt]{article} \usepackage{amsmath} diff --git a/src/sp_validation/calibration.py b/src/sp_validation/calibration.py index b594b9b6..8a0cd8dd 100644 --- a/src/sp_validation/calibration.py +++ b/src/sp_validation/calibration.py @@ -715,6 +715,8 @@ class metacal: relative size minimum rel_size_max : float, optional, default=3.0 relative size maximum + eps_max : float, optional + maximum ellipticity (absolute value); default is ``None`` (no cut) size_corr_ell : bool, optional, default=True global_R_weight : str, optional, weight column name for global response matrix; default is ``None`` @@ -737,6 +739,7 @@ def __init__( snr_max=500, rel_size_min=0.5, rel_size_max=3.0, + eps_max=None, size_corr_ell=True, global_R_weight=None, sigma_eps=0.34, @@ -751,12 +754,14 @@ def __init__( self._snr_max = snr_max self._rel_size_min = rel_size_min self._rel_size_max = rel_size_max + self._eps_max = eps_max self._size_corr_ell = size_corr_ell if verbose: print( f"Metacal cuts: {snr_min} self._rel_size_min) & (Tr_tmp / Tpsf < self._rel_size_max) & (snr_flux > self._snr_min) & (snr_flux < self._snr_max) + & mask_eps ) # Take care of rotated version