LSST Applications 30.0.7,g0e76e35be5+e8e946ae08,g19811a7679+138f7293ba,g199a45376c+5e234f8357,g1fd858c14a+2f48dbc4c4,g262e1987ae+fb36cac54d,g29ae962dfc+d9108a0941,g2c21b0017a+4f59a27f16,g31e44d4a5c+b0138be388,g33ac35c1f1+28b9f72785,g35bb328faa+b0138be388,g40c9b15c53+823ad735c1,g47891489e3+bcc48a0b46,g53246c7159+b0138be388,g64539dfbff+e8e946ae08,g67b6fd64d1+bcc48a0b46,g74acd417e5+422380537a,g76965917b2+a5ca99c4d9,g786e29fd12+796b79145d,g7aefaa3e3d+dc0c200193,g86b635cae8+734fe384f0,g87389fa792+d8b5378923,g89139ef638+bcc48a0b46,g8bbb235e95+3f4f7f9447,g8ea07a8fe4+78a4c88802,g9290983e33+ffdc83c6f7,g92c671f44c+e8e946ae08,gaa753fd333+03f406da14,gbf99507273+b0138be388,gc49b57b85e+8df26ee1f0,gca7fc764a6+bcc48a0b46,gd7ef33dd92+bcc48a0b46,gdab6d2f7ff+422380537a,ge1c02a5578+b0138be388,ge410e46f29+bcc48a0b46,ge80df9fc40+e6db5413d1,geaed405ab2+1de65a85c6,gf5dcc679e7+35a0ce2edd,gf5f1c85443+e8e946ae08
LSST Data Management Base Package
Loading...
Searching...
No Matches
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/geom/Point.h"
28#include "lsst/log/Log.h"
29#include "lsst/pex/exceptions.h"
36
37namespace lsst {
38namespace afw {
39namespace cameraGeom {
40
41namespace {
42
43// Allows conversions between LSST and AST data formats
44static lsst::afw::geom::Point2Endpoint const POINT2_ENDPOINT;
45
46static auto LOGGER = LOG_GET("lsst.afw.cameraGeom.TransformMap");
47
48// Make an AST Frame name for a CameraSys.
49std::string makeFrameName(CameraSys const &sys) {
50 std::string r = "Ident=" + sys.getSysName();
51 if (sys.hasDetectorName()) {
52 r += "_";
53 r += sys.getDetectorName();
54 }
55 return r;
56}
57
58/*
59 * Make a vector of `Connection` instances that can be safely passed to
60 * TransformMap's private constructor.
61 *
62 * This guarantees that:
63 * - Connections are sorted according to their distance (in number of
64 * intermediate connections) from the given reference `CameraSys`;
65 * - The `fromSys` of each `Connection` is closer to the reference than the
66 * `toSys`.
67 *
68 * @param[in] reference Reference coordinate system. All systems must be
69 * (indirectly) connected to this system, and will be
70 * sorted according to the number of connections to it.
71 * @param[in] connections Vector of `Connection` instances. Passed by value so
72 * we can either move into it (avoiding a copy) or copy
73 * into it (when we have a const reference and a copy is
74 * unavoidable), depending on the context.
75 *
76 * @returns connections An updated version of the connections vector.
77 *
78 * @throws pex::exceptions::InvalidParameterError Thrown if the vector of
79 * connections graph is empty, contains cycles, is not fully connected, or
80 * includes any connections in which `fromSys == toSys`.
81 */
82std::vector<TransformMap::Connection> standardizeConnections(
83 CameraSys const &reference, std::vector<TransformMap::Connection> connections) {
84 if (connections.empty()) {
85 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
86 "Cannot create a TransformMap with no connections.");
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) {
121 std::ostringstream ss;
122 ss << "Identity connection found: " << (*connection) << ".";
123 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, ss.str());
124 }
125 if (knownSystems.count(connection->toSys)) {
126 std::ostringstream ss;
127 ss << "Multiple paths between reference " << reference << " and " << connection->toSys
128 << ".";
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()) {
144 std::ostringstream ss;
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.
159CameraSys getReferenceSys(std::vector<TransformMap::Connection> const &connections) {
160 return connections.front().fromSys;
161}
162
163} // namespace
164
166 transform = transform->inverted();
167 toSys.swap(fromSys);
168}
169
171 return os << connection.fromSys << "->" << connection.toSys;
172}
173
175 Transforms const &transforms) {
176 std::vector<Connection> connections;
177 connections.reserve(transforms.size());
178 for (auto const &pair : transforms) {
179 connections.push_back(Connection{pair.second, reference, pair.first});
180 }
181 // We can't use make_shared because TransformMap ctor is private.
183 new TransformMap(standardizeConnections(reference, std::move(connections))));
184}
185
187 std::vector<Connection> const &connections) {
188 // We can't use make_shared because TransformMap ctor is private.
190 new TransformMap(standardizeConnections(reference, connections)));
191}
192
193// All resources owned by value or by smart pointer
194TransformMap::~TransformMap() noexcept = default;
195
196lsst::geom::Point2D TransformMap::transform(lsst::geom::Point2D const &point, CameraSys const &fromSys,
197 CameraSys const &toSys) const {
198 auto mapping = _getMapping(fromSys, toSys);
199 return POINT2_ENDPOINT.pointFromData(mapping->applyForward(POINT2_ENDPOINT.dataFromPoint(point)));
200}
201
203 CameraSys const &fromSys,
204 CameraSys const &toSys) const {
205 auto mapping = _getMapping(fromSys, toSys);
206 return POINT2_ENDPOINT.arrayFromData(mapping->applyForward(POINT2_ENDPOINT.dataFromArray(pointList)));
207}
208
209bool TransformMap::contains(CameraSys const &system) const noexcept { return _frameIds.count(system) > 0; }
210
212 CameraSys const &toSys) const {
213 return std::make_shared<geom::TransformPoint2ToPoint2>(*_getMapping(fromSys, toSys));
214}
215
216bool TransformMap::getFocalPlaneParity() const noexcept { return _focalPlaneParity; }
217
218int TransformMap::_getFrame(CameraSys const &system) const {
219 try {
220 return _frameIds.at(system);
221 } catch (std::out_of_range const &e) {
222 std::ostringstream buffer;
223 buffer << "Unsupported coordinate system: " << system;
225 }
226}
227
228std::shared_ptr<ast::Mapping const> TransformMap::_getMapping(CameraSys const &fromSys,
229 CameraSys const &toSys) const {
230 return _frameSet->getMapping(_getFrame(fromSys), _getFrame(toSys));
231}
232
233size_t TransformMap::size() const noexcept { return _frameIds.size(); }
234
236 : _connections(std::move(connections)), _focalPlaneParity(false) {
237 // standardizeConnections must be run by anything that calls the
238 // constructor, and that should throw on all of the conditions we assert
239 // on below (which is why those are asserts).
240 assert(!_connections.empty());
241
242 int nFrames = 0; // tracks frameSet->getNFrame() to avoid those (expensive) calls
243
244 // Local helper function that creates a Frame, updates the nFrames counter,
245 // and adds an entry to the frameIds map. Returns the new Frame.
246 // Should always be called in concert with an update to frameSet.
247 auto addFrameForSys = [this, &nFrames](CameraSys const &sys) mutable -> ast::Frame {
248#ifndef NDEBUG
249 auto r = // We only care about this return value for the assert below;
250#endif
251 _frameIds.emplace(sys, ++nFrames);
252 assert(r.second); // this must actually insert something, not find an already-inserted CameraSys.
253 return ast::Frame(2, makeFrameName(sys));
254 };
255
256 // FrameSet that manages all transforms; should always be updated in
257 // concert with a call to addFrameForSys.
258 _frameSet = std::make_unique<ast::FrameSet>(addFrameForSys(getReferenceSys(_connections)));
259
260 for (auto const &connection : _connections) {
261 auto fromSysIdIter = _frameIds.find(connection.fromSys);
262 assert(fromSysIdIter != _frameIds.end());
263 _frameSet->addFrame(fromSysIdIter->second, *connection.transform->getMapping(),
264 addFrameForSys(connection.toSys));
265 }
266
267 // We've maintained our own counter for frame IDs for performance and
268 // convenience reasons, but it had better match AST's internal counter.
269 assert(_frameSet->getNFrame() == nFrames);
270
271 // If the caller didn't provide the focal plane parity, get it from the
272 // determinant of the Jacobian of the FOCAL_PLANE -> FIELD_ANGLE transform.
273 try {
275 auto jacobian = transform->getJacobian(lsst::geom::Point2D(0.0, 0.0));
276 _focalPlaneParity = (jacobian.determinant() < 0);
277 } catch (pex::exceptions::InvalidParameterError &) {
278 }
279}
280
282
285 std::string const & focalPlaneUnit
286) const {
287 // We use copy=false to extract each frame from the internal FrameSet,
288 // since it will always be copied when adding it to the new one. We then
289 // set the 'ident' value on a shallow reference to the new frame.
290 auto result = std::make_unique<ast::FrameSet>(*_frameSet->getFrame(ast::FrameSet::BASE, false));
291 {
292 auto fp_frame = result->getFrame(ast::FrameSet::BASE, false);
293 fp_frame->setIdent("FOCAL_PLANE");
294 fp_frame->setTitle("Focal Plane Coordinates");
295 fp_frame->setUnit(1, focalPlaneUnit);
296 fp_frame->setUnit(2, focalPlaneUnit);
297 fp_frame->setLabel(1, "x");
298 fp_frame->setLabel(2, "y");
299 }
300 {
301 int old_frame_id = _getFrame(FIELD_ANGLE);
302 result->addFrame(
304 *_frameSet->getMapping(ast::FrameSet::BASE, old_frame_id),
305 *_frameSet->getFrame(old_frame_id, false)
306 );
307 auto frame = result->getFrame(ast::FrameSet::CURRENT, false);
308 frame->setIdent("FIELD_ANGLE");
309 frame->setTitle("Field Angle Coordinates");
310 frame->setUnit(1, "rad");
311 frame->setUnit(2, "rad");
312 frame->setLabel(1, "x");
313 frame->setLabel(2, "y");
314 }
315 for (auto const & detector : detectors) {
316 CameraSys sys(ACTUAL_PIXELS, detector->getName());
317 auto id_iter = _frameIds.find(sys);
318 if (id_iter == _frameIds.end()) {
319 sys = CameraSys(PIXELS, detector->getName());
320 id_iter = _frameIds.find(sys);
321 if (id_iter == _frameIds.end()) {
322 std::ostringstream buffer;
323 buffer << "Unsupported coordinate system: " << sys;
325 }
326 }
327 result->addFrame(
329 *_frameSet->getMapping(ast::FrameSet::BASE, id_iter->second),
330 *_frameSet->getFrame(id_iter->second, false)
331 );
332 auto frame = result->getFrame(ast::FrameSet::CURRENT, false);
333 frame->setIdent((boost::format("DETECTOR_%03d") % detector->getId()).str());
334 frame->setTitle((boost::format("Pixel Coordinates (Detector %d)") % detector->getId()).str());
335 frame->setUnit(1, "pix");
336 frame->setUnit(2, "pix");
337 frame->setLabel(1, "x");
338 frame->setLabel(2, "y");
339 auto bbox = detector->getBBox();
340 frame->setBottom(1, bbox.getMinX());
341 frame->setTop(1, bbox.getMaxX());
342 frame->setBottom(2, bbox.getMinY());
343 frame->setTop(2, bbox.getMaxY());
344 }
345 return result;
346}
347
348namespace {
349
350struct PersistenceHelper {
351 static PersistenceHelper const &get() {
352 static PersistenceHelper const instance;
353 return instance;
354 }
355
356 // Schema and keys for the catalog that stores Connection objects.
357 // Considered as a graph, 'from' and 'to' identify vertices, and
358 // 'transform' identifies an edge.
359 table::Schema schema;
360 table::Key<std::string> fromSysName;
361 table::Key<std::string> fromSysDetectorName;
362 table::Key<std::string> toSysName;
363 table::Key<std::string> toSysDetectorName;
365
366private:
367 PersistenceHelper()
368 : schema(),
369 fromSysName(
370 schema.addField<std::string>("fromSysName", "Camera coordinate system name.", "", 0)),
371 fromSysDetectorName(schema.addField<std::string>(
372 "fromSysDetectorName", "Camera coordinate system detector name.", "", 0)),
373 toSysName(schema.addField<std::string>("toSysName", "Camera coordinate system name.", "", 0)),
374 toSysDetectorName(schema.addField<std::string>(
375 "toSysDetectorName", "Camera coordinate system detector name.", "", 0)),
376 transform(schema.addField<int>("transform", "Archive ID of the transform.", "")) {}
377
378 PersistenceHelper(PersistenceHelper const &) = delete;
379 PersistenceHelper(PersistenceHelper &&) = delete;
380
381 PersistenceHelper &operator=(PersistenceHelper const &) = delete;
382 PersistenceHelper &operator=(PersistenceHelper &&) = delete;
383};
384
385// PersistenceHelper for a previous format version; now only supported in
386// reading.
387struct OldPersistenceHelper {
388 static OldPersistenceHelper const &get() {
389 static OldPersistenceHelper const instance;
390 return instance;
391 }
392
393 // Schema and keys for the catalog that stores TransformMap._frameIds.
394 // Considered as a graph, this is a list of all of the vertices with the
395 // integers that identify them in the list of edges below.
396 table::Schema sysSchema;
397 table::Key<std::string> sysName;
398 table::Key<std::string> detectorName;
399 table::Key<int> id;
400
401 // Schema and keys for the catalog that stores
402 // TransformMap._canonicalConnections entries and the associated Transform
403 // extracted from TransformMap._transforms.
404 // Considered as a graph, 'from' and 'to' identify vertices, and
405 // 'transform' identifies an edge.
406 table::Schema connectionSchema;
407 table::Key<int> from;
408 table::Key<int> to;
409 table::Key<int> transform;
410
411 CameraSys makeCameraSys(table::BaseRecord const &record) const {
412 return CameraSys(record.get(sysName), record.get(detectorName));
413 }
414
415private:
416 OldPersistenceHelper()
417 : sysSchema(),
418 sysName(sysSchema.addField<std::string>("sysName", "Camera coordinate system name", "", 0)),
419 detectorName(sysSchema.addField<std::string>("detectorName",
420 "Camera coordinate system detector name", "", 0)),
421 id(sysSchema.addField<int>("id", "AST ID of the Frame for the CameraSys", "")),
422 connectionSchema(),
423 from(connectionSchema.addField<int>("from", "AST ID of the Frame this transform maps from.",
424 "")),
425 to(connectionSchema.addField<int>("to", "AST ID of the Frame this transform maps to.", "")),
426 transform(connectionSchema.addField<int>("transform", "Archive ID of the transform.", "")) {}
427
428 OldPersistenceHelper(OldPersistenceHelper const &) = delete;
429 OldPersistenceHelper(OldPersistenceHelper &&) = delete;
430
431 OldPersistenceHelper &operator=(OldPersistenceHelper const &) = delete;
432 OldPersistenceHelper &operator=(OldPersistenceHelper &&) = delete;
433};
434
435} // namespace
436
437std::string TransformMap::getPersistenceName() const { return "TransformMap"; }
438
439std::string TransformMap::getPythonModule() const { return "lsst.afw.cameraGeom"; }
440
442 auto const &keys = PersistenceHelper::get();
443
444 auto cat = handle.makeCatalog(keys.schema);
445 for (auto const &connection : _connections) {
446 auto record = cat.addNew();
447 record->set(keys.fromSysName, connection.fromSys.getSysName());
448 record->set(keys.fromSysDetectorName, connection.fromSys.getDetectorName());
449 record->set(keys.toSysName, connection.toSys.getSysName());
450 record->set(keys.toSysDetectorName, connection.toSys.getDetectorName());
451 record->set(keys.transform, handle.put(connection.transform));
452 }
453 handle.saveCatalog(cat);
454}
455
457public:
458 Factory() : PersistableFactory("TransformMap") {}
459
460 std::shared_ptr<Persistable> readOld(InputArchive const &archive, CatalogVector const &catalogs) const {
461 auto const &keys = OldPersistenceHelper::get();
462
463 LSST_ARCHIVE_ASSERT(catalogs.size() == 2u);
464 auto const &sysCat = catalogs[0];
465 auto const &connectionCat = catalogs[1];
466 LSST_ARCHIVE_ASSERT(sysCat.getSchema() == keys.sysSchema);
467 LSST_ARCHIVE_ASSERT(connectionCat.getSchema() == keys.connectionSchema);
468 LSST_ARCHIVE_ASSERT(sysCat.size() == connectionCat.size() + 1);
469 LSST_ARCHIVE_ASSERT(sysCat.isSorted(keys.id));
470
472 for (auto const &sysRecord : sysCat) {
473 auto sys = keys.makeCameraSys(sysRecord);
474 sysById.emplace(sysRecord.get(keys.id), sys);
475 }
476
477 auto const referenceSysIter = sysById.find(1);
478 LSST_ARCHIVE_ASSERT(referenceSysIter != sysById.end());
479 std::vector<Connection> connections;
480 for (auto const &connectionRecord : connectionCat) {
481 auto const fromSysIter = sysById.find(connectionRecord.get(keys.from));
482 LSST_ARCHIVE_ASSERT(fromSysIter != sysById.end());
483 auto const toSysIter = sysById.find(connectionRecord.get(keys.to));
484 LSST_ARCHIVE_ASSERT(toSysIter != sysById.end());
485 auto const transform =
486 archive.get<geom::TransformPoint2ToPoint2>(connectionRecord.get(keys.transform));
487
488 connections.push_back(Connection{transform, fromSysIter->second, toSysIter->second});
489 }
490
491 connections = standardizeConnections(referenceSysIter->second, std::move(connections));
492 return std::shared_ptr<TransformMap>(new TransformMap(std::move(connections)));
493 }
494
496 CatalogVector const &catalogs) const override {
497 if (catalogs.size() == 2u) {
498 return readOld(archive, catalogs);
499 }
500
501 auto const &keys = PersistenceHelper::get();
502
503 LSST_ARCHIVE_ASSERT(catalogs.size() == 1u);
504 auto const &cat = catalogs[0];
505 LSST_ARCHIVE_ASSERT(cat.getSchema() == keys.schema);
506
507 std::vector<Connection> connections;
508 for (auto const &record : cat) {
509 CameraSys const fromSys(record.get(keys.fromSysName), record.get(keys.fromSysDetectorName));
510 CameraSys const toSys(record.get(keys.toSysName), record.get(keys.toSysDetectorName));
511 auto const transform = archive.get<geom::TransformPoint2ToPoint2>(record.get(keys.transform));
512 connections.push_back(Connection{transform, fromSys, toSys});
513 }
514
515 // Deserialized connections should already be standardized, but be
516 // defensive anyway.
517 auto const referenceSys = getReferenceSys(connections);
518 connections = standardizeConnections(referenceSys, std::move(connections));
519 return std::shared_ptr<TransformMap>(new TransformMap(std::move(connections)));
520 }
521
522 static Factory const registration;
523};
524
526
527} // namespace cameraGeom
528
529namespace table {
530namespace io {
531
532template class PersistableFacade<cameraGeom::TransformMap>;
533
534} // namespace io
535} // namespace table
536
537} // namespace afw
538} // 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:619
#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
static int constexpr CURRENT
index of current frame
Definition FrameSet.h:105
int getNFrame() const
Get FrameSet_NFrame "NFrame": number of Frames in the FrameSet, starting from 1.
Definition FrameSet.h:316
static int constexpr BASE
index of base frame
Definition FrameSet.h:104
Camera coordinate system; used as a key in in TransformMap.
Definition CameraSys.h:83
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.
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.
bool getFocalPlaneParity() const noexcept
Return True if there is an x-axis flip from FOCAL_PLANE to FIELD_ANGLE, false otherwise.
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
TransformMap(TransformMap const &other)=delete
std::unordered_map< CameraSys, std::shared_ptr< geom::TransformPoint2ToPoint2 > > Transforms
std::string getPythonModule() const override
Return the fully-qualified Python module that should be imported to guarantee that its factory is reg...
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.
std::unique_ptr< ast::FrameSet > makeFrameSet(std::vector< std::shared_ptr< DetectorBase > > const &detectors, std::string const &focalPlaneUnit="mm") const
Return an AST FrameSet with the standard transforms for this camera.
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.
ndarray::Array< double, 2, 2 > dataFromArray(Array const &arr) const override
Definition Endpoint.cc:123
std::vector< double > dataFromPoint(Point const &point) const override
Definition Endpoint.cc:114
Point pointFromData(std::vector< double > const &data) const override
Get a single point from raw data.
Definition Endpoint.cc:137
Array arrayFromData(ndarray::Array< double, 2, 2 > const &data) const override
Get an array of points from raw data.
Definition Endpoint.cc:147
A class used as a handle to a particular field in a table.
Definition Key.h:53
Defines the fields and offsets for a table.
Definition Schema.h:51
std::shared_ptr< Persistable > get(int id) const
Load the Persistable with the given ID and return it.
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.
int put(Persistable const *obj, bool permissive=false)
Save an object to the archive and return a unique ID that can be used to retrieve it from an InputArc...
A base class for factory classes used to reconstruct objects from records.
PersistableFactory(std::string const &name)
Constructor for the factory.
io::OutputArchiveHandle OutputArchiveHandle
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 make_shared(T... args)
T move(T... args)
transform(self, *, outOffset=None, outFlipX=False, outFlipY=False)
CameraSys const FIELD_ANGLE
Field angle coordinates: Angle of a principal ray relative to the optical axis (x,...
Definition CameraSys.cc:32
CameraSys const FOCAL_PLANE
Focal plane coordinates: Position on a 2-d planar approximation to the focal plane (x,...
Definition CameraSys.cc:30
CameraSysPrefix const PIXELS
Pixel coordinates: Nominal position on the entry surface of a given detector (x, y unbinned pixels).
Definition CameraSys.cc:34
std::ostream & operator<<(std::ostream &os, CameraSysPrefix const &detSysPrefix)
Definition CameraSys.cc:47
CameraSysPrefix const ACTUAL_PIXELS
The actual pixels where the photon lands and electrons are generated (x,y unbinned) This takes into a...
Definition CameraSys.cc:38
Point< double, 2 > Point2D
Definition Point.h:324
STL namespace.
T push_back(T... args)
T reserve(T... args)
T size(T... args)
T str(T... args)
Representation of a single edge in the graph defined by a TransformMap.
void reverse()
Reverse the connection, by swapping fromSys and toSys and inverting the transform.
std::shared_ptr< geom::TransformPoint2ToPoint2 const > transform
T swap(T... args)
T throw_with_nested(T... args)