LSSTApplications  11.0-24-g0a022a1,15.0+8,15.0+9,15.0-1-g19261fa+1,15.0-1-g1eca518+10,15.0-1-g60afb23+8,15.0-1-g615e0bb,15.0-1-g6668b0b+5,15.0-1-g788a293+8,15.0-1-ga91101e+8,15.0-1-gae1598d+7,15.0-1-gc45031d+10,15.0-1-gd076f1f+8,15.0-1-gdf18595+1,15.0-1-gf4f1c34+7,15.0-18-g5f205baaa,15.0-2-g100d730+1,15.0-2-g18f3f21,15.0-2-g35685a8+1,15.0-2-g947dc0d+10,15.0-2-ge3d7f4b+1,15.0-2-gf38729e,15.0-3-g150fc43+9,15.0-3-g6f085af+1,15.0-3-g9103c06+7,15.0-3-ga03b4ca+10,15.0-3-gaec6799+5,15.0-3-gb7a597c+8,15.0-3-ge6a6747,15.0-4-g45f767a+7,15.0-4-g654b129+6,15.0-4-gff20472+11,15.0-5-g389937dc+6,15.0-5-ga70c291+1,15.0-6-gbad5ef12+1,15.0-6-ge2d9597+10
LSSTDataManagementBasePackage
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  GtransfoPoly pol(chipDegree);
56 
57  if (initFromWCS) {
58  pol = GtransfoPoly(im.getPix2TangentPlane(), frame, chipDegree);
59  }
60  GtransfoLin shiftAndNormalize = normalizeCoordinatesTransfo(frame);
61 
62  _chipMap[chip] = std::unique_ptr<SimplePolyMapping>(
63  new SimplePolyMapping(shiftAndNormalize, pol * shiftAndNormalize.invert()));
64  }
65  }
66  // now, second loop to set the mappings of the CCdImages
67  for (auto &ccdImage : ccdImageList) {
68  const CcdImage &im = *ccdImage;
69  auto visit = im.getVisit();
70  auto chip = im.getCcdId();
71  // check that the chip_indexed part was indeed assigned
72  // (i.e. the reference visit was complete)
73  if (_chipMap.find(chip) == _chipMap.end()) {
74  LOGLS_WARN(_log, "Chip " << chip << " is missing in the reference exposure, expect troubles.");
76  _chipMap[chip] =
78  }
79  _mappings[&im] = std::unique_ptr<TwoTransfoMapping>(
80  new TwoTransfoMapping(_chipMap[chip].get(), _visitMap[visit].get()));
81  }
82  LOGLS_INFO(_log, "Constructor got " << _chipMap.size() << " chip mappings and " << _visitMap.size()
83  << " visit mappings.");
84  // DEBUG
85  for (auto i = _visitMap.begin(); i != _visitMap.end(); ++i) LOGLS_DEBUG(_log, i->first);
86 }
87 
89  mappingMapType::const_iterator i = _mappings.find(&ccdImage);
90  if (i == _mappings.end()) return nullptr;
91  return (i->second.get());
92 }
93 
98 unsigned ConstrainedPolyModel::assignIndices(unsigned firstIndex, std::string const &whatToFit) {
99  unsigned index = firstIndex;
100  if (whatToFit.find("Distortions") == std::string::npos) {
101  LOGLS_ERROR(_log, "assignIndices was called and Distortions is *not* in whatToFit");
102  return 0;
103  }
104  // if we get here "Distortions" is in whatToFit
105  _fittingChips = (whatToFit.find("DistortionsChip") != std::string::npos);
106  _fittingVisits = (whatToFit.find("DistortionsVisit") != std::string::npos);
107  // If nothing more than "Distortions" is specified, it means all:
108  if ((!_fittingChips) && (!_fittingVisits)) {
109  _fittingChips = _fittingVisits = true;
110  }
111  if (_fittingChips)
112  for (auto &i : _chipMap) {
113  i.second->setIndex(index);
114  index += i.second->getNpar();
115  }
116  if (_fittingVisits)
117  for (auto &i : _visitMap) {
118  i.second->setIndex(index);
119  index += i.second->getNpar();
120  }
121  // Tell the mappings which derivatives they will have to fill:
122  for (auto &i : _mappings) {
123  i.second->setWhatToFit(_fittingChips, _fittingVisits);
124  }
125  return index;
126 }
127 
128 void ConstrainedPolyModel::offsetParams(Eigen::VectorXd const &delta) {
129  if (_fittingChips)
130  for (auto &i : _chipMap) {
131  auto mapping = i.second.get();
132  mapping->offsetParams(delta.segment(mapping->getIndex(), mapping->getNpar()));
133  }
134  if (_fittingVisits)
135  for (auto &i : _visitMap) {
136  auto mapping = i.second.get();
137  mapping->offsetParams(delta.segment(mapping->getIndex(), mapping->getNpar()));
138  }
139 }
140 
142  for (auto i = _visitMap.begin(); i != _visitMap.end(); ++i) i->second->freezeErrorTransform();
143  for (auto i = _chipMap.begin(); i != _chipMap.end(); ++i) i->second->freezeErrorTransform();
144 }
145 
147  auto chipp = _chipMap.find(chip);
148  if (chipp == _chipMap.end()) {
149  std::stringstream errMsg;
150  errMsg << "No such chipId: '" << chip << "' found in chipMap of: " << this;
151  throw pexExcept::InvalidParameterError(errMsg.str());
152  }
153  return chipp->second->getTransfo();
154 }
155 
156 // Array of visits involved in the solution.
159  res.reserve(_visitMap.size());
160  for (auto i = _visitMap.begin(); i != _visitMap.end(); ++i) res.push_back(i->first);
161  return res;
162 }
163 
165  auto visitp = _visitMap.find(visit);
166  if (visitp == _visitMap.end()) {
167  std::stringstream errMsg;
168  errMsg << "No such visitId: '" << visit << "' found in visitMap of: " << this;
169  throw pexExcept::InvalidParameterError(errMsg.str());
170  }
171  return visitp->second->getTransfo();
172 }
173 
175  const TwoTransfoMapping *mapping;
176  try {
177  mapping = _mappings.at(&ccdImage).get();
178  } catch (std::out_of_range &) {
179  LOGLS_ERROR(_log, "CcdImage with ccd/visit " << ccdImage.getCcdId() << "/" << ccdImage.getVisit()
180  << " not found in constrainedPolyModel mapping list.");
182  for (auto const &i : _mappings) os << i.first << ",";
183  LOGLS_ERROR(_log, "Available CcdImages: " << os.str());
184  return nullptr;
185  }
186 
187  GtransfoPoly pix2Tp;
188  const GtransfoPoly &t1 = dynamic_cast<const GtransfoPoly &>(mapping->getTransfo1());
189  // TODO: This line produces a warning on clang (t1 is always valid: a failed dynamic_cast of a reference
190  // raises bad_cast instead of returning nullptr like a failed pointer cast), but I'll deal with it as
191  // part of DM-10524 (hopefully removing the necessity of the casts).
192  if (!(&t1)) {
193  LOGLS_ERROR(_log, "Problem with transform 1 of ccd/visit " << ccdImage.getCcdId() << "/"
194  << ccdImage.getVisit() << ": T1 "
195  << mapping->getTransfo1());
196  return nullptr;
197  }
198  // NOTE: we currently expect T2 to be an identity for the first visit, so we have to treat it separately.
199  // TODO: We are aware that this is a hack, but it will be fixed as part of DM-10524.
200  try {
201  const GtransfoIdentity &t2 = dynamic_cast<const GtransfoIdentity &>(mapping->getTransfo2());
202  pix2Tp = t1;
203  } catch (std::bad_cast &) {
204  try {
205  const GtransfoPoly &t2_poly = dynamic_cast<const GtransfoPoly &>(mapping->getTransfo2());
206  pix2Tp = t2_poly * t1;
207  } catch (std::bad_cast &) {
208  LOGLS_ERROR(_log, "Problem with transform 2 of ccd/visit " << ccdImage.getCcdId() << "/"
209  << ccdImage.getVisit() << ": T2 "
210  << mapping->getTransfo2());
211  return nullptr;
212  }
213  }
214  const TanRaDec2Pix *proj = dynamic_cast<const TanRaDec2Pix *>(getSky2TP(ccdImage));
215  if (!proj) {
216  LOGLS_ERROR(_log, "Problem with projection of ccd/visit " << ccdImage.getCcdId() << "/"
217  << ccdImage.getVisit() << ": projection "
218  << getSky2TP(ccdImage));
219  return nullptr;
220  }
221 
222  // should be the identity, but who knows? So, let us incorporate it into the pix2TP part.
223  const GtransfoLin &projLinPart = proj->getLinPart();
224  GtransfoPoly wcsPix2Tp = GtransfoPoly(projLinPart.invert()) * pix2Tp;
225 
226  // compute a decent approximation, if higher order corrections get ignored
227  GtransfoLin cdStuff = wcsPix2Tp.linearApproximation(ccdImage.getImageFrame().getCenter());
228 
229  // wcsPix2TP = cdStuff*sip , so
230  GtransfoPoly sip = GtransfoPoly(cdStuff.invert()) * wcsPix2Tp;
231  Point tangentPoint(proj->getTangentPoint());
232  return std::make_shared<TanSipPix2RaDec>(cdStuff, tangentPoint, &sip);
233 }
234 } // namespace jointcal
235 } // namespace lsst
#define LOGLS_WARN(logger, message)
Log a warn-level message using an iostream-based interface.
Definition: Log.h:657
VisitIdType getVisit() const
returns visit ID
Definition: CcdImage.h:102
implements the linear transformations (6 real coefficients).
Definition: Gtransfo.h:294
#define LOG_LOGGER
Definition: Log.h:712
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:1090
Mapping implementation for a polynomial transformation.
T norm(const T &x)
Definition: Integrate.h:194
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:99
The mapping with two transfos in a row.
STL class.
Gtransfo const * getPix2TangentPlane() const
Definition: CcdImage.h:93
Polynomial transformation class.
Definition: Gtransfo.h:195
GtransfoLin normalizeCoordinatesTransfo(const Frame &frame)
Returns the transformation that maps the input frame along both axes to [-1,1].
Definition: Gtransfo.cc:725
STL class.
LSST DM logging module built on log4cxx.
T at(T... args)
T push_back(T... args)
rectangle with sides parallel to axes.
Definition: Frame.h:19
#define LOGLS_DEBUG(logger, message)
Log a debug-level message using an iostream-based interface.
Definition: Log.h:617
A base class for image defects.
Definition: cameraGeom.dox:3
std::shared_ptr< TanSipPix2RaDec > produceSipWcs(CcdImage const &ccdImage) const
Cook up a SIP WCS.
void freezeErrorTransform()
From there on, measurement errors are propagated using the current transfos (and no longer evolve)...
Point getTangentPoint() const
tangent point coordinates (degrees)
Definition: Gtransfo.cc:1481
T str(T... args)
Include files required for standard LSST Exception handling.
This is a virtual class that allows a lot of freedom in the choice of the projection from "Sky" (wher...
#define LOGLS_INFO(logger, message)
Log a info-level message using an iostream-based interface.
Definition: Log.h:637
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:152
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:93
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:554
T begin(T... args)
GtransfoLin getLinPart() const
The Linear part (corresponding to CD&#39;s and CRPIX&#39;s)
Definition: Gtransfo.cc:1483
a virtual (interface) class for geometric transformations.
Definition: Gtransfo.h:41
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.
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:35
#define LOG_GET(logger)
Returns a Log object associated with logger.
Definition: Log.h:83
Gtransfo const & getTransfo1() const
access to transfos
Gtransfo const & getTransfo2() const
access to transfos
#define LOGLS_ERROR(logger, message)
Log a error-level message using an iostream-based interface.
Definition: Log.h:677
Frame const & getImageFrame() const
Frame in pixels.
Definition: CcdImage.h:144
std::ostream * os
Definition: Schema.cc:736
T reserve(T... args)
Gtransfo const & getChipTransfo(CcdIdType const chip) const
Access to mappings.