Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DM-2308: Raise PhotoCalInputFluxError if no calib fluxes for photocal #951

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
42 changes: 37 additions & 5 deletions python/lsst/pipe/tasks/photoCal.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

__all__ = ["PhotoCalTask", "PhotoCalConfig"]
__all__ = ["PhotoCalTask", "PhotoCalConfig", "PhotoCalInputFluxError"]

import math
import sys
Expand All @@ -38,6 +38,35 @@
from .colorterms import ColortermLibrary


class PhotoCalInputFluxError(pipeBase.AlgorithmError):
"""Raised if photoCal fails in a non-recoverable way.

Parameters
----------
nMatches : `int`
Number of nMatches available to the fitter at the point of failure.
nFiniteInstFluxes : `int`
Number of calibration instFluxes that are are finite (non-NaN).
nFiniteInstFluxes : `int`
Number of calibration instFluxErrs that are are finite (non-NaN).
"""
def __init__(self, *, nMatches, nFiniteInstFluxes, nFiniteInstFluxErrs):
msg = (f"No finite calibration instFluxes ({nFiniteInstFluxes}) or "
f"instFluxErrs ({nFiniteInstFluxErrs}) for {nMatches} matches.")
super().__init__(msg)
self.nMatches = nMatches
self.nFiniteInstFluxes = nFiniteInstFluxes
self.nFiniteInstFluxErrs = nFiniteInstFluxErrs

@property
def metadata(self):
metadata = {"nMatches": self.nMatches,
"nFiniteInstFluxes": self.nFiniteInstFluxes,
"nFiniteInstFluxErrs": self.nFiniteInstFluxErrs,
}
return metadata


class PhotoCalConfig(pexConf.Config):
"""Config for PhotoCal."""

Expand Down Expand Up @@ -238,10 +267,13 @@ def extractMagArrays(self, matches, filterLabel, sourceKeys):
"""
srcInstFluxArr = np.array([m.second.get(sourceKeys.instFlux) for m in matches])
srcInstFluxErrArr = np.array([m.second.get(sourceKeys.instFluxErr) for m in matches])
if not np.all(np.isfinite(srcInstFluxErrArr)):
# this is an unpleasant hack; see DM-2308 requesting a better solution
self.log.warning("Source catalog does not have flux uncertainties; using sqrt(flux).")
srcInstFluxErrArr = np.sqrt(srcInstFluxArr)

nFiniteInstFluxes = np.isfinite(srcInstFluxArr).sum()
nFiniteInstFluxErrs = np.isfinite(srcInstFluxErrArr).sum()

if not nFiniteInstFluxes or not nFiniteInstFluxErrs:
raise PhotoCalInputFluxError(nMatches=len(matches), nFiniteInstFluxes=nFiniteInstFluxes,
nFiniteInstFluxErrs=nFiniteInstFluxErrs)

# convert source instFlux from DN to an estimate of nJy
referenceFlux = (0*u.ABmag).to_value(u.nJy)
Expand Down
20 changes: 19 additions & 1 deletion tests/test_photoCal.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import lsst.afw.image as afwImage
import lsst.utils.tests
from lsst.utils import getPackageDir
from lsst.pipe.tasks.photoCal import PhotoCalTask, PhotoCalConfig
from lsst.pipe.tasks.photoCal import PhotoCalTask, PhotoCalConfig, PhotoCalInputFluxError
from lsst.pipe.tasks.colorterms import Colorterm, ColortermDict, ColortermLibrary
from lsst.utils.logging import TRACE
from lsst.meas.algorithms.testUtils import MockReferenceObjectLoaderFromFiles
Expand Down Expand Up @@ -199,6 +199,24 @@ def testColorTerms(self):
# zeropoint: 32.3145
self.assertLess(abs(self.zp - (31.3145 + zeroPointOffset)), 0.05)

def testNoFiniteFluxes(self):
"""Test case where matches exist but calib fluxes are NaN"""
catalog = self.srcCat.copy(deep=True)
catalog['slot_ApFlux_instFlux'] = np.nan
task = PhotoCalTask(self.refObjLoader, config=self.config, schema=self.srcCat.schema)
with self.assertRaisesRegex(PhotoCalInputFluxError,
r"No finite calibration instFluxes \(0\) or instFluxErrs \(\d+\)"):
task.run(exposure=self.exposure, sourceCat=catalog)

def testNoFiniteFluxErrs(self):
"""Test case where matches exist but calib fluxErrs are NaN"""
catalog = self.srcCat.copy(deep=True)
catalog['slot_ApFlux_instFluxErr'] = np.nan
task = PhotoCalTask(self.refObjLoader, config=self.config, schema=self.srcCat.schema)
with self.assertRaisesRegex(PhotoCalInputFluxError,
r"No finite calibration instFluxes \(\d+\) or instFluxErrs \(0\)"):
task.run(exposure=self.exposure, sourceCat=catalog)


class MemoryTester(lsst.utils.tests.MemoryTestCase):
pass
Expand Down
Loading