Skip to content

Commit a686ea4

Browse files
committed
Raise PhotoCalInputFluxError if no calib fluxes for photocal
1 parent 8b7d742 commit a686ea4

File tree

2 files changed

+56
-6
lines changed

2 files changed

+56
-6
lines changed

python/lsst/pipe/tasks/photoCal.py

+37-5
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
# You should have received a copy of the GNU General Public License
2020
# along with this program. If not, see <https://www.gnu.org/licenses/>.
2121

22-
__all__ = ["PhotoCalTask", "PhotoCalConfig"]
22+
__all__ = ["PhotoCalTask", "PhotoCalConfig", "PhotoCalInputFluxError"]
2323

2424
import math
2525
import sys
@@ -38,6 +38,35 @@
3838
from .colorterms import ColortermLibrary
3939

4040

41+
class PhotoCalInputFluxError(pipeBase.AlgorithmError):
42+
"""Raised if photoCal fails in a non-recoverable way.
43+
44+
Parameters
45+
----------
46+
nMatches : `int`
47+
Number of nMatches available to the fitter at the point of failure.
48+
nFiniteInstFluxes : `int`
49+
Number of calibration instFluxes that are are finite (non-NaN).
50+
nFiniteInstFluxes : `int`
51+
Number of calibration instFluxErrs that are are finite (non-NaN).
52+
"""
53+
def __init__(self, *, nMatches, nFiniteInstFluxes, nFiniteInstFluxErrs):
54+
msg = (f"No finite calibration instFluxes ({nFiniteInstFluxes}) or "
55+
f"instFluxErrs ({nFiniteInstFluxErrs}) for {nMatches} matches.")
56+
super().__init__(msg)
57+
self.nMatches = nMatches
58+
self.nFiniteInstFluxes = nFiniteInstFluxes
59+
self.nFiniteInstFluxErrs = nFiniteInstFluxErrs
60+
61+
@property
62+
def metadata(self):
63+
metadata = {"nMatches": self.nMatches,
64+
"nFiniteInstFluxes": self.nFiniteInstFluxes,
65+
"nFiniteInstFluxErrs": self.nFiniteInstFluxErrs,
66+
}
67+
return metadata
68+
69+
4170
class PhotoCalConfig(pexConf.Config):
4271
"""Config for PhotoCal."""
4372

@@ -238,10 +267,13 @@ def extractMagArrays(self, matches, filterLabel, sourceKeys):
238267
"""
239268
srcInstFluxArr = np.array([m.second.get(sourceKeys.instFlux) for m in matches])
240269
srcInstFluxErrArr = np.array([m.second.get(sourceKeys.instFluxErr) for m in matches])
241-
if not np.all(np.isfinite(srcInstFluxErrArr)):
242-
# this is an unpleasant hack; see DM-2308 requesting a better solution
243-
self.log.warning("Source catalog does not have flux uncertainties; using sqrt(flux).")
244-
srcInstFluxErrArr = np.sqrt(srcInstFluxArr)
270+
271+
nFiniteInstFluxes = np.isfinite(srcInstFluxArr).sum()
272+
nFiniteInstFluxErrs = np.isfinite(srcInstFluxErrArr).sum()
273+
274+
if not nFiniteInstFluxes or not nFiniteInstFluxErrs:
275+
raise PhotoCalInputFluxError(nMatches=len(matches), nFiniteInstFluxes=nFiniteInstFluxes,
276+
nFiniteInstFluxErrs=nFiniteInstFluxErrs)
245277

246278
# convert source instFlux from DN to an estimate of nJy
247279
referenceFlux = (0*u.ABmag).to_value(u.nJy)

tests/test_photoCal.py

+19-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import lsst.afw.image as afwImage
3333
import lsst.utils.tests
3434
from lsst.utils import getPackageDir
35-
from lsst.pipe.tasks.photoCal import PhotoCalTask, PhotoCalConfig
35+
from lsst.pipe.tasks.photoCal import PhotoCalTask, PhotoCalConfig, PhotoCalInputFluxError
3636
from lsst.pipe.tasks.colorterms import Colorterm, ColortermDict, ColortermLibrary
3737
from lsst.utils.logging import TRACE
3838
from lsst.meas.algorithms.testUtils import MockReferenceObjectLoaderFromFiles
@@ -199,6 +199,24 @@ def testColorTerms(self):
199199
# zeropoint: 32.3145
200200
self.assertLess(abs(self.zp - (31.3145 + zeroPointOffset)), 0.05)
201201

202+
def testNoFiniteFluxes(self):
203+
"""Test case where matches exist but calib fluxes are NaN"""
204+
catalog = self.srcCat.copy(deep=True)
205+
catalog['slot_ApFlux_instFlux'] = np.nan
206+
task = PhotoCalTask(self.refObjLoader, config=self.config, schema=self.srcCat.schema)
207+
with self.assertRaisesRegex(PhotoCalInputFluxError,
208+
r"No finite calibration instFluxes \(0\) or instFluxErrs \(\d+\)"):
209+
task.run(exposure=self.exposure, sourceCat=catalog)
210+
211+
def testNoFiniteFluxErrs(self):
212+
"""Test case where matches exist but calib fluxErrs are NaN"""
213+
catalog = self.srcCat.copy(deep=True)
214+
catalog['slot_ApFlux_instFluxErr'] = np.nan
215+
task = PhotoCalTask(self.refObjLoader, config=self.config, schema=self.srcCat.schema)
216+
with self.assertRaisesRegex(PhotoCalInputFluxError,
217+
r"No finite calibration instFluxes \(\d+\) or instFluxErrs \(0\)"):
218+
task.run(exposure=self.exposure, sourceCat=catalog)
219+
202220

203221
class MemoryTester(lsst.utils.tests.MemoryTestCase):
204222
pass

0 commit comments

Comments
 (0)