diff --git a/include/lsst/afw/image/PhotoCalib.h b/include/lsst/afw/image/PhotoCalib.h index 6d5168972..7472376eb 100644 --- a/include/lsst/afw/image/PhotoCalib.h +++ b/include/lsst/afw/image/PhotoCalib.h @@ -389,6 +389,23 @@ class PhotoCalib final : public table::io::PersistableFacade, public /// @overload magnitudeToInstFlux(double, lsst::geom::Point const &) const; double magnitudeToInstFlux(double magnitude) const; + /** + * Convert nanojansky to instFlux (ADU). + * + * If passed point, use the exact calculation at that point, otherwise, use the mean scaling factor. + * + * Useful for computing expected instrumental flux from reference catalog sources. + * + * @param[in] nanojansky The flux in nanojanksies to convert. + * @param[in] point The position that flux is to be converted at. + * + * @returns Source instFlux in ADU. + */ + double nanojanskyToInstFlux(double nanojansky, lsst::geom::Point const &point) const; + + /// @overload nanojanskyToInstFlux(double, lsst::geom::Point const &) const; + double nanojanskyToInstFlux(double nanojansky) const; + /** * Get the mean photometric calibration. * diff --git a/python/lsst/afw/image/_photoCalib.cc b/python/lsst/afw/image/_photoCalib.cc index 89cf09d88..d551463e9 100644 --- a/python/lsst/afw/image/_photoCalib.cc +++ b/python/lsst/afw/image/_photoCalib.cc @@ -154,10 +154,19 @@ void declarePhotoCalib(lsst::utils::python::WrapperCollection &wrappers) { cls.def("magnitudeToInstFlux", py::overload_cast const &>( &PhotoCalib::magnitudeToInstFlux, py::const_), - "instFlux"_a, "point"_a); + "magnitude"_a, "point"_a); cls.def("magnitudeToInstFlux", py::overload_cast(&PhotoCalib::magnitudeToInstFlux, py::const_), - "instFlux"_a); + "magnitude"_a); + + /* from nanojansky. */ + cls.def("nanojanskyToInstFlux", + py::overload_cast const &>( + &PhotoCalib::nanojanskyToInstFlux, py::const_), + "nanojansky"_a, "point"_a); + cls.def("nanojanskyToInstFlux", + py::overload_cast(&PhotoCalib::nanojanskyToInstFlux, py::const_), + "nanojansky"_a); /* utilities */ cls.def("getCalibrationMean", &PhotoCalib::getCalibrationMean); diff --git a/src/image/PhotoCalib.cc b/src/image/PhotoCalib.cc index 894872955..d9a682fb1 100644 --- a/src/image/PhotoCalib.cc +++ b/src/image/PhotoCalib.cc @@ -65,6 +65,8 @@ double toInstFluxFromMagnitude(double magnitude, double scale) { return utils::ABMagnitudeToNanojansky(magnitude) / scale; } +double toInstFluxFromNanojansky(double nanojansky, double scale) { return nanojansky / scale; } + double toNanojanskyErr(double instFlux, double instFluxErr, double scale, double scaleErr, double nanojansky) { return std::abs(nanojansky) * hypot(instFluxErr / instFlux, scaleErr / scale); @@ -219,6 +221,14 @@ double PhotoCalib::magnitudeToInstFlux(double magnitude, lsst::geom::Point const &point) const { + return toInstFluxFromNanojansky(nanojansky, evaluate(point)); +} + std::shared_ptr PhotoCalib::computeScaledCalibration() const { return *(_calibration) / _calibrationMean; } diff --git a/tests/test_photoCalib.py b/tests/test_photoCalib.py index d7fb9174f..2108b8fff 100644 --- a/tests/test_photoCalib.py +++ b/tests/test_photoCalib.py @@ -258,6 +258,20 @@ def _testPhotoCalibCenter(self, photoCalib, calibrationErr): photoCalib.magnitudeToInstFlux(mag2, self.pointXShift), rtol=1e-15) + # test reverse conversion: nanojansky to instFlux (no position specified) + self.assertFloatsAlmostEqual(self.instFlux1, photoCalib.nanojanskyToInstFlux(self.flux1)) + self.assertFloatsAlmostEqual(self.instFlux2, photoCalib.nanojanskyToInstFlux(self.flux2), rtol=1e-15) + + # test round-tripping instFlux->nanojansky->instFlux (position specified) + flux = photoCalib.instFluxToNanojansky(self.instFlux1, self.pointXShift) + self.assertFloatsAlmostEqual(self.instFlux1, + photoCalib.nanojanskyToInstFlux(flux, self.pointXShift), + rtol=1e-15) + flux2 = photoCalib.instFluxToNanojansky(self.instFlux2, self.pointXShift) + self.assertFloatsAlmostEqual(self.instFlux2, + photoCalib.nanojanskyToInstFlux(flux2, self.pointXShift), + rtol=1e-15) + # test round-tripping arrays (position specified) instFlux1Array = np.full(10, self.instFlux1) instFlux2Array = np.full(10, self.instFlux2)