LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
Transform.cc
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  * Copyright 2008-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 #include <memory>
24 #include <iostream>
25 #include <sstream>
26 #include <vector>
27 
28 #include "astshim.h"
31 #include "lsst/afw/geom/Endpoint.h"
33 #include "lsst/afw/geom/SkyWcs.h"
38 
39 namespace lsst {
40 namespace afw {
41 namespace geom {
42 
43 template <class FromEndpoint, class ToEndpoint>
45  : _fromEndpoint(mapping.getNIn()),
46  _mapping(simplify ? mapping.simplified() : mapping.copy()),
47  _toEndpoint(mapping.getNOut()) {}
48 
49 template <typename FromEndpoint, typename ToEndpoint>
51  : _fromEndpoint(frameSet.getNIn()), _mapping(), _toEndpoint(frameSet.getNOut()) {
52  auto frameSetCopy = frameSet.copy();
53  // Normalize the base and current frame in a way that affects its behavior as a mapping.
54  // To do this one must set the current frame to the frame to be normalized
55  // and normalize the frame set as a frame (i.e. normalize the frame "in situ").
56  // The obvious alternative of normalizing a shallow copy of the frame does not work;
57  // the frame is altered but not the associated mapping!
58 
59  // Normalize the current frame by normalizing the frameset as a frame
60  _toEndpoint.normalizeFrame(frameSetCopy);
61 
62  // Normalize the base frame by temporarily making it the current frame,
63  // normalizing the frameset as a frame, then making it the base frame again
64  const int baseIndex = frameSetCopy->getBase();
65  const int currentIndex = frameSetCopy->getCurrent();
66  frameSetCopy->setCurrent(baseIndex);
67  _fromEndpoint.normalizeFrame(frameSetCopy);
68  frameSetCopy->setBase(baseIndex);
69  frameSetCopy->setCurrent(currentIndex);
70  _mapping = simplify ? frameSetCopy->getMapping()->simplified() : frameSetCopy->getMapping();
71 }
72 
73 template <typename FromEndpoint, typename ToEndpoint>
75  : _fromEndpoint(mapping->getNIn()), _mapping(mapping), _toEndpoint(mapping->getNOut()) {}
76 
77 template <class FromEndpoint, class ToEndpoint>
78 typename ToEndpoint::Point Transform<FromEndpoint, ToEndpoint>::applyForward(
79  typename FromEndpoint::Point const &point) const {
80  auto const rawFromData = _fromEndpoint.dataFromPoint(point);
81  auto rawToData = _mapping->applyForward(rawFromData);
82  return _toEndpoint.pointFromData(rawToData);
83 }
84 
85 template <class FromEndpoint, class ToEndpoint>
86 typename ToEndpoint::Array Transform<FromEndpoint, ToEndpoint>::applyForward(
87  typename FromEndpoint::Array const &array) const {
88  auto const rawFromData = _fromEndpoint.dataFromArray(array);
89  auto rawToData = _mapping->applyForward(rawFromData);
90  return _toEndpoint.arrayFromData(rawToData);
91 }
92 
93 template <class FromEndpoint, class ToEndpoint>
94 typename FromEndpoint::Point Transform<FromEndpoint, ToEndpoint>::applyInverse(
95  typename ToEndpoint::Point const &point) const {
96  auto const rawFromData = _toEndpoint.dataFromPoint(point);
97  auto rawToData = _mapping->applyInverse(rawFromData);
98  return _fromEndpoint.pointFromData(rawToData);
99 }
100 
101 template <class FromEndpoint, class ToEndpoint>
102 typename FromEndpoint::Array Transform<FromEndpoint, ToEndpoint>::applyInverse(
103  typename ToEndpoint::Array const &array) const {
104  auto const rawFromData = _toEndpoint.dataFromArray(array);
105  auto rawToData = _mapping->applyInverse(rawFromData);
106  return _fromEndpoint.arrayFromData(rawToData);
107 }
108 
109 template <class FromEndpoint, class ToEndpoint>
111  auto inverse = std::dynamic_pointer_cast<ast::Mapping>(_mapping->inverted());
112  if (!inverse) {
113  // don't throw std::bad_cast because it doesn't let you provide debugging info
114  std::ostringstream buffer;
115  buffer << "Mapping.inverted() does not return a Mapping. Called from: " << _mapping;
117  }
118  return std::make_shared<Transform<ToEndpoint, FromEndpoint>>(*inverse);
119 }
120 
121 template <class FromEndpoint, class ToEndpoint>
123  int const nIn = _fromEndpoint.getNAxes();
124  int const nOut = _toEndpoint.getNAxes();
125  std::vector<double> const point = _fromEndpoint.dataFromPoint(x);
126 
127  Eigen::MatrixXd jacobian(nOut, nIn);
128  for (int i = 0; i < nOut; ++i) {
129  for (int j = 0; j < nIn; ++j) {
130  jacobian(i, j) = _mapping->rate(point, i + 1, j + 1);
131  }
132  }
133  return jacobian;
134 }
135 
136 template <class FromEndpoint, class ToEndpoint>
139  os << "Transform" << FromEndpoint::getClassPrefix() << "To" << ToEndpoint::getClassPrefix();
140  return os.str();
141 }
142 
143 template <class FromEndpoint, class ToEndpoint>
145  std::istream &is) {
146  return detail::readStream<Transform<FromEndpoint, ToEndpoint>>(is);
147 }
148 
149 template <class FromEndpoint, class ToEndpoint>
151  std::string &str) {
152  std::istringstream is(str);
154 }
155 
156 template <class FromEndpoint, class ToEndpoint>
158  detail::writeStream<Transform<FromEndpoint, ToEndpoint>>(*this, os);
159 }
160 
161 template <class FromEndpoint, class ToEndpoint>
164  writeStream(os);
165  return os.str();
166 }
167 
168 template <class FromEndpoint, class ToEndpoint>
169 template <class NextToEndpoint>
171  Transform<ToEndpoint, NextToEndpoint> const &next, bool simplify) const {
172  if (_toEndpoint.getNAxes() == next.getFromEndpoint().getNAxes()) {
173  auto nextMapping = next.getMapping();
174  auto combinedMapping = getMapping()->then(*next.getMapping());
175  if (simplify) {
176  return std::make_shared<Transform<FromEndpoint, NextToEndpoint>>(*combinedMapping.simplified());
177  } else {
178  return std::make_shared<Transform<FromEndpoint, NextToEndpoint>>(combinedMapping);
179  }
180  } else {
181  auto message = "Cannot match " + std::to_string(_toEndpoint.getNAxes()) + "-D to-endpoint to " +
182  std::to_string(next.getFromEndpoint().getNAxes()) + "-D from-endpoint.";
184  }
185 }
186 
187 template <class FromEndpoint, class ToEndpoint>
189  os << "Transform<" << transform.getFromEndpoint() << ", " << transform.getToEndpoint() << ">";
190  return os;
191 };
192 
193 namespace {
194 
195 class TransformPersistenceHelper {
196 public:
197  table::Schema schema;
198  table::Key<table::Array<std::uint8_t>> bytes;
199 
200  static TransformPersistenceHelper const &get() {
201  static TransformPersistenceHelper instance;
202  return instance;
203  }
204 
205  // No copying
206  TransformPersistenceHelper(TransformPersistenceHelper const &) = delete;
207  TransformPersistenceHelper &operator=(TransformPersistenceHelper const &) = delete;
208 
209  // No moving
210  TransformPersistenceHelper(TransformPersistenceHelper &&) = delete;
211  TransformPersistenceHelper &operator=(TransformPersistenceHelper &&) = delete;
212 
213 private:
214  TransformPersistenceHelper()
215  : schema(),
216  bytes(schema.addField<table::Array<std::uint8_t>>(
217  "bytes", "a bytestring containing the output of Transform.writeString", "")) {}
218 };
219 
220 template <typename FromEndpoint, typename ToEndpoint>
221 class TransformFactory : public table::io::PersistableFactory {
222 public:
223  explicit TransformFactory(std::string const &name) : table::io::PersistableFactory(name) {}
224 
225  std::shared_ptr<table::io::Persistable> read(InputArchive const &archive,
226  CatalogVector const &catalogs) const override {
227  auto const &keys = TransformPersistenceHelper::get();
228  LSST_ARCHIVE_ASSERT(catalogs.size() == 1u);
229  LSST_ARCHIVE_ASSERT(catalogs.front().size() == 1u);
230  LSST_ARCHIVE_ASSERT(catalogs.front().getSchema() == keys.schema);
231  auto const &record = catalogs.front().front();
232  std::string stringRep = formatters::bytesToString(record.get(keys.bytes));
234  }
235 };
236 
237 } // namespace
238 
239 template <class FromEndpoint, class ToEndpoint>
241  auto const &keys = TransformPersistenceHelper::get();
242  table::BaseCatalog cat = handle.makeCatalog(keys.schema);
244  record->set(keys.bytes, formatters::stringToBytes(writeString()));
245  handle.saveCatalog(cat);
246 }
247 
248 #define INSTANTIATE_OVERLOADS(FromEndpoint, ToEndpoint, NextToEndpoint) \
249  template std::shared_ptr<Transform<FromEndpoint, NextToEndpoint>> \
250  Transform<FromEndpoint, ToEndpoint>::then<NextToEndpoint>( \
251  Transform<ToEndpoint, NextToEndpoint> const &next, bool) const;
252 
253 #define INSTANTIATE_TRANSFORM(FromEndpoint, ToEndpoint) \
254  } /* namespace geom */ \
255  template std::shared_ptr<geom::Transform<geom::FromEndpoint, geom::ToEndpoint>> \
256  table::io::PersistableFacade<geom::Transform<geom::FromEndpoint, geom::ToEndpoint>>::dynamicCast( \
257  std::shared_ptr<table::io::Persistable> const &); \
258  namespace geom { \
259  template class Transform<FromEndpoint, ToEndpoint>; \
260  template std::ostream &operator<<<FromEndpoint, ToEndpoint>( \
261  std::ostream &os, Transform<FromEndpoint, ToEndpoint> const &transform); \
262  namespace { \
263  TransformFactory<FromEndpoint, ToEndpoint> registration##FromEndpoint##ToEndpoint( \
264  Transform<FromEndpoint, ToEndpoint>::getShortClassName()); \
265  } /* namespace */ \
266  INSTANTIATE_OVERLOADS(FromEndpoint, ToEndpoint, GenericEndpoint) \
267  INSTANTIATE_OVERLOADS(FromEndpoint, ToEndpoint, Point2Endpoint) \
268  INSTANTIATE_OVERLOADS(FromEndpoint, ToEndpoint, SpherePointEndpoint)
269 
270 // explicit instantiations
280 
281 } // namespace geom
282 } // namespace afw
283 } // namespace lsst
table::Key< std::string > name
Definition: Amplifier.cc:116
double x
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
std::ostream * os
Definition: Schema.cc:557
table::Key< table::Array< std::uint8_t > > frameSet
table::Key< int > transform
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
Definition: Persistable.h:48
#define INSTANTIATE_TRANSFORM(FromEndpoint, ToEndpoint)
Definition: Transform.cc:253
table::Schema schema
Definition: Transform.cc:197
table::Key< table::Array< std::uint8_t > > bytes
Definition: Transform.cc:198
A FrameSet consists of a set of one or more Frames (which describe coordinate systems),...
Definition: FrameSet.h:99
An abstract base class for objects which transform one set of coordinates to another.
Definition: Mapping.h:59
std::shared_ptr< Mapping > simplified() const
Return a simplied version of the mapping (which may be a compound Mapping such as a CmpMap).
Definition: Mapping.h:248
A generic endpoint for data in the format used by ast::Mapping.
Definition: Endpoint.h:226
An endpoint for lsst::geom::Point2D.
Definition: Endpoint.h:261
An endpoint for lsst::geom::SpherePoint.
Definition: Endpoint.h:315
Transform LSST spatial data, such as lsst::geom::Point2D and lsst::geom::SpherePoint,...
Definition: Transform.h:68
typename FromEndpoint::Point FromPoint
Definition: Transform.h:74
static std::shared_ptr< Transform< FromEndpoint, ToEndpoint > > readStream(std::istream &is)
Deserialize a Transform of this type from an input stream.
Definition: Transform.cc:144
FromPoint applyInverse(ToPoint const &point) const
Transform one point in the inverse direction ("to" to "from")
static std::string getShortClassName()
Return a short version of the class name with no punctuation.
Definition: Transform.cc:137
std::shared_ptr< Transform< ToEndpoint, FromEndpoint > > inverted() const
The inverse of this Transform.
Definition: Transform.cc:110
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
Definition: Transform.cc:240
Eigen::MatrixXd getJacobian(FromPoint const &x) const
The Jacobian matrix of this Transform.
Definition: Transform.cc:122
std::string writeString() const
Serialize this Transform to a string, using the same format as writeStream.
Definition: Transform.cc:162
Transform(Transform const &)=default
static std::shared_ptr< Transform< FromEndpoint, ToEndpoint > > readString(std::string &str)
Deserialize a Transform of this type from a string, using the same format as readStream.
Definition: Transform.cc:150
std::shared_ptr< Transform< FromEndpoint, NextToEndpoint > > then(Transform< ToEndpoint, NextToEndpoint > const &next, bool simplify=true) const
Concatenate two Transforms.
Definition: Transform.cc:170
ToPoint applyForward(FromPoint const &point) const
Transform one point in the forward direction ("from" to "to")
void writeStream(std::ostream &os) const
Serialize this Transform to an output stream.
Definition: Transform.cc:157
std::shared_ptr< RecordT > addNew()
Create a new record, add it to the end of the catalog, and return a pointer to it.
Definition: Catalog.h:490
An object passed to Persistable::write to allow it to persist itself.
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
Reports invalid arguments.
Definition: Runtime.h:66
Reports errors in the logical structure of the program.
Definition: Runtime.h:46
ndarray::Array< std::uint8_t, 1, 1 > stringToBytes(std::string const &str)
Encode a std::string as a vector of uint8.
Definition: Utils.cc:161
std::string bytesToString(ndarray::Array< std::uint8_t const, 1, 1 > const &bytes)
Decode a std::string from a vector of uint8 returned by stringToBytes.
Definition: Utils.cc:172
void writeStream(Transform const &transform, std::ostream &os)
Serialize a Transform to an output stream.
std::ostream & operator<<(std::ostream &os, GenericEndpoint const &endpoint)
Print "GenericEndpoint(_n_)" to the ostream where _n_ is the number of axes, e.g. "GenericAxes(4)".
Definition: Endpoint.cc:239
FilterProperty & operator=(FilterProperty const &)=default
PolynomialFunction1d simplified(ScaledPolynomialFunction1d const &f)
Calculate the standard polynomial function that is equivalent to a scaled standard polynomial functio...
A base class for image defects.
STL namespace.
T str(T... args)
T to_string(T... args)
std::shared_ptr< table::io::Persistable > read(table::io::InputArchive const &archive, table::io::CatalogVector const &catalogs) const override
Definition: warpExposure.cc:0