lsst.jointcal  15.0-7-gab4c137+6
CcdImage.cc
Go to the documentation of this file.
1 #include <assert.h>
2 #include <string>
3 #include <sstream>
4 #include <math.h>
5 
7 #include "lsst/pex/exceptions.h"
8 #include "lsst/afw/image/Image.h"
10 #include "lsst/afw/geom/Angle.h"
11 #include "lsst/afw/geom/Point.h"
12 
13 #include "lsst/log/Log.h"
14 #include "lsst/jointcal/CcdImage.h"
15 #include "lsst/jointcal/Gtransfo.h"
16 #include "lsst/jointcal/Point.h"
17 
18 namespace jointcal = lsst::jointcal;
19 namespace afwImg = lsst::afw::image;
20 
21 namespace {
22 LOG_LOGGER _log = LOG_GET("jointcal.CcdImage");
23 }
24 
25 namespace lsst {
26 namespace jointcal {
27 
29  out << "(visit: " << key.first << ", ccd: " << key.second << ")";
30  return out;
31 }
32 
33 void CcdImage::loadCatalog(afw::table::SourceCatalog const &catalog, std::string const &fluxField) {
34  auto xKey = catalog.getSchema().find<double>("slot_Centroid_x").key;
35  auto yKey = catalog.getSchema().find<double>("slot_Centroid_y").key;
36  auto xsKey = catalog.getSchema().find<float>("slot_Centroid_xSigma").key;
37  auto ysKey = catalog.getSchema().find<float>("slot_Centroid_ySigma").key;
38  auto mxxKey = catalog.getSchema().find<double>("slot_Shape_xx").key;
39  auto myyKey = catalog.getSchema().find<double>("slot_Shape_yy").key;
40  auto mxyKey = catalog.getSchema().find<double>("slot_Shape_xy").key;
41  auto fluxKey = catalog.getSchema().find<double>(fluxField + "_flux").key;
42  auto fluxErrKey = catalog.getSchema().find<double>(fluxField + "_fluxSigma").key;
43 
44  auto transform = _detector->getTransform(afw::cameraGeom::PIXELS, afw::cameraGeom::FOCAL_PLANE);
45 
46  _wholeCatalog.clear();
47  for (auto const &record : catalog) {
48  auto ms = std::make_shared<MeasuredStar>();
49  ms->setId(record.getId());
50  ms->x = record.get(xKey);
51  ms->y = record.get(yKey);
52  ms->vx = std::pow(record.get(xsKey), 2);
53  ms->vy = std::pow(record.get(ysKey), 2);
54  auto pointFocal = transform->applyForward(record.getCentroid());
55  ms->setXFocal(pointFocal.getX());
56  ms->setYFocal(pointFocal.getY());
57  /* the xy covariance is not provided in the input catalog: we
58  cook it up from the x and y position variance and the shape
59  measurements: */
60  double mxx = record.get(mxxKey);
61  double myy = record.get(myyKey);
62  double mxy = record.get(mxyKey);
63  ms->vxy = mxy * (ms->vx + ms->vy) / (mxx + myy);
64  if (std::isnan(ms->vxy) || ms->vx < 0 || ms->vy < 0 || (ms->vxy * ms->vxy) > (ms->vx * ms->vy)) {
65  LOGLS_WARN(_log, "Bad source detected during loadCatalog id: "
66  << ms->getId() << " with vx,vy: " << ms->vx << "," << ms->vy
67  << " vxy^2: " << ms->vxy * ms->vxy << " vx*vy: " << ms->vx * ms->vy);
68  continue;
69  }
70  ms->setInstFlux(record.get(fluxKey));
71  ms->setInstFluxErr(record.get(fluxErrKey));
72  // TODO: the below lines will be less clumsy once DM-4044 is cleaned up and we can say:
73  // TODO: instFluxToMaggies(ms->getInstFlux(), ms) (because ms will be derived from afw::geom::Point).
74  afw::geom::Point<double, 2> point(ms->x, ms->y);
75  auto flux = _photoCalib->instFluxToMaggies(ms->getInstFlux(), ms->getInstFluxErr(), point);
76  ms->setFlux(flux.value);
77  ms->setFluxErr(flux.err);
78  ms->mag = _photoCalib->instFluxToMagnitude(ms->getInstFlux(), point);
79  ms->setCcdImage(this);
80  _wholeCatalog.push_back(std::move(ms));
81  }
82  _wholeCatalog.setCcdImage(this);
83 }
84 
87  std::string const &filter, std::shared_ptr<afw::image::PhotoCalib> photoCalib,
88  std::shared_ptr<afw::cameraGeom::Detector> detector, int visit, int ccdId,
89  std::string const &fluxField)
90  : _ccdId(ccdId), _visit(visit), _photoCalib(photoCalib), _detector(detector), _filter(filter) {
91  loadCatalog(catalog, fluxField);
92 
93  Point lowerLeft(bbox.getMinX(), bbox.getMinY());
94  Point upperRight(bbox.getMaxX(), bbox.getMaxY());
95  _imageFrame = Frame(lowerLeft, upperRight);
96 
97  _readWcs = std::make_shared<GtransfoSkyWcs>(wcs);
98 
100  out << visit << "_" << ccdId;
101  _name = out.str();
102 
103  _boresightRaDec = visitInfo->getBoresightRaDec();
104  _airMass = visitInfo->getBoresightAirmass();
105  _mjd = visitInfo->getDate().get(lsst::daf::base::DateTime::MJD);
106  double latitude = visitInfo->getObservatory().getLatitude();
107  _lstObs = visitInfo->getEra();
108  _hourAngle = visitInfo->getBoresightHourAngle();
109 
110  // lsstSim doesn't manage ERA (and thus Hour Angle) properly, so it's going to be NaN.
111  // Because we need the refraction vector later, go with 0 HA to prevent crashes on that NaN.
112  if (std::isnan(_hourAngle) == true) {
113  _hourAngle = 0;
114  }
115 
116  if (_airMass == 1)
117  _sineta = _coseta = _tgz = 0;
118  else {
119  double cosz = 1. / _airMass;
120  double sinz = sqrt(1 - cosz * cosz); // astronomers usually observe above the horizon
121  _tgz = sinz / cosz;
122  // TODO: as part of DM-12473, we can remove all of this and just call _visitInfo.getParallacticAngle()
123  double dec = _boresightRaDec.getLatitude();
124  // x/y components of refraction angle, eta.]
125  double yEta = sin(_hourAngle);
126  double xEta = cos(dec) * tan(latitude) - sin(dec) * cos(_hourAngle);
127  double eta = atan2(yEta, xEta);
128  _sineta = sin(eta);
129  _coseta = cos(eta);
130  }
131 }
132 
133 void CcdImage::setCommonTangentPoint(Point const &commonTangentPoint) {
134  _commonTangentPoint = commonTangentPoint;
135 
136  auto const crval = _readWcs->getSkyWcs()->getSkyOrigin();
137  jointcal::Point tangentPoint(crval[0].asDegrees(), crval[1].asDegrees());
138 
139  /* we don't assume here that we know the internals of TanPix2RaDec:
140  to construct pix->TP, we do pix->sky->TP, although pix->sky
141  actually goes through TP */
142  GtransfoLin identity;
143  TanRaDec2Pix raDec2TP(identity, tangentPoint);
144  _pix2TP = gtransfoCompose(raDec2TP, *_readWcs);
145  TanPix2RaDec CTP2RaDec(identity, commonTangentPoint);
146  _CTP2TP = gtransfoCompose(raDec2TP, CTP2RaDec);
147 
148  // jump from one TP to an other:
149  TanRaDec2Pix raDec2CTP(identity, commonTangentPoint);
150  TanPix2RaDec TP2RaDec(identity, tangentPoint);
151  _TP2CTP = gtransfoCompose(raDec2CTP, TP2RaDec);
152  _sky2TP.reset(new TanRaDec2Pix(identity, tangentPoint));
153 
154  // this one is needed for matches :
155  _pix2CommonTangentPlane = gtransfoCompose(raDec2CTP, *_readWcs);
156 }
157 } // namespace jointcal
158 } // namespace lsst
implements the linear transformations (6 real coefficients).
Definition: Gtransfo.h:391
double dec
std::ostream & operator<<(std::ostream &out, CcdImageKey const &key)
Definition: CcdImage.cc:28
A point in a plane.
Definition: Point.h:13
the transformation that handles pix to sideral transfos (Gnomonic, possibly with polynomial distortio...
Definition: Gtransfo.h:577
table::PointKey< double > crval
table::Key< geom::Angle > latitude
T atan2(T... args)
STL class.
T sin(T... args)
rectangle with sides parallel to axes.
Definition: Frame.h:15
SchemaItem< T > find(std::string const &name) const
Class for a simple mapping implementing a generic Gtransfo.
Key< U > key
T cos(T... args)
T move(T... args)
T get(T... args)
Angle getLatitude() const noexcept
This one is the Tangent Plane (called gnomonic) projection (from celestial sphere to tangent plane) ...
Definition: Gtransfo.h:653
T pow(T... args)
T tan(T... args)
T isnan(T... args)
T sqrt(T... args)
table::Key< int > transform
STL class.
#define LOG_GET(logger)
void setCommonTangentPoint(Point const &commonTangentPoint)
Sets the common tangent point and computes necessary transforms.
Definition: CcdImage.cc:133
#define LOGLS_WARN(logger, message)
std::unique_ptr< Gtransfo > gtransfoCompose(Gtransfo const &left, Gtransfo const &right)
Returns a pointer to a composition of gtransfos, representing left(right()).
Definition: Gtransfo.cc:384