LSSTApplications  17.0+11,17.0+34,17.0+56,17.0+57,17.0+59,17.0+7,17.0-1-g377950a+33,17.0.1-1-g114240f+2,17.0.1-1-g4d4fbc4+28,17.0.1-1-g55520dc+49,17.0.1-1-g5f4ed7e+52,17.0.1-1-g6dd7d69+17,17.0.1-1-g8de6c91+11,17.0.1-1-gb9095d2+7,17.0.1-1-ge9fec5e+5,17.0.1-1-gf4e0155+55,17.0.1-1-gfc65f5f+50,17.0.1-1-gfc6fb1f+20,17.0.1-10-g87f9f3f+1,17.0.1-11-ge9de802+16,17.0.1-16-ga14f7d5c+4,17.0.1-17-gc79d625+1,17.0.1-17-gdae4c4a+8,17.0.1-2-g26618f5+29,17.0.1-2-g54f2ebc+9,17.0.1-2-gf403422+1,17.0.1-20-g2ca2f74+6,17.0.1-23-gf3eadeb7+1,17.0.1-3-g7e86b59+39,17.0.1-3-gb5ca14a,17.0.1-3-gd08d533+40,17.0.1-30-g596af8797,17.0.1-4-g59d126d+4,17.0.1-4-gc69c472+5,17.0.1-6-g5afd9b9+4,17.0.1-7-g35889ee+1,17.0.1-7-gc7c8782+18,17.0.1-9-gc4bbfb2+3,w.2019.22
LSSTDataManagementBasePackage
PhotoCalib.h
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  * Copyright 2017 LSST Corporation.
4  *
5  * This product includes software developed by the
6  * LSST Project (http://www.lsst.org/).
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the LSST License Statement and
19  * the GNU General Public License along with this program. If not,
20  * see <http://www.lsstcorp.org/LegalNotices/>.
21  */
22 
23 #ifndef LSST_AFW_IMAGE_PHOTOCALIB_H
24 #define LSST_AFW_IMAGE_PHOTOCALIB_H
25 
32 #include <cmath> // For quiet_nan in the deprecated block
33 
34 #include "boost/format.hpp"
35 
38 #include "lsst/geom/Point.h"
39 #include "lsst/geom/Box.h"
40 #include "lsst/afw/table/Source.h"
46 #include "lsst/utils/Magnitude.h"
47 
48 namespace lsst {
49 namespace afw {
50 namespace image {
51 
53 struct Measurement {
54  Measurement(double value, double error) : value(value), error(error) {}
55  double const value;
56  double const error;
57 };
58 
59 std::ostream &operator<<(std::ostream &os, Measurement const &measurement);
60 
71 inline void assertNonNegative(double value, std::string const &name) {
72  if (value < 0) {
74  (boost::format("%s must be positive: %.3g") % name % value).str());
75  }
76 }
77 
116 class PhotoCalib final : public table::io::PersistableFacade<PhotoCalib>, public typehandling::Storable {
117 public:
118  // Allow move, but no copy
119  PhotoCalib(PhotoCalib const &) = default;
120  PhotoCalib(PhotoCalib &&) = default;
121  PhotoCalib &operator=(PhotoCalib const &) = delete;
122  PhotoCalib &operator=(PhotoCalib &&) = delete;
123 
124  ~PhotoCalib() override = default;
125 
130 
139  explicit PhotoCalib(double calibrationMean, double calibrationErr = 0,
141  : _calibrationMean(calibrationMean), _calibrationErr(calibrationErr), _isConstant(true) {
142  assertNonNegative(_calibrationMean, "Calibration mean");
143  assertNonNegative(_calibrationErr, "Calibration error");
144  ndarray::Array<double, 2, 2> coeffs = ndarray::allocate(ndarray::makeVector(1, 1));
145  coeffs[0][0] = calibrationMean;
146  _calibration = std::make_shared<afw::math::ChebyshevBoundedField>(
148  }
149 
157  : _calibration(calibration),
158  _calibrationMean(computeCalibrationMean(calibration)),
159  _calibrationErr(calibrationErr),
160  _isConstant(false) {
161  assertNonNegative(_calibrationMean, "Calibration (computed via BoundedField.mean()) mean");
162  assertNonNegative(_calibrationErr, "Calibration error");
163  }
164 
173  PhotoCalib(double calibrationMean, double calibrationErr,
175  : _calibration(calibration),
176  _calibrationMean(calibrationMean),
177  _calibrationErr(calibrationErr),
178  _isConstant(isConstant) {
179  assertNonNegative(_calibrationMean, "Calibration mean");
180  assertNonNegative(_calibrationErr, "Calibration error");
181  }
182 
193  double instFluxToNanojansky(double instFlux, lsst::geom::Point<double, 2> const &point) const;
194 
196  double instFluxToNanojansky(double instFlux) const;
197 
209  Measurement instFluxToNanojansky(double instFlux, double instFluxErr,
210  lsst::geom::Point<double, 2> const &point) const;
211 
213  Measurement instFluxToNanojansky(double instFlux, double instFluxErr) const;
214 
227  Measurement instFluxToNanojansky(const afw::table::SourceRecord &sourceRecord,
228  std::string const &instFluxField) const;
229 
242  ndarray::Array<double, 2, 2> instFluxToNanojansky(afw::table::SourceCatalog const &sourceCatalog,
243  std::string const &instFluxField) const;
244 
258  void instFluxToNanojansky(afw::table::SourceCatalog &sourceCatalog, std::string const &instFluxField,
259  std::string const &outField) const;
260 
271  double instFluxToMagnitude(double instFlux, lsst::geom::Point<double, 2> const &point) const;
272 
274  double instFluxToMagnitude(double instFlux) const;
275 
287  Measurement instFluxToMagnitude(double instFlux, double instFluxErr,
288  lsst::geom::Point<double, 2> const &point) const;
289 
291  Measurement instFluxToMagnitude(double instFlux, double instFluxErr) const;
292 
305  Measurement instFluxToMagnitude(afw::table::SourceRecord const &sourceRecord,
306  std::string const &instFluxField) const;
307 
320  ndarray::Array<double, 2, 2> instFluxToMagnitude(afw::table::SourceCatalog const &sourceCatalog,
321  std::string const &instFluxField) const;
322 
339  void instFluxToMagnitude(afw::table::SourceCatalog &sourceCatalog, std::string const &instFluxField,
340  std::string const &outField) const;
341 
352  MaskedImage<float> calibrateImage(MaskedImage<float> const &maskedImage,
353  bool includeScaleUncertainty = true) const;
354 
371  afw::table::SourceCatalog calibrateCatalog(afw::table::SourceCatalog const &catalog,
372  std::vector<std::string> const &instFluxFields) const;
373 
375  afw::table::SourceCatalog calibrateCatalog(afw::table::SourceCatalog const &catalog) const;
376 
389  double magnitudeToInstFlux(double magnitude, lsst::geom::Point<double, 2> const &point) const;
390 
392  double magnitudeToInstFlux(double magnitude) const;
393 
406  double getCalibrationMean() const { return _calibrationMean; }
407 
420  double getCalibrationErr() const { return _calibrationErr; }
421 
434  double getInstFluxAtZeroMagnitude() const { return utils::referenceFlux / _calibrationMean; }
435 
449  std::shared_ptr<afw::math::BoundedField> computeScaledCalibration() const;
450 
473 
475  bool operator==(PhotoCalib const &rhs) const;
476 
478  bool operator!=(PhotoCalib const &rhs) const { return !(*this == rhs); }
479 
480  bool isPersistable() const noexcept override { return true; }
481 
482  /* Backwards compatibility with old Calib object */
483 
485  [[deprecated("No-op: PhotoCalib never throws on negative instFlux. Will remove after v18.")]] static void
486  setThrowOnNegativeFlux(bool raiseException) noexcept {
487  ; // do nothing!
488  }
490  [[deprecated("No-op: PhotoCalib never throws on negative instFlux. Will remove after v18.")]] static bool
492  return false;
493  }
494 
498  [
499  [deprecated("For backwards compatibility with Calib; use `instFluxToMagnitude` instead. To be "
500  "removed after v18.")]] double
501  getMagnitude(double instFlux) const {
502  return instFluxToMagnitude(instFlux);
503  }
504 
508  [
509  [deprecated("For backwards compatibility with Calib; use `instFluxToMagnitude` instead. To be "
510  "removed after v18.")]] ndarray::Array<double, 1>
511  getMagnitude(ndarray::Array<double const, 1> const &instFlux) const;
512  [
513  [deprecated("For backwards compatibility with Calib; use `instFluxToMagnitude` instead. To be "
514  "removed after v18.")]] std::pair<double, double>
515  getMagnitude(double instFlux, double instFluxErr) const {
516  auto result = instFluxToMagnitude(instFlux, instFluxErr);
517  return std::make_pair<const double &, const double &>(result.value, result.error);
518  };
519  [[deprecated(
520  "For backwards compatibility with Calib; use `instFluxToMagnitude` instead. To be "
521  "removed after v18.")]] std::pair<ndarray::Array<double, 1>, ndarray::Array<double, 1>>
522  getMagnitude(ndarray::Array<double const, 1> const &instFlux,
523  ndarray::Array<double const, 1> const &instFluxErr) const;
528  [[deprecated(
529  "For backwards compatibility with Calib; use `magnitudeToInstFlux` instead. To be removed "
530  "after v18.")]] double
531  getFlux(double magnitude) const {
532  return magnitudeToInstFlux(magnitude);
533  }
538  [[deprecated(
539  "For backwards compatibility with Calib: use `getCalibrationMean`, `getCalibrationErr`, or "
540  "`getInstFluxAtZeroMagnitude. To be removed after v18.")]] std::pair<double, double>
541  getFluxMag0() const {
542  return std::make_pair<double, double>(getInstFluxAtZeroMagnitude(),
544  }
546  [[deprecated(
547  "PhotoCalib is immutable: create a new one with the calibration factor and calibration error,"
548  " or create it like an old Calib object with makePhotoCalibFromCalibZeroPoint.")]] void
549  setFluxMag0(double, double = 0) const {
550  std::string msg =
551  "PhotoCalib is immutable: create a new `PhotoCalib` with the calibration"
552  " factor and error, or create it like an old Calib object with "
553  "`makePhotoCalibFromCalibZeroPoint`.";
555  }
556 
558  std::shared_ptr<typehandling::Storable> cloneStorable() const override;
559 
561  std::string toString() const override;
562 
568  bool equals(typehandling::Storable const &other) const noexcept override;
569  // PhotoCalib equality comparable but intentionally not hashable
570 
571 protected:
572  std::string getPersistenceName() const override;
573 
574  void write(OutputArchiveHandle &handle) const override;
575 
576 private:
578 
579  // The "mean" calibration, defined as the geometric mean of _calibration evaluated over _calibration's
580  // bbox. Computed on instantiation as a convinience. Also, the actual calibration for a spatially-constant
581  // calibration.
582  double _calibrationMean;
583 
584  // The standard deviation of this PhotoCalib.
585  double _calibrationErr;
586 
587  // Is this spatially-constant? Used to short-circuit getting centroids.
588  bool _isConstant;
589 
595  double evaluate(lsst::geom::Point<double, 2> const &point) const;
599  ndarray::Array<double, 1> evaluateArray(ndarray::Array<double, 1> const &xx,
600  ndarray::Array<double, 1> const &yy) const;
604  ndarray::Array<double, 1> evaluateCatalog(afw::table::SourceCatalog const &sourceCatalog) const;
605 
607  double computeCalibrationMean(std::shared_ptr<afw::math::BoundedField> calibration) const;
608 
610  void instFluxToNanojanskyArray(afw::table::SourceCatalog const &sourceCatalog,
611  std::string const &instFluxField,
612  ndarray::Array<double, 2, 2> result) const;
613  void instFluxToMagnitudeArray(afw::table::SourceCatalog const &sourceCatalog,
614  std::string const &instFluxField,
615  ndarray::Array<double, 2, 2> result) const;
616 };
617 
630 
644 std::shared_ptr<PhotoCalib> makePhotoCalibFromCalibZeroPoint(double instFluxMag0, double instFluxMag0Err);
645 
646 } // namespace image
647 } // namespace afw
648 } // namespace lsst
649 
650 #endif // LSST_AFW_IMAGE_PHOTOCALIB_H
std::shared_ptr< PhotoCalib > makePhotoCalibFromMetadata(daf::base::PropertySet &metadata, bool strip=false)
Construct a PhotoCalib from FITS FLUXMAG0/FLUXMAG0ERR keywords.
Definition: PhotoCalib.cc:626
bool isPersistable() const noexcept override
Return true if this particular object can be persisted using afw::table::io.
Definition: PhotoCalib.h:480
std::shared_ptr< PhotoCalib > makePhotoCalibFromCalibZeroPoint(double instFluxMag0, double instFluxMag0Err)
Construct a PhotoCalib from the deprecated Calib-style instFluxMag0/instFluxMag0Err values...
Definition: PhotoCalib.cc:644
PhotoCalib(double calibrationMean, double calibrationErr, std::shared_ptr< afw::math::BoundedField > calibration, bool isConstant)
Create a calibration with a pre-computed mean.
Definition: PhotoCalib.h:173
static bool getThrowOnNegativeFlux() noexcept
No-op: for backwards compatibility with Calib (always returns false).
Definition: PhotoCalib.h:491
std::ostream & operator<<(std::ostream &os, Measurement const &measurement)
Definition: PhotoCalib.cc:48
double getCalibrationMean() const
Get the mean photometric calibration.
Definition: PhotoCalib.h:406
An object passed to Persistable::write to allow it to persist itself.
The photometric calibration of an exposure.
Definition: PhotoCalib.h:116
Interface supporting iteration over heterogenous containers.
Definition: Storable.h:56
py::object result
Definition: schema.cc:418
bool operator!=(PhotoCalib const &rhs) const
Two PhotoCalibs are equal if their component bounded fields and calibrationErr are equal...
Definition: PhotoCalib.h:478
A value and its error.
Definition: PhotoCalib.h:53
PhotoCalib(double calibrationMean, double calibrationErr=0, lsst::geom::Box2I const &bbox=lsst::geom::Box2I())
Create a non-spatially-varying calibration.
Definition: PhotoCalib.h:139
STL class.
A base class for image defects.
static void setThrowOnNegativeFlux(bool raiseException) noexcept
No-op: for backwards compatibility with Calib.
Definition: PhotoCalib.h:486
PhotoCalib(std::shared_ptr< afw::math::BoundedField > calibration, double calibrationErr=0)
Create a spatially-varying calibration.
Definition: PhotoCalib.h:156
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
A class to manipulate images, masks, and variance as a single object.
Definition: MaskedImage.h:74
Utilities for converting between flux and magnitude in C++.
table::Key< double > calibrationMean
Definition: PhotoCalib.cc:398
PhotoCalib()
Create a empty, zeroed calibration.
Definition: PhotoCalib.h:129
void setFluxMag0(double, double=0) const
Invalid for PhotoCalib: this only exists to provide the user an informative error message...
Definition: PhotoCalib.h:549
table::Box2IKey bbox
Definition: Detector.cc:169
Measurement(double value, double error)
Definition: PhotoCalib.h:54
std::pair< double, double > getMagnitude(double instFlux, double instFluxErr) const
Definition: PhotoCalib.h:515
double getCalibrationErr() const
Get the mean photometric calibration error.
Definition: PhotoCalib.h:420
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
A BoundedField based on 2-d Chebyshev polynomials of the first kind.
Class for storing generic metadata.
Definition: PropertySet.h:68
std::pair< double, double > getFluxMag0() const
Get the magnitude zero point (the instrumental flux corresponding to 0 magnitude).
Definition: PhotoCalib.h:541
Reports invalid arguments.
Definition: Runtime.h:66
ItemVariant const * other
Definition: Schema.cc:56
double getMagnitude(double instFlux) const
Definition: PhotoCalib.h:501
Record class that contains measurements made on a single exposure.
Definition: Source.h:82
table::Key< table::Flag > isConstant
Definition: PhotoCalib.cc:400
T quiet_NaN(T... args)
void assertNonNegative(double value, std::string const &name)
Raise lsst::pex::exceptions::InvalidParameterError if value is not >=0.
Definition: PhotoCalib.h:71
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects...
const double referenceFlux
The Oke & Gunn (1983) AB magnitude reference flux, in nJy (often approximated as 3631.0).
Definition: Magnitude.h:46
A CRTP facade class for subclasses of Persistable.
Definition: Persistable.h:176
An integer coordinate rectangle.
Definition: Box.h:54
STL class.
double getFlux(double magnitude) const
Definition: PhotoCalib.h:531
bool strip
Definition: fits.cc:883
double getInstFluxAtZeroMagnitude() const
Get the magnitude zero point (the instrumental flux corresponding to 0 magnitude).
Definition: PhotoCalib.h:434
table::Key< double > calibrationErr
Definition: PhotoCalib.cc:399
std::ostream * os
Definition: Schema.cc:746
Reports errors that are due to events beyond the control of the program.
Definition: Runtime.h:104