From 1f213ed07522d0adf09e33d2023e71f1b88aa0d7 Mon Sep 17 00:00:00 2001 From: Clare Saunders Date: Wed, 26 Jun 2024 15:14:12 -0700 Subject: [PATCH] Change RuntimeError to AlgorithmError --- .../algorithms/normalizedCalibrationFlux.py | 58 +++++++++++++++---- tests/test_normalizedCalibrationFlux.py | 16 ++++- 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/python/lsst/meas/algorithms/normalizedCalibrationFlux.py b/python/lsst/meas/algorithms/normalizedCalibrationFlux.py index 9b6c97c58..b3322e45e 100644 --- a/python/lsst/meas/algorithms/normalizedCalibrationFlux.py +++ b/python/lsst/meas/algorithms/normalizedCalibrationFlux.py @@ -19,7 +19,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -__all__ = ["NormalizedCalibrationFluxConfig", "NormalizedCalibrationFluxTask"] +__all__ = ["NormalizedCalibrationFluxConfig", "NormalizedCalibrationFluxTask", + "NormalizedCalibrationFluxError"] import numpy as np @@ -31,6 +32,35 @@ from .sourceSelector import sourceSelectorRegistry +class NormalizedCalibrationFluxError(lsst.pipe.base.AlgorithmError): + """Raised if Aperture Correction fails in a non-recoverable way. + + Parameters + ---------- + initNSources : `int` + Number of sources selected by the fallback source selector. + nCalibFluxFlag : `int` + Number of selected sources with raw calibration flux flag unset. + nRefFluxFlag : `int` + Number of selected sources with reference flux flag unset. + """ + def __init__(self, *, initNSources, nCalibFluxFlag, nRefFluxFlag): + msg = "There are no valid stars to compute normalized calibration fluxes." + msg += (f" Of {initNSources} initially selected sources, {nCalibFluxFlag} have good raw calibration " + f"fluxes and {nRefFluxFlag} have good reference fluxes.") + super().__init__(msg) + self.initNSources = initNSources + self.nCalibFluxFlag = nCalibFluxFlag + self.nRefFluxFlag = nRefFluxFlag + + @property + def metadata(self): + metadata = {"nInitSources": self.initNSources, + "nCalibFluxFlag": self.nCalibFluxFlag, + "nRefFluxFlag": self.nRefFluxFlag} + return metadata + + class NormalizedCalibrationFluxConfig(lsst.pex.config.Config): """Configuration parameters for NormalizedCalibrationFluxTask. """ @@ -99,6 +129,11 @@ class NormalizedCalibrationFluxTask(lsst.pipe.base.Task): Schema for the input table; will be modified in place. **kwargs : `dict` Additional kwargs to pass to lsst.pipe.base.Task.__init__() + + Raises + ------ + NormalizedCalibrationFluxError if there are not enough sources to + calculate normalization. """ ConfigClass = NormalizedCalibrationFluxConfig _DefaultName = "normalizedCalibrationFlux" @@ -265,18 +300,21 @@ def _measure_aperture_correction(self, exposure, catalog): ).apCorrMap ap_corr_field = ap_corr_map.get(raw_name + "_instFlux") - except MeasureApCorrError: - self.log.warning("Failed to measure full aperture correction for %s", raw_name) + except MeasureApCorrError as e: + self.log.warning("Failed to measure full aperture correction for %s with the following error %s", + raw_name, e) - sel = self.fallback_source_selector.run(catalog, exposure=exposure).selected - sel &= (~catalog[self.config.raw_calibflux_name + "_flag"] - & ~catalog[self.config.measure_ap_corr.refFluxName + "_flag"]) + initSel = self.fallback_source_selector.run(catalog, exposure=exposure).selected + sel = (initSel & ~catalog[self.config.raw_calibflux_name + "_flag"] + & ~catalog[self.config.measure_ap_corr.refFluxName + "_flag"]) - n_sel = sel.sum() - - if n_sel == 0: + if (n_sel := sel.sum()) == 0: # This is a fatal error. - raise RuntimeError("There are no valid stars to compute normalized calibration fluxes.") + raise NormalizedCalibrationFluxError( + initNSources=initSel.sum(), + nCalibFluxFlag=(initSel & ~catalog[self.config.raw_calibflux_name + "_flag"]).sum(), + nRefFluxFlag=(initSel & ~catalog[self.config.measure_ap_corr.refFluxName + "_flag"]).sum() + ) self.log.info("Measuring normalized flux correction with %d stars from fallback selector.", n_sel) diff --git a/tests/test_normalizedCalibrationFlux.py b/tests/test_normalizedCalibrationFlux.py index 78c2e5819..5133f69b2 100644 --- a/tests/test_normalizedCalibrationFlux.py +++ b/tests/test_normalizedCalibrationFlux.py @@ -27,7 +27,7 @@ import lsst.afw.image import lsst.afw.table import lsst.utils.tests -from lsst.meas.algorithms import NormalizedCalibrationFluxTask +from lsst.meas.algorithms import NormalizedCalibrationFluxTask, NormalizedCalibrationFluxError class NormalizedCalibrationFluxTestCase(lsst.utils.tests.TestCase): @@ -260,6 +260,20 @@ def testNormalizedCalibrationFluxApplyOnlyFail(self): warnings = '\n'.join(cm.output) self.assertIn("aperture correction map is missing base_CompensatedTophatFlux_12_instFlux", warnings) + def testNormalizedCalibrationFluxError(self): + + np.random.seed(12345) + norm_task = self._make_task() + catalog = self._make_catalog(norm_task.schema) + catalog[norm_task.config.raw_calibflux_name + "_flag"] = True + nStars = len(catalog) + + error_string = (f"There are no valid stars to compute normalized calibration fluxes. Of {nStars} " + "initially selected sources, 0 have good raw calibration fluxes and {nStars} have " + "good reference fluxes.") + with self.assertRaises(NormalizedCalibrationFluxError, msg=error_string): + norm_task.run(catalog=catalog, exposure=self.exposure) + class TestMemory(lsst.utils.tests.MemoryTestCase): pass