lsst.jointcal  14.0-15-gc2c14a3
ConstrainedPolyModel.cc
Go to the documentation of this file.
1 #include "lsst/log/Log.h"
8 #include "lsst/jointcal/AstroUtils.h" // applyTransfo(Frame)
9 
10 #include "lsst/pex/exceptions.h"
12 
13 #include <string>
14 #include <iostream>
15 
16 namespace {
17 LOG_LOGGER _log = LOG_GET("jointcal.ConstrainedPolyModel");
18 }
19 
20 namespace lsst {
21 namespace jointcal {
22 
23 /* This code does not contain anything involved. It just maps the
24 routines AstrometryFit needs to what is needed for this two-transfo model.
25 The two-transfo mappings are implemented using two one-transfo
26 mappings.*/
27 
28 using namespace std;
29 
30 ConstrainedPolyModel::ConstrainedPolyModel(CcdImageList const &ccdImageList,
31  ProjectionHandler const *projectionHandler, bool initFromWCS,
32  unsigned nNotFit, int chipDegree, int visitDegree)
33  : _sky2TP(projectionHandler)
34 
35 {
36  // first loop to initialize all visit and chip transfos.
37  for (auto &ccdImage : ccdImageList) {
38  const CcdImage &im = *ccdImage;
39  auto visit = im.getVisit();
40  auto chip = im.getCcdId();
41  auto visitp = _visitMap.find(visit);
42  if (visitp == _visitMap.end()) {
43  if (_visitMap.size() == 0) {
44  _visitMap[visit] =
46  } else {
47  _visitMap[visit] = std::unique_ptr<SimpleGtransfoMapping>(
48  new SimplePolyMapping(GtransfoLin(), GtransfoPoly(visitDegree)));
49  }
50  }
51  auto chipp = _chipMap.find(chip);
52  if (chipp == _chipMap.end()) {
53  const Frame &frame = im.getImageFrame();
54 
55  _tpFrame += applyTransfo(frame, *im.getPix2CommonTangentPlane(), LargeFrame);
56  GtransfoPoly pol(im.getPix2TangentPlane(), frame, chipDegree);
57  GtransfoLin shiftAndNormalize = normalizeCoordinatesTransfo(frame);
58 
59  _chipMap[chip] = std::unique_ptr<SimplePolyMapping>(
60  new SimplePolyMapping(shiftAndNormalize, pol * shiftAndNormalize.invert()));
61  }
62  }
63  // now, second loop to set the mappings of the CCdImages
64  for (auto &ccdImage : ccdImageList) {
65  const CcdImage &im = *ccdImage;
66  auto visit = im.getVisit();
67  auto chip = im.getCcdId();
68  // check that the chip_indexed part was indeed assigned
69  // (i.e. the reference visit was complete)
70  if (_chipMap.find(chip) == _chipMap.end()) {
71  LOGLS_WARN(_log, "Chip " << chip << " is missing in the reference exposure, expect troubles.");
73  _chipMap[chip] =
75  }
76  _mappings[&im] = std::unique_ptr<TwoTransfoMapping>(
77  new TwoTransfoMapping(_chipMap[chip].get(), _visitMap[visit].get()));
78  }
79  LOGLS_INFO(_log, "Constructor got " << _chipMap.size() << " chip mappings and " << _visitMap.size()
80  << " visit mappings.");
81  // DEBUG
82  for (auto i = _visitMap.begin(); i != _visitMap.end(); ++i) LOGLS_DEBUG(_log, i->first);
83 }
84 
86  mappingMapType::const_iterator i = _mappings.find(&ccdImage);
87  if (i == _mappings.end()) return nullptr;
88  return (i->second.get());
89 }
90 
95 unsigned ConstrainedPolyModel::assignIndices(unsigned firstIndex, std::string const &whatToFit) {
96  unsigned index = firstIndex;
97  if (whatToFit.find("Distortions") == std::string::npos) {
98  LOGLS_ERROR(_log, "assignIndices was called and Distortions is *not* in whatToFit");
99  return 0;
100  }
101  // if we get here "Distortions" is in whatToFit
102  _fittingChips = (whatToFit.find("DistortionsChip") != std::string::npos);
103  _fittingVisits = (whatToFit.find("DistortionsVisit") != std::string::npos);
104  // If nothing more than "Distortions" is specified, it means all:
105  if ((!_fittingChips) && (!_fittingVisits)) {
106  _fittingChips = _fittingVisits = true;
107  }
108  if (_fittingChips)
109  for (auto &i : _chipMap) {
110  i.second->setIndex(index);
111  index += i.second->getNpar();
112  }
113  if (_fittingVisits)
114  for (auto &i : _visitMap) {
115  i.second->setIndex(index);
116  index += i.second->getNpar();
117  }
118  // Tell the mappings which derivatives they will have to fill:
119  for (auto &i : _mappings) {
120  i.second->setWhatToFit(_fittingChips, _fittingVisits);
121  }
122  return index;
123 }
124 
125 void ConstrainedPolyModel::offsetParams(Eigen::VectorXd const &delta) {
126  if (_fittingChips)
127  for (auto &i : _chipMap) {
128  auto mapping = i.second.get();
129  mapping->offsetParams(delta.segment(mapping->getIndex(), mapping->getNpar()));
130  }
131  if (_fittingVisits)
132  for (auto &i : _visitMap) {
133  auto mapping = i.second.get();
134  mapping->offsetParams(delta.segment(mapping->getIndex(), mapping->getNpar()));
135  }
136 }
137 
139  for (auto i = _visitMap.begin(); i != _visitMap.end(); ++i) i->second->freezeErrorScales();
140  for (auto i = _chipMap.begin(); i != _chipMap.end(); ++i) i->second->freezeErrorScales();
141 }
142 
144  auto chipp = _chipMap.find(chip);
145  if (chipp == _chipMap.end()) {
146  std::stringstream errMsg;
147  errMsg << "No such chipId: '" << chip << "' found in chipMap of: " << this;
148  throw pexExcept::InvalidParameterError(errMsg.str());
149  }
150  return chipp->second->getTransfo();
151 }
152 
153 // Array of visits involved in the solution.
156  res.reserve(_visitMap.size());
157  for (auto i = _visitMap.begin(); i != _visitMap.end(); ++i) res.push_back(i->first);
158  return res;
159 }
160 
162  auto visitp = _visitMap.find(visit);
163  if (visitp == _visitMap.end()) {
164  std::stringstream errMsg;
165  errMsg << "No such visitId: '" << visit << "' found in visitMap of: " << this;
166  throw pexExcept::InvalidParameterError(errMsg.str());
167  }
168  return visitp->second->getTransfo();
169 }
170 
172  const TwoTransfoMapping *mapping;
173  try {
174  mapping = _mappings.at(&ccdImage).get();
175  } catch (std::out_of_range &) {
176  LOGLS_ERROR(_log, "CcdImage with ccd/visit " << ccdImage.getCcdId() << "/" << ccdImage.getVisit()
177  << " not found in constrainedPolyModel mapping list.");
179  for (auto const &i : _mappings) os << i.first << ",";
180  LOGLS_ERROR(_log, "Available CcdImages: " << os.str());
181  return nullptr;
182  }
183 
184  GtransfoPoly pix2Tp;
185  const GtransfoPoly &t1 = dynamic_cast<const GtransfoPoly &>(mapping->getTransfo1());
186  // TODO: This line produces a warning on clang (t1 is always valid: a failed dynamic_cast of a reference
187  // raises bad_cast instead of returning nullptr like a failed pointer cast), but I'll deal with it as
188  // part of DM-10524 (hopefully removing the necessity of the casts).
189  if (!(&t1)) {
190  LOGLS_ERROR(_log, "Problem with transform 1 of ccd/visit " << ccdImage.getCcdId() << "/"
191  << ccdImage.getVisit() << ": T1 "
192  << mapping->getTransfo1());
193  return nullptr;
194  }
195  // NOTE: we currently expect T2 to be an identity for the first visit, so we have to treat it separately.
196  // TODO: We are aware that this is a hack, but it will be fixed as part of DM-10524.
197  try {
198  const GtransfoIdentity &t2 = dynamic_cast<const GtransfoIdentity &>(mapping->getTransfo2());
199  pix2Tp = t1;
200  } catch (std::bad_cast &) {
201  try {
202  const GtransfoPoly &t2_poly = dynamic_cast<const GtransfoPoly &>(mapping->getTransfo2());
203  pix2Tp = t2_poly * t1;
204  } catch (std::bad_cast &) {
205  LOGLS_ERROR(_log, "Problem with transform 2 of ccd/visit " << ccdImage.getCcdId() << "/"
206  << ccdImage.getVisit() << ": T2 "
207  << mapping->getTransfo2());
208  return nullptr;
209  }
210  }
211  const TanRaDec2Pix *proj = dynamic_cast<const TanRaDec2Pix *>(getSky2TP(ccdImage));
212  if (!proj) {
213  LOGLS_ERROR(_log, "Problem with projection of ccd/visit " << ccdImage.getCcdId() << "/"
214  << ccdImage.getVisit() << ": projection "
215  << getSky2TP(ccdImage));
216  return nullptr;
217  }
218 
219  // should be the identity, but who knows? So, let us incorporate it into the pix2TP part.
220  const GtransfoLin &projLinPart = proj->getLinPart();
221  GtransfoPoly wcsPix2Tp = GtransfoPoly(projLinPart.invert()) * pix2Tp;
222 
223  // compute a decent approximation, if higher order corrections get ignored
224  GtransfoLin cdStuff = wcsPix2Tp.linearApproximation(ccdImage.getImageFrame().getCenter());
225 
226  // wcsPix2TP = cdStuff*sip , so
227  GtransfoPoly sip = GtransfoPoly(cdStuff.invert()) * wcsPix2Tp;
228  Point tangentPoint(proj->getTangentPoint());
229  return std::make_shared<TanSipPix2RaDec>(cdStuff, tangentPoint, &sip);
230 }
231 } // namespace jointcal
232 } // namespace lsst
VisitIdType getVisit() const
returns visit ID
Definition: CcdImage.h:101
implements the linear transformations (6 real coefficients).
Definition: Gtransfo.h:292
void offsetParams(Eigen::VectorXd const &Delta)
Dispaches the offsets after a fit step into the actual locations of parameters.
virtual class needed in the abstraction of the distortion model
Definition: Mapping.h:15
A point in a plane.
Definition: Point.h:13
GtransfoLin invert() const
returns the inverse: T1 = T2.invert();
Definition: Gtransfo.cc:1089
Mapping implementation for a polynomial transformation.
Gtransfo const * getPix2CommonTangentPlane() const
Definition: CcdImage.h:83
T norm(const T &x)
STL namespace.
Gtransfo const & getVisitTransfo(VisitIdType const &visit) const
Access to mappings.
T end(T... args)
CcdIdType getCcdId() const
returns ccd ID
Definition: CcdImage.h:98
The mapping with two transfos in a row.
STL class.
Gtransfo const * getPix2TangentPlane() const
Definition: CcdImage.h:92
Polynomial transformation class.
Definition: Gtransfo.h:193
GtransfoLin normalizeCoordinatesTransfo(const Frame &frame)
Returns the transformation that maps the input frame along both axes to [-1,1].
Definition: Gtransfo.cc:724
#define LOGLS_INFO(logger, message)
STL class.
T at(T... args)
T push_back(T... args)
rectangle with sides parallel to axes.
Definition: Frame.h:19
Class for a simple mapping implementing a generic Gtransfo.
std::shared_ptr< TanSipPix2RaDec > produceSipWcs(CcdImage const &ccdImage) const
Cook up a SIP WCS.
Point getTangentPoint() const
tangent point coordinates (in degrees)
Definition: Gtransfo.cc:1459
T str(T... args)
This is a virtual class that allows a lot of freedom in the choice of the projection from "Sky" (wher...
T get(T... args)
Point getCenter() const
Center of the frame.
Definition: Frame.h:41
A do-nothing transformation. It anyway has dummy routines to mimick a Gtransfo.
Definition: Gtransfo.h:150
T find(T... args)
T size(T... args)
virtual GtransfoLin linearApproximation(const Point &where, const double step=0.01) const
linear (local) approximation.
Definition: Gtransfo.cc:92
STL class.
std::vector< VisitIdType > getVisits() const
Access to array of visits involved in the solution.
This one is the Tangent Plane (called gnomonic) projection (from celestial sphere to tangent plane) ...
Definition: Gtransfo.h:517
T begin(T... args)
GtransfoLin getLinPart() const
The Linear part (corresponding to CD&#39;s and CRPIX&#39;s)
Definition: Gtransfo.cc:1461
a virtual (interface) class for geometric transformations.
Definition: Gtransfo.h:39
#define LOGLS_DEBUG(logger, message)
Mapping const * getMapping(CcdImage const &) const
Mapping associated to a given CcdImage.
const Gtransfo * getSky2TP(CcdImage const &ccdImage) const
The mapping of sky coordinates (i.e.
Frame applyTransfo(const Frame &inputframe, const Gtransfo &gtransfo, const WhichTransformed which)
Transform a Frame through a Transfo.
Definition: AstroUtils.cc:15
int VisitIdType
Definition: CcdImage.h:25
unsigned assignIndices(unsigned firstIndex, std::string const &whatToFit)
Positions the various parameter sets into the parameter vector, starting at firstIndex.
Handler of an actual image from a single CCD.
Definition: CcdImage.h:34
Gtransfo const & getTransfo1() const
access to transfos
Gtransfo const & getTransfo2() const
access to transfos
#define LOG_GET(logger)
Frame const & getImageFrame() const
Frame in pixels.
Definition: CcdImage.h:146
#define LOGLS_ERROR(logger, message)
#define LOGLS_WARN(logger, message)
T reserve(T... args)
void freezeErrorScales()
From there on, measurement errors are propagated using the current transfos (and no longer evolve)...
Gtransfo const & getChipTransfo(CcdIdType const chip) const
Access to mappings.