23#include <unordered_set>
41static auto LOGGER =
LOG_GET(
"lsst.afw.cameraGeom.TransformMap");
46 if (sys.hasDetectorName()) {
48 r += sys.getDetectorName();
78 CameraSys
const & reference,
81 if (connections.
empty()) {
83 pex::exceptions::InvalidParameterError,
84 "Cannot create a TransformMap with no connections."
89 auto firstUnprocessed = connections.
begin();
101 LOGLS_DEBUG(LOGGER,
"Standardizing: starting with reference " << reference);
102 while (!currentSystems.
empty()) {
103 LOGLS_DEBUG(LOGGER,
"Standardizing: beginning iteration with currentSystems={ ");
104 for (
auto const & sys : currentSystems) {
105 LOGLS_DEBUG(LOGGER,
"Standardizing: " << sys <<
", ");
110 for (
auto connection = firstUnprocessed; connection != connections.
end(); ++connection) {
111 bool related = currentSystems.count(connection->fromSys) > 0;
112 if (!related && currentSystems.count(connection->toSys)) {
113 LOGLS_DEBUG(LOGGER,
"Standardizing: reversing " << (*connection));
115 connection->reverse();
119 if (connection->toSys == connection->fromSys) {
121 ss <<
"Identity connection found: " << (*connection) <<
".";
122 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, ss.
str());
124 if (knownSystems.
count(connection->toSys)) {
126 ss <<
"Multiple paths between reference " << reference
127 <<
" and " << connection->toSys <<
".";
128 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, ss.
str());
130 LOGLS_DEBUG(LOGGER,
"Standardizing: adding " << (*connection));
131 nextSystems.
insert(connection->toSys);
132 knownSystems.
insert(connection->toSys);
133 std::swap(*firstUnprocessed, *connection);
137 currentSystems.swap(nextSystems);
142 if (firstUnprocessed != connections.
end()) {
144 ss <<
"Disconnected connection(s) found: " << (*firstUnprocessed);
146 for (
auto connection = firstUnprocessed; connection != connections.
end(); ++connection) {
147 ss <<
", " << (*connection);
150 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, ss.
str());
159 return connections.
front().fromSys;
179 for (
auto const & pair : transforms) {
194 new TransformMap(standardizeConnections(reference, connections))
204 auto mapping = _getMapping(fromSys, toSys);
211 auto mapping = _getMapping(fromSys, toSys);
219 return std::make_shared<geom::TransformPoint2ToPoint2>(*_getMapping(fromSys, toSys));
222int TransformMap::_getFrame(
CameraSys const &system)
const {
224 return _frameIds.
at(system);
227 buffer <<
"Unsupported coordinate system: " << system;
233 CameraSys
const &toSys)
const {
234 return _frameSet->
getMapping(_getFrame(fromSys), _getFrame(toSys));
241 _connections(
std::move(connections))
246 assert(!_connections.empty());
257 _frameIds.
emplace(sys, ++nFrames);
264 _frameSet = std::make_unique<ast::FrameSet>(addFrameForSys(getReferenceSys(_connections)));
266 for (
auto const & connection : _connections) {
267 auto fromSysIdIter = _frameIds.
find(connection.fromSys);
268 assert(fromSysIdIter != _frameIds.
end());
269 _frameSet->
addFrame(fromSysIdIter->second, *connection.transform->getMapping(),
270 addFrameForSys(connection.toSys));
275 assert(_frameSet->
getNFrame() == nFrames);
283struct PersistenceHelper {
285 static PersistenceHelper
const & get() {
286 static PersistenceHelper
const instance;
302 PersistenceHelper() :
305 "Camera coordinate system name.",
"", 0)),
307 "Camera coordinate system detector name.",
"", 0)),
309 "Camera coordinate system name.",
"", 0)),
311 "Camera coordinate system detector name.",
"", 0)),
312 transform(
schema.addField<int>(
"transform",
"Archive ID of the transform.",
""))
315 PersistenceHelper(PersistenceHelper
const &) =
delete;
316 PersistenceHelper(PersistenceHelper &&) =
delete;
318 PersistenceHelper & operator=(PersistenceHelper
const &) =
delete;
319 PersistenceHelper & operator=(PersistenceHelper &&) =
delete;
326struct OldPersistenceHelper {
328 static OldPersistenceHelper
const & get() {
329 static OldPersistenceHelper
const instance;
351 CameraSys makeCameraSys(table::BaseRecord
const & record)
const {
357 OldPersistenceHelper() :
359 sysName(
sysSchema.addField<
std::string>(
"sysName",
"Camera coordinate system name",
"", 0)),
361 "Camera coordinate system detector name",
"", 0)),
362 id(
sysSchema.addField<int>(
"id",
"AST ID of the Frame for the CameraSys",
"")),
364 from(
connectionSchema.addField<int>(
"from",
"AST ID of the Frame this transform maps from.",
"")),
365 to(
connectionSchema.addField<int>(
"to",
"AST ID of the Frame this transform maps to.",
"")),
369 OldPersistenceHelper(OldPersistenceHelper
const &) =
delete;
370 OldPersistenceHelper(OldPersistenceHelper &&) =
delete;
372 OldPersistenceHelper & operator=(OldPersistenceHelper
const &) =
delete;
373 OldPersistenceHelper & operator=(OldPersistenceHelper &&) =
delete;
381std::string TransformMap::getPersistenceName()
const {
382 return "TransformMap";
386 return "lsst.afw.cameraGeom";
389void TransformMap::write(OutputArchiveHandle& handle)
const {
390 auto const &
keys = PersistenceHelper::get();
392 auto cat = handle.makeCatalog(
keys.schema);
393 for (
auto const & connection : _connections) {
394 auto record = cat.addNew();
395 record->set(
keys.fromSysName, connection.fromSys.getSysName());
396 record->set(
keys.fromSysDetectorName, connection.fromSys.getDetectorName());
397 record->set(
keys.toSysName, connection.toSys.getSysName());
398 record->set(
keys.toSysDetectorName, connection.toSys.getDetectorName());
399 record->set(
keys.transform, handle.put(connection.transform));
401 handle.saveCatalog(cat);
411 auto const & keys = OldPersistenceHelper::get();
414 auto const & sysCat = catalogs[0];
415 auto const & connectionCat = catalogs[1];
422 for (
auto const & sysRecord : sysCat) {
423 auto sys = keys.makeCameraSys(sysRecord);
424 sysById.
emplace(sysRecord.get(keys.id), sys);
427 auto const referenceSysIter = sysById.
find(1);
430 for (
auto const & connectionRecord : connectionCat) {
431 auto const fromSysIter = sysById.
find(connectionRecord.get(keys.from));
433 auto const toSysIter = sysById.
find(connectionRecord.get(keys.to));
435 auto const transform = archive.
get<geom::TransformPoint2ToPoint2>(
436 connectionRecord.get(keys.transform)
442 connections = standardizeConnections(referenceSysIter->second,
std::move(connections));
448 if (catalogs.
size() == 2u) {
449 return readOld(archive, catalogs);
452 auto const & keys = PersistenceHelper::get();
455 auto const & cat = catalogs[0];
459 for (
auto const & record : cat) {
460 CameraSys const fromSys(record.get(keys.fromSysName), record.get(keys.fromSysDetectorName));
461 CameraSys const toSys(record.get(keys.toSysName), record.get(keys.toSysDetectorName));
462 auto const transform = archive.
get<geom::TransformPoint2ToPoint2>(record.get(keys.transform));
468 auto const referenceSys = getReferenceSys(connections);
469 connections = standardizeConnections(referenceSys,
std::move(connections));
484template class PersistableFacade<cameraGeom::TransformMap>;
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
LSST DM logging module built on log4cxx.
#define LOG_GET(logger)
Returns a Log object associated with logger.
#define LOGLS_DEBUG(logger, message)
Log a debug-level message using an iostream-based interface.
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
Frame is used to represent a coordinate system.
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,...
std::shared_ptr< Mapping > getMapping(int from=BASE, int to=CURRENT) const
Obtain a Mapping that converts between two Frames in a FrameSet.
int getNFrame() const
Get FrameSet_NFrame "NFrame": number of Frames in the FrameSet, starting from 1.
Camera coordinate system; used as a key in in TransformMap.
void swap(CameraSys &other) noexcept
An endpoint for lsst::geom::Point2D.
ndarray::Array< double, 2, 2 > dataFromArray(Array const &arr) const override
Get raw data from an array of points.
std::vector< double > dataFromPoint(Point const &point) const override
Get raw data from a single point.
Point pointFromData(std::vector< double > const &data) const override
Get a single point from raw data.
Array arrayFromData(ndarray::Array< double, 2, 2 > const &data) const override
Get an array of points from raw data.
A vector of catalogs used by Persistable.
A base class for factory classes used to reconstruct objects from records.
PersistableFactory(std::string const &name)
Constructor for the factory.
Reports invalid arguments.
std::ostream & operator<<(std::ostream &os, CameraSysPrefix const &detSysPrefix)
T throw_with_nested(T... args)