LSSTApplications  21.0.0+75b29a8a7f,21.0.0+e70536a077,21.0.0-1-ga51b5d4+62c747d40b,21.0.0-11-ga6ea59e8e+47cba9fc36,21.0.0-2-g103fe59+914993bf7c,21.0.0-2-g1367e85+e2614ded12,21.0.0-2-g45278ab+e70536a077,21.0.0-2-g4bc9b9f+7b2b5f8678,21.0.0-2-g5242d73+e2614ded12,21.0.0-2-g54e2caa+6403186824,21.0.0-2-g7f82c8f+3ac4acbffc,21.0.0-2-g8dde007+04a6aea1af,21.0.0-2-g8f08a60+9402881886,21.0.0-2-ga326454+3ac4acbffc,21.0.0-2-ga63a54e+81dd751046,21.0.0-2-gc738bc1+5f65c6e7a9,21.0.0-2-gde069b7+26c92b3210,21.0.0-2-gecfae73+0993ddc9bd,21.0.0-2-gfc62afb+e2614ded12,21.0.0-21-gba890a8+5a4f502a26,21.0.0-23-g9966ff26+03098d1af8,21.0.0-3-g357aad2+8ad216c477,21.0.0-3-g4be5c26+e2614ded12,21.0.0-3-g6d51c4a+4d2fe0280d,21.0.0-3-g7d9da8d+75b29a8a7f,21.0.0-3-gaa929c8+522e0f12c2,21.0.0-3-ge02ed75+4d2fe0280d,21.0.0-4-g3300ddd+e70536a077,21.0.0-4-gc004bbf+eac6615e82,21.0.0-4-gccdca77+f94adcd104,21.0.0-4-gd1c1571+18b81799f9,21.0.0-5-g7b47fff+4d2fe0280d,21.0.0-5-gb155db7+d2632f662b,21.0.0-5-gdf36809+637e4641ee,21.0.0-6-g722ad07+28c848f42a,21.0.0-7-g959bb79+522e0f12c2,21.0.0-7-gfd72ab2+cf01990774,21.0.0-9-g87fb7b8d+e2ab11cdd6,w.2021.04
LSSTDataManagementBasePackage
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 <exception>
24 #include <memory>
25 #include <ostream>
26 #include <sstream>
27 #include <vector>
28 
29 #include "astshim.h"
32 #include "lsst/afw/geom/Endpoint.h"
34 #include "lsst/afw/geom/SkyWcs.h"
39 
40 namespace lsst {
41 namespace afw {
42 namespace geom {
43 
44 template <class FromEndpoint, class ToEndpoint>
46  : _fromEndpoint(mapping.getNIn()),
47  _mapping(simplify ? mapping.simplified() : mapping.copy()),
48  _toEndpoint(mapping.getNOut()) {}
49 
50 template <typename FromEndpoint, typename ToEndpoint>
52  : _fromEndpoint(frameSet.getNIn()), _mapping(), _toEndpoint(frameSet.getNOut()) {
53  auto frameSetCopy = frameSet.copy();
54  // Normalize the base and current frame in a way that affects its behavior as a mapping.
55  // To do this one must set the current frame to the frame to be normalized
56  // and normalize the frame set as a frame (i.e. normalize the frame "in situ").
57  // The obvious alternative of normalizing a shallow copy of the frame does not work;
58  // the frame is altered but not the associated mapping!
59 
60  // Normalize the current frame by normalizing the frameset as a frame
61  _toEndpoint.normalizeFrame(frameSetCopy);
62 
63  // Normalize the base frame by temporarily making it the current frame,
64  // normalizing the frameset as a frame, then making it the base frame again
65  const int baseIndex = frameSetCopy->getBase();
66  const int currentIndex = frameSetCopy->getCurrent();
67  frameSetCopy->setCurrent(baseIndex);
68  _fromEndpoint.normalizeFrame(frameSetCopy);
69  frameSetCopy->setBase(baseIndex);
70  frameSetCopy->setCurrent(currentIndex);
71  _mapping = simplify ? frameSetCopy->getMapping()->simplified() : frameSetCopy->getMapping();
72 }
73 
74 template <typename FromEndpoint, typename ToEndpoint>
76  : _fromEndpoint(mapping->getNIn()), _mapping(mapping), _toEndpoint(mapping->getNOut()) {}
77 
78 template <class FromEndpoint, class ToEndpoint>
80  typename FromEndpoint::Point const &point) const {
81  auto const rawFromData = _fromEndpoint.dataFromPoint(point);
82  auto rawToData = _mapping->applyForward(rawFromData);
83  return _toEndpoint.pointFromData(rawToData);
84 }
85 
86 template <class FromEndpoint, class ToEndpoint>
88  typename FromEndpoint::Array const &array) const {
89  auto const rawFromData = _fromEndpoint.dataFromArray(array);
90  auto rawToData = _mapping->applyForward(rawFromData);
91  return _toEndpoint.arrayFromData(rawToData);
92 }
93 
94 template <class FromEndpoint, class ToEndpoint>
96  typename ToEndpoint::Point const &point) const {
97  auto const rawFromData = _toEndpoint.dataFromPoint(point);
98  auto rawToData = _mapping->applyInverse(rawFromData);
99  return _fromEndpoint.pointFromData(rawToData);
100 }
101 
102 template <class FromEndpoint, class ToEndpoint>
104  typename ToEndpoint::Array const &array) const {
105  auto const rawFromData = _toEndpoint.dataFromArray(array);
106  auto rawToData = _mapping->applyInverse(rawFromData);
107  return _fromEndpoint.arrayFromData(rawToData);
108 }
109 
110 template <class FromEndpoint, class ToEndpoint>
112  auto inverse = std::dynamic_pointer_cast<ast::Mapping>(_mapping->inverted());
113  if (!inverse) {
114  // don't throw std::bad_cast because it doesn't let you provide debugging info
115  std::ostringstream buffer;
116  buffer << "Mapping.inverted() does not return a Mapping. Called from: " << _mapping;
118  }
119  return std::make_shared<Transform<ToEndpoint, FromEndpoint>>(*inverse);
120 }
121 
122 template <class FromEndpoint, class ToEndpoint>
124  int const nIn = _fromEndpoint.getNAxes();
125  int const nOut = _toEndpoint.getNAxes();
126  std::vector<double> const point = _fromEndpoint.dataFromPoint(x);
127 
128  Eigen::MatrixXd jacobian(nOut, nIn);
129  for (int i = 0; i < nOut; ++i) {
130  for (int j = 0; j < nIn; ++j) {
131  jacobian(i, j) = _mapping->rate(point, i + 1, j + 1);
132  }
133  }
134  return jacobian;
135 }
136 
137 template <class FromEndpoint, class ToEndpoint>
140  os << "Transform" << FromEndpoint::getClassPrefix() << "To" << ToEndpoint::getClassPrefix();
141  return os.str();
142 }
143 
144 template <class FromEndpoint, class ToEndpoint>
146  std::istream &is) {
147  return detail::readStream<Transform<FromEndpoint, ToEndpoint>>(is);
148 }
149 
150 template <class FromEndpoint, class ToEndpoint>
152  std::string &str) {
155 }
156 
157 template <class FromEndpoint, class ToEndpoint>
159  detail::writeStream<Transform<FromEndpoint, ToEndpoint>>(*this, os);
160 }
161 
162 template <class FromEndpoint, class ToEndpoint>
165  writeStream(os);
166  return os.str();
167 }
168 
169 template <class FromEndpoint, class ToEndpoint>
170 template <class NextToEndpoint>
172  Transform<ToEndpoint, NextToEndpoint> const &next, bool simplify) const {
173  if (_toEndpoint.getNAxes() == next.getFromEndpoint().getNAxes()) {
174  auto nextMapping = next.getMapping();
175  auto combinedMapping = getMapping()->then(*next.getMapping());
176  if (simplify) {
177  return std::make_shared<Transform<FromEndpoint, NextToEndpoint>>(*combinedMapping.simplified());
178  } else {
179  return std::make_shared<Transform<FromEndpoint, NextToEndpoint>>(combinedMapping);
180  }
181  } else {
182  auto message = "Cannot match " + std::to_string(_toEndpoint.getNAxes()) + "-D to-endpoint to " +
183  std::to_string(next.getFromEndpoint().getNAxes()) + "-D from-endpoint.";
185  }
186 }
187 
188 template <class FromEndpoint, class ToEndpoint>
190  os << "Transform<" << transform.getFromEndpoint() << ", " << transform.getToEndpoint() << ">";
191  return os;
192 };
193 
194 namespace {
195 
196 class TransformPersistenceHelper {
197 public:
198  table::Schema schema;
199  table::Key<table::Array<std::uint8_t>> bytes;
200 
201  static TransformPersistenceHelper const &get() {
202  static TransformPersistenceHelper instance;
203  return instance;
204  }
205 
206  // No copying
207  TransformPersistenceHelper(TransformPersistenceHelper const &) = delete;
208  TransformPersistenceHelper &operator=(TransformPersistenceHelper const &) = delete;
209 
210  // No moving
211  TransformPersistenceHelper(TransformPersistenceHelper &&) = delete;
212  TransformPersistenceHelper &operator=(TransformPersistenceHelper &&) = delete;
213 
214 private:
215  TransformPersistenceHelper()
216  : schema(),
217  bytes(schema.addField<table::Array<std::uint8_t>>(
218  "bytes", "a bytestring containing the output of Transform.writeString", "")) {}
219 };
220 
221 template <typename FromEndpoint, typename ToEndpoint>
222 class TransformFactory : public table::io::PersistableFactory {
223 public:
224  explicit TransformFactory(std::string const &name) : table::io::PersistableFactory(name) {}
225 
226  std::shared_ptr<table::io::Persistable> read(InputArchive const &archive,
227  CatalogVector const &catalogs) const override {
228  auto const &keys = TransformPersistenceHelper::get();
229  LSST_ARCHIVE_ASSERT(catalogs.size() == 1u);
230  LSST_ARCHIVE_ASSERT(catalogs.front().size() == 1u);
231  LSST_ARCHIVE_ASSERT(catalogs.front().getSchema() == keys.schema);
232  auto const &record = catalogs.front().front();
233  std::string stringRep = formatters::bytesToString(record.get(keys.bytes));
235  }
236 };
237 
238 } // namespace
239 
240 template <class FromEndpoint, class ToEndpoint>
242  auto const &keys = TransformPersistenceHelper::get();
243  table::BaseCatalog cat = handle.makeCatalog(keys.schema);
245  record->set(keys.bytes, formatters::stringToBytes(writeString()));
246  handle.saveCatalog(cat);
247 }
248 
249 #define INSTANTIATE_OVERLOADS(FromEndpoint, ToEndpoint, NextToEndpoint) \
250  template std::shared_ptr<Transform<FromEndpoint, NextToEndpoint>> \
251  Transform<FromEndpoint, ToEndpoint>::then<NextToEndpoint>( \
252  Transform<ToEndpoint, NextToEndpoint> const &next, bool) const;
253 
254 #define INSTANTIATE_TRANSFORM(FromEndpoint, ToEndpoint) \
255  } /* namespace geom */ \
256  template std::shared_ptr<geom::Transform<geom::FromEndpoint, geom::ToEndpoint>> \
257  table::io::PersistableFacade<geom::Transform<geom::FromEndpoint, geom::ToEndpoint>>::dynamicCast( \
258  std::shared_ptr<table::io::Persistable> const &); \
259  namespace geom { \
260  template class Transform<FromEndpoint, ToEndpoint>; \
261  template std::ostream &operator<<<FromEndpoint, ToEndpoint>( \
262  std::ostream &os, Transform<FromEndpoint, ToEndpoint> const &transform); \
263  namespace { \
264  TransformFactory<FromEndpoint, ToEndpoint> registration##FromEndpoint##ToEndpoint( \
265  Transform<FromEndpoint, ToEndpoint>::getShortClassName()); \
266  } /* namespace */ \
267  INSTANTIATE_OVERLOADS(FromEndpoint, ToEndpoint, GenericEndpoint) \
268  INSTANTIATE_OVERLOADS(FromEndpoint, ToEndpoint, Point2Endpoint) \
269  INSTANTIATE_OVERLOADS(FromEndpoint, ToEndpoint, SpherePointEndpoint)
270 
271 // explicit instantiations
281 
282 } // namespace geom
283 } // namespace afw
284 } // namespace lsst
lsst::afw::geom::Transform::write
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
Definition: Transform.cc:241
lsst::afw::geom::detail::writeStream
void writeStream(Transform const &transform, std::ostream &os)
Serialize a Transform to an output stream.
Definition: transformUtils.h:107
astshim.fitsChanContinued.next
def next(self)
Definition: fitsChanContinued.py:105
Persistable.cc
ast::FrameSet
A FrameSet consists of a set of one or more Frames (which describe coordinate systems),...
Definition: FrameSet.h:99
std::string
STL class.
std::shared_ptr< ast::Mapping >
ast::Mapping::simplified
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
lsst::afw::geom::Transform
Transform LSST spatial data, such as lsst::geom::Point2D and lsst::geom::SpherePoint,...
Definition: Transform.h:68
lsst::afw::table::io::OutputArchiveHandle
An object passed to Persistable::write to allow it to persist itself.
Definition: OutputArchive.h:118
std::vector< double >
ast::Mapping
An abstract base class for objects which transform one set of coordinates to another.
Definition: Mapping.h:59
lsst::afw::table::io::OutputArchiveHandle::saveCatalog
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
Definition: OutputArchive.cc:211
lsst::afw::geom::Transform::getShortClassName
static std::string getShortClassName()
Return a short version of the class name with no punctuation.
Definition: Transform.cc:138
lsst::afw
Definition: imageAlgorithm.dox:1
std::istringstream
STL class.
lsst::afw::geom::Transform::applyForward
ToPoint applyForward(FromPoint const &point) const
Transform one point in the forward direction ("from" to "to")
Definition: Transform.cc:79
astshim.keyMap.keyMapContinued.keys
def keys(self)
Definition: keyMapContinued.py:6
SkyWcs.h
CatalogVector.h
Endpoint.h
lsst::afw::geom.transform.transformContinued.name
string name
Definition: transformContinued.py:32
lsst::afw::geom::Point2Endpoint
An endpoint for lsst::geom::Point2D.
Definition: Endpoint.h:261
astshim.h
lsst::afw::table::io::OutputArchiveHandle::makeCatalog
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
Definition: OutputArchive.cc:207
lsst::afw::formatters::bytesToString
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:173
lsst::afw::geom::Transform::writeStream
void writeStream(std::ostream &os) const
Serialize this Transform to an output stream.
Definition: Transform.cc:158
lsst::afw::geom::operator<<
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:240
lsst::geom::polynomials::simplified
PolynomialFunction1d simplified(ScaledPolynomialFunction1d const &f)
Calculate the standard polynomial function that is equivalent to a scaled standard polynomial functio...
Definition: PolynomialFunction1d.cc:32
LSST_ARCHIVE_ASSERT
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
Definition: Persistable.h:48
std::ostream
STL class.
transformUtils.h
lsst::afw::geom::Transform::readStream
static std::shared_ptr< Transform< FromEndpoint, ToEndpoint > > readStream(std::istream &is)
Deserialize a Transform of this type from an input stream.
Definition: Transform.cc:145
x
double x
Definition: ChebyshevBoundedField.cc:277
INSTANTIATE_TRANSFORM
#define INSTANTIATE_TRANSFORM(FromEndpoint, ToEndpoint)
Definition: Transform.cc:254
frameSet
table::Key< table::Array< std::uint8_t > > frameSet
Definition: TransformBoundedField.cc:91
std::to_string
T to_string(T... args)
lsst.pex::exceptions::LogicError
Reports errors in the logical structure of the program.
Definition: Runtime.h:46
lsst::afw::geom::Transform::FromPoint
typename FromEndpoint::Point FromPoint
Definition: Transform.h:74
Transform.h
lsst.pipe.tasks.cli.cmd.commands.str
str
Definition: commands.py:50
lsst::afw::geom::Transform::readString
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:151
lsst
A base class for image defects.
Definition: imageAlgorithm.dox:1
LSST_EXCEPT
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
std::ostringstream
STL class.
schema
table::Schema schema
Definition: Transform.cc:198
lsst::geom
Definition: AffineTransform.h:36
os
std::ostream * os
Definition: Schema.cc:746
lsst::afw::geom::Transform::Transform
Transform(Transform const &)=default
lsst::afw::formatters::stringToBytes
ndarray::Array< std::uint8_t, 1, 1 > stringToBytes(std::string const &str)
Encode a std::string as a vector of uint8.
Definition: Utils.cc:162
lsst::afw::geom::Transform::inverted
std::shared_ptr< Transform< ToEndpoint, FromEndpoint > > inverted() const
The inverse of this Transform.
Definition: Transform.cc:111
bytes
table::Key< table::Array< std::uint8_t > > bytes
Definition: Transform.cc:199
lsst.pex::exceptions::InvalidParameterError
Reports invalid arguments.
Definition: Runtime.h:66
std
STL namespace.
lsst::afw::geom::Transform::writeString
std::string writeString() const
Serialize this Transform to a string, using the same format as writeStream.
Definition: Transform.cc:163
lsst::afw::geom::GenericEndpoint
A generic endpoint for data in the format used by ast::Mapping.
Definition: Endpoint.h:226
transform
table::Key< int > transform
Definition: TransformMap.cc:299
std::ostringstream::str
T str(T... args)
lsst::afw::table::CatalogT::addNew
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:485
lsst::afw::geom::Transform::getJacobian
Eigen::MatrixXd getJacobian(FromPoint const &x) const
The Jacobian matrix of this Transform.
Definition: Transform.cc:123
Exception.h
Utils.h
lsst::afw::geom::Transform::applyInverse
FromPoint applyInverse(ToPoint const &point) const
Transform one point in the inverse direction ("to" to "from")
Definition: Transform.cc:95
std::istream
STL class.
lsst::afw::table::CatalogT< BaseRecord >
lsst::afw::geom::Transform::then
std::shared_ptr< Transform< FromEndpoint, NextToEndpoint > > then(Transform< ToEndpoint, NextToEndpoint > const &next, bool simplify=true) const
Concatenate two Transforms.
Definition: Transform.cc:171
OutputArchive.h
lsst::afw::geom::SpherePointEndpoint
An endpoint for lsst::geom::SpherePoint.
Definition: Endpoint.h:315