LSST Applications  21.0.0+04719a4bac,21.0.0-1-ga51b5d4+ae94e5adf4,21.0.0-10-g2408eff+ad7fe00a3b,21.0.0-10-g560fb7b+5d30037bff,21.0.0-10-gcf60f90+7fd8e8fd04,21.0.0-11-g25eff31+491f1498e8,21.0.0-11-gd78879e+d13a45ff19,21.0.0-12-g1e69a3f+69d54d99d8,21.0.0-17-g6590b197+c8c705a94e,21.0.0-2-g103fe59+29086b68f8,21.0.0-2-g1367e85+d793a9824f,21.0.0-2-g45278ab+04719a4bac,21.0.0-2-g5242d73+d793a9824f,21.0.0-2-g7f82c8f+7178d1fb8b,21.0.0-2-g8f08a60+fd0b970de5,21.0.0-2-g8faa9b5+3b24369756,21.0.0-2-ga326454+7178d1fb8b,21.0.0-2-gde069b7+ca45a81b40,21.0.0-2-gecfae73+3609a557ba,21.0.0-2-gfc62afb+d793a9824f,21.0.0-22-g2a5702db6+f385fa6f38,21.0.0-3-g357aad2+673ab9f056,21.0.0-3-g4be5c26+d793a9824f,21.0.0-3-g65f322c+45176dc65e,21.0.0-3-g7d9da8d+3b24369756,21.0.0-3-ge02ed75+d05e6d1be4,21.0.0-4-g591bb35+d05e6d1be4,21.0.0-4-g65b4814+5d30037bff,21.0.0-4-gccdca77+a631590478,21.0.0-4-ge8a399c+7f1b116a8b,21.0.0-5-gb7b9a9f+d793a9824f,21.0.0-5-gd00fb1e+de3bd29da1,21.0.0-55-g0be6b205+66ae927d20,21.0.0-6-g2d4f3f3+04719a4bac,21.0.0-7-g04766d7+510a52a951,21.0.0-7-g98eecf7+adb4d61a8d,21.0.0-9-g39e06b5+d05e6d1be4,master-gac4afde19b+d05e6d1be4,w.2021.12
LSST Data Management Base Package
TransformMap.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 /*
3  * Developed for the LSST Data Management System.
4  * This product includes software developed by the LSST Project
5  * (https://www.lsst.org).
6  * See the COPYRIGHT file at the top-level directory of this distribution
7  * for details of code ownership.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  */
22 #include <sstream>
23 #include <unordered_set>
24 
25 #include "lsst/log/Log.h"
26 #include "lsst/pex/exceptions.h"
32 
33 namespace lsst {
34 namespace afw {
35 namespace cameraGeom {
36 
37 namespace {
38 
39 // Allows conversions between LSST and AST data formats
40 static lsst::afw::geom::Point2Endpoint const POINT2_ENDPOINT;
41 
42 static auto LOGGER = LOG_GET("afw.cameraGeom.TransformMap");
43 
44 // Make an AST Frame name for a CameraSys.
45 std::string makeFrameName(CameraSys const & sys) {
46  std::string r = "Ident=" + sys.getSysName();
47  if (sys.hasDetectorName()) {
48  r += "_";
49  r += sys.getDetectorName();
50  }
51  return r;
52 }
53 
54 /*
55  * Make a vector of `Connection` instances that can be safely passed to
56  * TransformMap's private constructor.
57  *
58  * This guarantees that:
59  * - Connections are sorted according to their distance (in number of
60  * intermediate connections) from the given reference `CameraSys`;
61  * - The `fromSys` of each `Connection` is closer to the reference than the
62  * `toSys`.
63  *
64  * @param[in] reference Reference coordinate system. All systems must be
65  * (indirectly) connected to this system, and will be
66  * sorted according to the number of connections to it.
67  * @param[in] connections Vector of `Connection` instances. Passed by value so
68  * we can either move into it (avoiding a copy) or copy
69  * into it (when we have a const reference and a copy is
70  * unavoidable), depending on the context.
71  *
72  * @returns connections An updated version of the connections vector.
73  *
74  * @throws pex::exceptions::InvalidParameterError Thrown if the vector of
75  * connections graph is empty, contains cycles, is not fully connected, or
76  * includes any connections in which `fromSys == toSys`.
77  */
78 std::vector<TransformMap::Connection> standardizeConnections(
79  CameraSys const & reference,
81 ) {
82  if (connections.empty()) {
83  throw LSST_EXCEPT(
84  pex::exceptions::InvalidParameterError,
85  "Cannot create a TransformMap with no connections."
86  );
87  }
88  // Iterator to the first unprocessed connection in result; will be
89  // incremented as we proceed.
90  auto firstUnprocessed = connections.begin();
91  // All CameraSys whose associated Connections are already in the processed
92  // part of `connections`.
93  std::unordered_set<CameraSys> knownSystems = {reference};
94  // The set of CameraSys whose associated Connections are being processed
95  // in this iteration of the outer (while) loop. These are all some common
96  // distance N from the reference system (in number of connections), where
97  // N increases for each iteration (but is not tracked).
98  std::unordered_set<CameraSys> currentSystems = {reference};
99  // The set of CameraSys that will become currentSys at the next
100  // iteration.
101  std::unordered_set<CameraSys> nextSystems;
102  LOGLS_DEBUG(LOGGER, "Standardizing: starting with reference " << reference);
103  while (!currentSystems.empty()) {
104  LOGLS_DEBUG(LOGGER, "Standardizing: beginning iteration with currentSystems={ ");
105  for (auto const & sys : currentSystems) {
106  LOGLS_DEBUG(LOGGER, "Standardizing: " << sys << ", ");
107  }
108  LOGLS_DEBUG(LOGGER, "Standardizing: }");
109  // Iterate over all unsorted connections, looking for those associated
110  // with a CameraSys in currentSystems.
111  for (auto connection = firstUnprocessed; connection != connections.end(); ++connection) {
112  bool related = currentSystems.count(connection->fromSys) > 0;
113  if (!related && currentSystems.count(connection->toSys)) {
114  LOGLS_DEBUG(LOGGER, "Standardizing: reversing " << (*connection));
115  // Safe because `connections` is passed by value.
116  connection->reverse();
117  related = true;
118  }
119  if (related) {
120  if (connection->toSys == connection->fromSys) {
122  ss << "Identity connection found: " << (*connection) << ".";
123  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, ss.str());
124  }
125  if (knownSystems.count(connection->toSys)) {
127  ss << "Multiple paths between reference " << reference
128  << " and " << connection->toSys << ".";
129  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, ss.str());
130  }
131  LOGLS_DEBUG(LOGGER, "Standardizing: adding " << (*connection));
132  nextSystems.insert(connection->toSys);
133  knownSystems.insert(connection->toSys);
134  std::swap(*firstUnprocessed, *connection);
135  ++firstUnprocessed;
136  }
137  }
138  currentSystems.swap(nextSystems);
139  nextSystems.clear();
140  }
141  // Any connections we haven't processed yet must include only CameraSys
142  // we've never seen before.
143  if (firstUnprocessed != connections.end()) {
145  ss << "Disconnected connection(s) found: " << (*firstUnprocessed);
146  ++firstUnprocessed;
147  for (auto connection = firstUnprocessed; connection != connections.end(); ++connection) {
148  ss << ", " << (*connection);
149  }
150  ss << ".";
151  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, ss.str());
152  }
153  // No RVO, because this is a function argument, but it's still a move so we
154  // don't care.
155  return connections;
156 }
157 
158 // Return the reference coordinate system from an already-standardized vector of connections.
159 CameraSys getReferenceSys(std::vector<TransformMap::Connection> const & connections) {
160  return connections.front().fromSys;
161 }
162 
163 } // anonymous
164 
166  transform = transform->inverted();
167  toSys.swap(fromSys);
168 }
169 
171  return os << connection.fromSys << "->" << connection.toSys;
172 }
173 
175  CameraSys const & reference,
176  Transforms const & transforms
177 ) {
178  std::vector<Connection> connections;
179  connections.reserve(transforms.size());
180  for (auto const & pair : transforms) {
181  connections.push_back(Connection{pair.second, reference, pair.first});
182  }
183  // We can't use make_shared because TransformMap ctor is private.
185  new TransformMap(standardizeConnections(reference, std::move(connections)))
186  );
187 }
188 
190  CameraSys const &reference,
191  std::vector<Connection> const & connections
192 ) {
193  // We can't use make_shared because TransformMap ctor is private.
195  new TransformMap(standardizeConnections(reference, connections))
196  );
197 }
198 
199 
200 // All resources owned by value or by smart pointer
201 TransformMap::~TransformMap() noexcept = default;
202 
203 lsst::geom::Point2D TransformMap::transform(lsst::geom::Point2D const &point, CameraSys const &fromSys,
204  CameraSys const &toSys) const {
205  auto mapping = _getMapping(fromSys, toSys);
206  return POINT2_ENDPOINT.pointFromData(mapping->applyForward(POINT2_ENDPOINT.dataFromPoint(point)));
207 }
208 
210  CameraSys const &fromSys,
211  CameraSys const &toSys) const {
212  auto mapping = _getMapping(fromSys, toSys);
213  return POINT2_ENDPOINT.arrayFromData(mapping->applyForward(POINT2_ENDPOINT.dataFromArray(pointList)));
214 }
215 
216 bool TransformMap::contains(CameraSys const &system) const noexcept { return _frameIds.count(system) > 0; }
217 
219  CameraSys const &toSys) const {
220  return std::make_shared<geom::TransformPoint2ToPoint2>(*_getMapping(fromSys, toSys));
221 }
222 
223 int TransformMap::_getFrame(CameraSys const &system) const {
224  try {
225  return _frameIds.at(system);
226  } catch (std::out_of_range const &e) {
227  std::ostringstream buffer;
228  buffer << "Unsupported coordinate system: " << system;
230  }
231 }
232 
233 std::shared_ptr<ast::Mapping const> TransformMap::_getMapping(CameraSys const &fromSys,
234  CameraSys const &toSys) const {
235  return _frameSet->getMapping(_getFrame(fromSys), _getFrame(toSys));
236 }
237 
238 size_t TransformMap::size() const noexcept { return _frameIds.size(); }
239 
240 
242  _connections(std::move(connections))
243 {
244  // standardizeConnections must be run by anything that calls the
245  // constructor, and that should throw on all of the conditions we assert
246  // on below (which is why those are asserts).
247  assert(!_connections.empty());
248 
249  int nFrames = 0; // tracks frameSet->getNFrame() to avoid those (expensive) calls
250 
251  // Local helper function that creates a Frame, updates the nFrames counter,
252  // and adds an entry to the frameIds map. Returns the new Frame.
253  // Should always be called in concert with an update to frameSet.
254  auto addFrameForSys = [this, &nFrames](CameraSys const & sys) mutable -> ast::Frame {
255  #ifndef NDEBUG
256  auto r = // We only care about this return value for the assert below;
257  #endif
258  _frameIds.emplace(sys, ++nFrames);
259  assert(r.second); // this must actually insert something, not find an already-inserted CameraSys.
260  return ast::Frame(2, makeFrameName(sys));
261  };
262 
263  // FrameSet that manages all transforms; should always be updated in
264  // concert with a call to addFrameForSys.
265  _frameSet = std::make_unique<ast::FrameSet>(addFrameForSys(getReferenceSys(_connections)));
266 
267  for (auto const & connection : _connections) {
268  auto fromSysIdIter = _frameIds.find(connection.fromSys);
269  assert(fromSysIdIter != _frameIds.end());
270  _frameSet->addFrame(fromSysIdIter->second, *connection.transform->getMapping(),
271  addFrameForSys(connection.toSys));
272  }
273 
274  // We've maintained our own counter for frame IDs for performance and
275  // convenience reasons, but it had better match AST's internal counter.
276  assert(_frameSet->getNFrame() == nFrames);
277 }
278 
280 
281 
282 namespace {
283 
284 struct PersistenceHelper {
285 
286  static PersistenceHelper const & get() {
287  static PersistenceHelper const instance;
288  return instance;
289  }
290 
291  // Schema and keys for the catalog that stores Connection objects.
292  // Considered as a graph, 'from' and 'to' identify vertices, and
293  // 'transform' identifies an edge.
294  table::Schema schema;
295  table::Key<std::string> fromSysName;
296  table::Key<std::string> fromSysDetectorName;
297  table::Key<std::string> toSysName;
298  table::Key<std::string> toSysDetectorName;
299  table::Key<int> transform;
300 
301 private:
302 
303  PersistenceHelper() :
304  schema(),
305  fromSysName(schema.addField<std::string>("fromSysName",
306  "Camera coordinate system name.", "", 0)),
307  fromSysDetectorName(schema.addField<std::string>("fromSysDetectorName",
308  "Camera coordinate system detector name.", "", 0)),
309  toSysName(schema.addField<std::string>("toSysName",
310  "Camera coordinate system name.", "", 0)),
311  toSysDetectorName(schema.addField<std::string>("toSysDetectorName",
312  "Camera coordinate system detector name.", "", 0)),
313  transform(schema.addField<int>("transform", "Archive ID of the transform.", ""))
314  {}
315 
316  PersistenceHelper(PersistenceHelper const &) = delete;
317  PersistenceHelper(PersistenceHelper &&) = delete;
318 
319  PersistenceHelper & operator=(PersistenceHelper const &) = delete;
320  PersistenceHelper & operator=(PersistenceHelper &&) = delete;
321 
322 };
323 
324 
325 // PersistenceHelper for a previous format version; now only supported in
326 // reading.
327 struct OldPersistenceHelper {
328 
329  static OldPersistenceHelper const & get() {
330  static OldPersistenceHelper const instance;
331  return instance;
332  }
333 
334  // Schema and keys for the catalog that stores TransformMap._frameIds.
335  // Considered as a graph, this is a list of all of the vertices with the
336  // integers that identify them in the list of edges below.
337  table::Schema sysSchema;
338  table::Key<std::string> sysName;
339  table::Key<std::string> detectorName;
340  table::Key<int> id;
341 
342  // Schema and keys for the catalog that stores
343  // TransformMap._canonicalConnections entries and the associated Transform
344  // extracted from TransformMap._transforms.
345  // Considered as a graph, 'from' and 'to' identify vertices, and
346  // 'transform' identifies an edge.
347  table::Schema connectionSchema;
348  table::Key<int> from;
349  table::Key<int> to;
350  table::Key<int> transform;
351 
352  CameraSys makeCameraSys(table::BaseRecord const & record) const {
353  return CameraSys(record.get(sysName), record.get(detectorName));
354  }
355 
356 private:
357 
358  OldPersistenceHelper() :
359  sysSchema(),
360  sysName(sysSchema.addField<std::string>("sysName", "Camera coordinate system name", "", 0)),
361  detectorName(sysSchema.addField<std::string>("detectorName",
362  "Camera coordinate system detector name", "", 0)),
363  id(sysSchema.addField<int>("id", "AST ID of the Frame for the CameraSys", "")),
365  from(connectionSchema.addField<int>("from", "AST ID of the Frame this transform maps from.", "")),
366  to(connectionSchema.addField<int>("to", "AST ID of the Frame this transform maps to.", "")),
367  transform(connectionSchema.addField<int>("transform", "Archive ID of the transform.", ""))
368  {}
369 
370  OldPersistenceHelper(OldPersistenceHelper const &) = delete;
371  OldPersistenceHelper(OldPersistenceHelper &&) = delete;
372 
373  OldPersistenceHelper & operator=(OldPersistenceHelper const &) = delete;
374  OldPersistenceHelper & operator=(OldPersistenceHelper &&) = delete;
375 
376 };
377 
378 
379 } // namespace
380 
381 
382 std::string TransformMap::getPersistenceName() const {
383  return "TransformMap";
384 }
385 
386 std::string TransformMap::getPythonModule() const {
387  return "lsst.afw.cameraGeom";
388 }
389 
390 void TransformMap::write(OutputArchiveHandle& handle) const {
391  auto const & keys = PersistenceHelper::get();
392 
393  auto cat = handle.makeCatalog(keys.schema);
394  for (auto const & connection : _connections) {
395  auto record = cat.addNew();
396  record->set(keys.fromSysName, connection.fromSys.getSysName());
397  record->set(keys.fromSysDetectorName, connection.fromSys.getDetectorName());
398  record->set(keys.toSysName, connection.toSys.getSysName());
399  record->set(keys.toSysDetectorName, connection.toSys.getDetectorName());
400  record->set(keys.transform, handle.put(connection.transform));
401  }
402  handle.saveCatalog(cat);
403 }
404 
406 public:
407 
408  Factory() : PersistableFactory("TransformMap") {}
409 
411  CatalogVector const& catalogs) const {
412  auto const & keys = OldPersistenceHelper::get();
413 
414  LSST_ARCHIVE_ASSERT(catalogs.size() == 2u);
415  auto const & sysCat = catalogs[0];
416  auto const & connectionCat = catalogs[1];
417  LSST_ARCHIVE_ASSERT(sysCat.getSchema() == keys.sysSchema);
418  LSST_ARCHIVE_ASSERT(connectionCat.getSchema() == keys.connectionSchema);
419  LSST_ARCHIVE_ASSERT(sysCat.size() == connectionCat.size() + 1);
420  LSST_ARCHIVE_ASSERT(sysCat.isSorted(keys.id));
421 
423  for (auto const & sysRecord : sysCat) {
424  auto sys = keys.makeCameraSys(sysRecord);
425  sysById.emplace(sysRecord.get(keys.id), sys);
426  }
427 
428  auto const referenceSysIter = sysById.find(1);
429  LSST_ARCHIVE_ASSERT(referenceSysIter != sysById.end());
430  std::vector<Connection> connections;
431  for (auto const & connectionRecord : connectionCat) {
432  auto const fromSysIter = sysById.find(connectionRecord.get(keys.from));
433  LSST_ARCHIVE_ASSERT(fromSysIter != sysById.end());
434  auto const toSysIter = sysById.find(connectionRecord.get(keys.to));
435  LSST_ARCHIVE_ASSERT(toSysIter != sysById.end());
436  auto const transform = archive.get<geom::TransformPoint2ToPoint2>(
437  connectionRecord.get(keys.transform)
438  );
439 
440  connections.push_back(Connection{transform, fromSysIter->second, toSysIter->second});
441  }
442 
443  connections = standardizeConnections(referenceSysIter->second, std::move(connections));
444  return std::shared_ptr<TransformMap>(new TransformMap(std::move(connections)));
445  }
446 
448  CatalogVector const& catalogs) const override {
449  if (catalogs.size() == 2u) {
450  return readOld(archive, catalogs);
451  }
452 
453  auto const & keys = PersistenceHelper::get();
454 
455  LSST_ARCHIVE_ASSERT(catalogs.size() == 1u);
456  auto const & cat = catalogs[0];
457  LSST_ARCHIVE_ASSERT(cat.getSchema() == keys.schema);
458 
459  std::vector<Connection> connections;
460  for (auto const & record : cat) {
461  CameraSys const fromSys(record.get(keys.fromSysName), record.get(keys.fromSysDetectorName));
462  CameraSys const toSys(record.get(keys.toSysName), record.get(keys.toSysDetectorName));
463  auto const transform = archive.get<geom::TransformPoint2ToPoint2>(record.get(keys.transform));
464  connections.push_back(Connection{transform, fromSys, toSys});
465  }
466 
467  // Deserialized connections should already be standardized, but be
468  // defensive anyway.
469  auto const referenceSys = getReferenceSys(connections);
470  connections = standardizeConnections(referenceSys, std::move(connections));
471  return std::shared_ptr<TransformMap>(new TransformMap(std::move(connections)));
472  }
473 
474  static Factory const registration;
475 
476 };
477 
479 
480 } // namespace cameraGeom
481 
482 namespace table {
483 namespace io {
484 
485 template class PersistableFacade<cameraGeom::TransformMap>;
486 
487 } // namespace io
488 } // namespace table
489 
490 } // namespace afw
491 } // namespace lsst
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
LSST DM logging module built on log4cxx.
#define LOG_GET(logger)
Returns a Log object associated with logger.
Definition: Log.h:75
#define LOGLS_DEBUG(logger, message)
Log a debug-level message using an iostream-based interface.
Definition: Log.h:608
std::ostream * os
Definition: Schema.cc:746
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
Definition: Persistable.h:48
T at(T... args)
T begin(T... args)
Frame is used to represent a coordinate system.
Definition: Frame.h:157
virtual void addFrame(int iframe, Mapping const &map, Frame const &frame)
Add a new Frame and an associated Mapping to this FrameSet so as to define a new coordinate system,...
Definition: FrameSet.h:210
std::shared_ptr< Mapping > getMapping(int from=BASE, int to=CURRENT) const
Obtain a Mapping that converts between two Frames in a FrameSet.
Definition: FrameSet.h:304
int getNFrame() const
Get FrameSet_NFrame "NFrame": number of Frames in the FrameSet, starting from 1.
Definition: FrameSet.h:316
Camera coordinate system; used as a key in in TransformMap.
Definition: CameraSys.h:83
void swap(CameraSys &other) noexcept
Definition: CameraSys.h:107
std::shared_ptr< Persistable > readOld(InputArchive const &archive, CatalogVector const &catalogs) const
std::shared_ptr< Persistable > read(InputArchive const &archive, CatalogVector const &catalogs) const override
Construct a new object from the given InputArchive and vector of catalogs.
A registry of 2-dimensional coordinate transforms for a specific camera.
Definition: TransformMap.h:62
static std::shared_ptr< TransformMap const > make(CameraSys const &reference, Transforms const &transforms)
Construct a TransformMap with all transforms relative to a single reference CameraSys.
TransformMap(TransformMap const &other)=delete
size_t size() const noexcept
Get the number of supported coordinate systems.
bool contains(CameraSys const &system) const noexcept
Can this transform to and from the specified coordinate system?
std::vector< Connection > getConnections() const
Return the sequence of connections used to construct this Transform.
std::shared_ptr< geom::TransformPoint2ToPoint2 > getTransform(CameraSys const &fromSys, CameraSys const &toSys) const
Get a Transform from one camera coordinate system to another.
lsst::geom::Point2D transform(lsst::geom::Point2D const &point, CameraSys const &fromSys, CameraSys const &toSys) const
Convert a point from one camera coordinate system to another.
An endpoint for lsst::geom::Point2D.
Definition: Endpoint.h:261
ndarray::Array< double, 2, 2 > dataFromArray(Array const &arr) const override
Get raw data from an array of points.
Definition: Endpoint.cc:124
std::vector< double > dataFromPoint(Point const &point) const override
Get raw data from a single point.
Definition: Endpoint.cc:115
Point pointFromData(std::vector< double > const &data) const override
Get a single point from raw data.
Definition: Endpoint.cc:138
Array arrayFromData(ndarray::Array< double, 2, 2 > const &data) const override
Get an array of points from raw data.
Definition: Endpoint.cc:148
A vector of catalogs used by Persistable.
Definition: CatalogVector.h:29
A multi-catalog archive object used to load table::io::Persistable objects.
Definition: InputArchive.h:31
std::shared_ptr< Persistable > get(int id) const
Load the Persistable with the given ID and return it.
A base class for factory classes used to reconstruct objects from records.
Definition: Persistable.h:228
PersistableFactory(std::string const &name)
Constructor for the factory.
Definition: Persistable.cc:74
Reports invalid arguments.
Definition: Runtime.h:66
T clear(T... args)
T count(T... args)
T emplace(T... args)
T empty(T... args)
T end(T... args)
T find(T... args)
T front(T... args)
T insert(T... args)
T move(T... args)
std::ostream & operator<<(std::ostream &os, CameraSysPrefix const &detSysPrefix)
Definition: CameraSys.cc:47
Transform< Point2Endpoint, Point2Endpoint > TransformPoint2ToPoint2
Definition: Transform.h:300
FilterProperty & operator=(FilterProperty const &)=default
Point< double, 2 > Point2D
Definition: Point.h:324
A base class for image defects.
STL namespace.
T push_back(T... args)
T reserve(T... args)
T size(T... args)
table::Key< int > id
table::Key< std::string > sysName
table::Key< std::string > fromSysName
table::Key< int > from
table::Schema sysSchema
table::Schema schema
table::Key< std::string > toSysDetectorName
table::Key< std::string > fromSysDetectorName
table::Key< int > to
table::Key< int > transform
table::Key< std::string > toSysName
table::Key< std::string > detectorName
table::Schema connectionSchema
T str(T... args)
Representation of a single edge in the graph defined by a TransformMap.
Definition: TransformMap.h:80
void reverse()
Reverse the connection, by swapping fromSys and toSys and inverting the transform.
std::shared_ptr< geom::TransformPoint2ToPoint2 const > transform
Definition: TransformMap.h:81
T swap(T... args)
T throw_with_nested(T... args)