Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
5224e31
ngmix: record silent metacal failures in mcal_flags; fail loudly at 100%
cailmdaley Jul 17, 2026
94bbb60
ngmix: log instead of raising on 0-fitted (don't crash a campaign on …
cailmdaley Sep 25, 2026
146eacd
make_cat: never-fit objects get FLAG_NO_RESULT, not MCAL_FLAGS == 0
cailmdaley Sep 25, 2026
7c1056c
ngmix: extract log_run_health for direct unit testing
cailmdaley Sep 25, 2026
ec1b30e
tests: cover FLAG_NO_RESULT absence handling and 0-fitted logging
cailmdaley Sep 25, 2026
6b2183c
ngmix: derive every metacal flag column from one per-type flag
cailmdaley Sep 25, 2026
ab7d739
ngmix, make_cat: @sc contracts for the mcal flag invariant
cailmdaley Sep 25, 2026
fff6d85
tests: consumer-side invariant for the mcal flag columns; prune resta…
cailmdaley Sep 26, 2026
9b078dc
tests: an empty tile survives Ngmix.process (run-health-logs-not-raises)
cailmdaley Sep 26, 2026
f4b2ada
ngmix: 0-fitted log names the expected cause (an empty tile) first
cailmdaley Sep 26, 2026
6ad8010
ngmix: fail fast on a wcs-centroid tile with no propagated OFFSET
cailmdaley Sep 26, 2026
6272edc
ngmix, ngmix_runner: a truly empty tile writes the empty catalogue too
cailmdaley Sep 26, 2026
58a6569
tests: close the g2-only and disconnected-flagged-counter coverage gaps
cailmdaley Sep 26, 2026
1f9265b
ngmix_runner: restore Martin's PSF-then-image all-empty guards
cailmdaley Sep 26, 2026
d308073
Merge origin/develop into ngmix-flag-wholesale-failure
cailmdaley Sep 28, 2026
366420f
ngmix, make_cat: mark metacal failures with ngmix's LM_FUNC_NOTFINITE
cailmdaley Sep 28, 2026
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
13 changes: 8 additions & 5 deletions astra.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1955,15 +1955,18 @@ analyses:
rationale: >-
[HARDCODED] detections with no ngmix row (no surviving epoch, or an
exception during the fit) stay in the catalogue with sentinels:
sizes, fluxes, magnitudes and flags 0, flux and magnitude errors -1,
sizes, fluxes and magnitudes 0, flux and magnitude errors -1,
ellipticities and their errors -10, size errors 1e30,
NGMIX_N_EPOCH 0. A failed object's NGMIX_MCAL_FLAGS reads 0, the
success value, so a cut on flags alone keeps it; NGMIX_N_EPOCH > 0
removes it.
NGMIX_N_EPOCH 0. Their flag columns carry ngmix's own
LM_FUNC_NOTFINITE bit (2**12; FLAGS_<SHEAR> and NGMIX_MCAL_FLAGS)
and NGMIX_MCAL_TYPES_FAIL is 5, as for a metacal type that reports
success without a finite shear, so the MCAL_FLAGS == 0 and
MCAL_TYPES_FAIL == 0 cut rejects them; NGMIX_N_EPOCH == 0 tells
them apart from fitted objects.
default: sentinel_values
options:
sentinel_values:
label: Keep with sentinels (flags 0, e -10, T_ERR 1e30)
label: Keep with sentinels (flags LM_FUNC_NOTFINITE, e -10, T_ERR 1e30)
drop_unmatched:
label: Drop objects without shapes
excluded: true
Expand Down
43 changes: 33 additions & 10 deletions src/shapepipe/modules/make_cat_package/make_cat.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
from astropy.wcs import WCS
from sqlitedict import SqliteDict

from shapepipe.modules.ngmix_package.ngmix import (
get_mcal_flags,
get_mcal_types_fail,
get_type_flags,
)
from shapepipe.pipeline import file_io
from shapepipe.utilities import mask_query

Expand Down Expand Up @@ -423,11 +428,16 @@ def _save_ngmix_data(self, ngmix_cat_path, moments=False):
If True, write the parallel ``NGMIXm_*`` (moments-branch) columns.

@sc [decision:catalogue_assembly.failure_sentinels,label:coupling] failure-sentinel-cut-semantics
Missing-row ``T``, ``SNR``, flux, magnitude, PSF-size and flag values
initialize to 0, which is in range and cannot identify failure. Use
``NGMIX_N_EPOCH == 0`` for that cut; the -10 ellipticity, -1
flux/magnitude-error and 1e30 size-error sentinels are out of range and
can also identify missing fits.
An object absent from the ngmix catalogue was never fit (no usable
epoch, or its fit raised). Its flag columns take what
:func:`ngmix.get_type_flags` derives for an empty metacal result:
``LM_FUNC_NOTFINITE`` in ``FLAGS_<SHEAR>`` and ``MCAL_FLAGS``, and
``MCAL_TYPES_FAIL`` 5, never 0, so sp_validation's ``MCAL_FLAGS == 0``
and ``MCAL_TYPES_FAIL == 0`` cut rejects it. Its ``T``, ``SNR``, flux,
magnitude and PSF-size values initialize to 0, which is in range and
cannot identify failure; ``NGMIX_N_EPOCH == 0`` identifies a
never-fit row, and the -10 ellipticity, -1 flux/magnitude-error and
1e30 size-error sentinels are out of range.

"""
self._key_ends = ["1M", "1P", "2M", "2P", "NOSHEAR"]
Expand Down Expand Up @@ -462,13 +472,19 @@ def _save_ngmix_data(self, ngmix_cat_path, moments=False):
n_obj = len(self._obj_id)
self._w_log.info(f"writing ngmix info for {n_obj} objects")

# An object ngmix never fit has no metacal result at all.
never_fit = {}

if moments:
m = "m"
else:
m = ""

self._add2dict("NGMIX_N_EPOCH", np.zeros(n_obj))
self._add2dict("NGMIX_MCAL_TYPES_FAIL", np.zeros(n_obj))
self._add2dict(
"NGMIX_MCAL_TYPES_FAIL",
np.full(n_obj, get_mcal_types_fail(never_fit), dtype=float),
)
self._add2dict("NGMIX_NEIGHBOUR_FLAG", np.zeros(n_obj))

prefix = f"NGMIX{m}"
Expand All @@ -477,18 +493,22 @@ def _save_ngmix_data(self, ngmix_cat_path, moments=False):
# reconvolution kernel (PSF_RECONV); see ngmix.average_original_psf /
# average_multiepoch_psf for what each PSF family is. G1/G2 are scalar
# reduced-shear components, not a 2-vector. Sentinels:
# sizes/fluxes/mags/flags 0, *_ERR fluxes/mags -1, ellipticities -10,
# *_ERR sizes 1e30.
# sizes/fluxes/mags 0, *_ERR fluxes/mags -1, ellipticities -10,
# *_ERR sizes 1e30; flags as ngmix derives for an empty metacal result
# (never_fit).
for key_str in (
f"{prefix}_T_",
f"{prefix}_SNR_",
f"{prefix}_FLUX_",
f"{prefix}_MAG_",
f"{prefix}_FLAGS_",
f"{prefix}_T_PSF_ORIG_",
f"{prefix}_T_PSF_RECONV_",
):
self._update_dict(key_str, np.zeros(n_obj))
self._update_dict(
f"{prefix}_FLAGS_",
np.full(n_obj, get_type_flags(never_fit), dtype=float),
)
for key_str in (
f"{prefix}_FLUX_ERR_",
f"{prefix}_MAG_ERR_",
Expand All @@ -515,7 +535,10 @@ def _save_ngmix_data(self, ngmix_cat_path, moments=False):
f"{prefix}_T_ERR_PSF_RECONV_",
):
self._update_dict(key_str, np.ones(n_obj) * 1e30)
self._add2dict(f"{prefix}_MCAL_FLAGS", np.zeros(n_obj))
self._add2dict(
f"{prefix}_MCAL_FLAGS",
np.full(n_obj, get_mcal_flags(never_fit), dtype=float),
)

for idx, id_tmp in enumerate(self._obj_id):
ind = np.where(id_tmp == ngmix_id)[0]
Expand Down
Loading
Loading