23 #include <unordered_set> 35 namespace cameraGeom {
42 static auto LOGGER =
LOG_GET(
"afw.cameraGeom.TransformMap");
47 if (sys.hasDetectorName()) {
49 r += sys.getDetectorName();
79 CameraSys
const & reference,
82 if (connections.
empty()) {
84 pex::exceptions::InvalidParameterError,
85 "Cannot create a TransformMap with no connections." 90 auto firstUnprocessed = connections.
begin();
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 <<
", ");
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));
116 connection->reverse();
120 if (connection->toSys == connection->fromSys) {
122 ss <<
"Identity connection found: " << (*connection) <<
".";
123 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, ss.
str());
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());
131 LOGLS_DEBUG(LOGGER,
"Standardizing: adding " << (*connection));
132 nextSystems.
insert(connection->toSys);
133 knownSystems.
insert(connection->toSys);
134 std::swap(*firstUnprocessed, *connection);
138 currentSystems.swap(nextSystems);
143 if (firstUnprocessed != connections.
end()) {
145 ss <<
"Disconnected connection(s) found: " << (*firstUnprocessed);
147 for (
auto connection = firstUnprocessed; connection != connections.
end(); ++connection) {
148 ss <<
", " << (*connection);
151 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, ss.
str());
171 return os << connection.
fromSys <<
"->" << connection.
toSys;
180 for (
auto const & pair : transforms) {
195 new TransformMap(standardizeConnections(reference, connections))
205 auto mapping = _getMapping(fromSys, toSys);
212 auto mapping = _getMapping(fromSys, toSys);
220 return std::make_shared<geom::TransformPoint2ToPoint2>(*_getMapping(fromSys, toSys));
223 int TransformMap::_getFrame(
CameraSys const &system)
const {
225 return _frameIds.at(system);
228 buffer <<
"Unsupported coordinate system: " << system;
235 return _frameSet->getMapping(_getFrame(fromSys), _getFrame(toSys));
247 assert(!_connections.empty());
258 _frameIds.emplace(sys, ++nFrames);
265 _frameSet = std::make_unique<ast::FrameSet>(addFrameForSys(getReferenceSys(_connections)));
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));
276 assert(_frameSet->getNFrame() == nFrames);
284 struct PersistenceHelper {
286 static PersistenceHelper
const &
get() {
287 static PersistenceHelper
const instance;
303 PersistenceHelper() :
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.",
""))
316 PersistenceHelper(PersistenceHelper
const &) =
delete;
317 PersistenceHelper(PersistenceHelper &&) =
delete;
319 PersistenceHelper &
operator=(PersistenceHelper
const &) =
delete;
320 PersistenceHelper &
operator=(PersistenceHelper &&) =
delete;
327 struct OldPersistenceHelper {
329 static OldPersistenceHelper
const &
get() {
330 static OldPersistenceHelper
const instance;
352 CameraSys makeCameraSys(table::BaseRecord
const & record)
const {
353 return CameraSys(record.get(sysName), record.get(detectorName));
358 OldPersistenceHelper() :
360 sysName(sysSchema.addField<
std::string>(
"sysName",
"Camera coordinate system name",
"", 0)),
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.",
""))
370 OldPersistenceHelper(OldPersistenceHelper
const &) =
delete;
371 OldPersistenceHelper(OldPersistenceHelper &&) =
delete;
373 OldPersistenceHelper &
operator=(OldPersistenceHelper
const &) =
delete;
374 OldPersistenceHelper &
operator=(OldPersistenceHelper &&) =
delete;
382 std::string TransformMap::getPersistenceName()
const {
383 return "TransformMap";
386 std::string TransformMap::getPythonModule()
const {
387 return "lsst.afw.cameraGeom";
391 auto const &
keys = PersistenceHelper::get();
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));
402 handle.saveCatalog(cat);
408 Factory() : PersistableFactory(
"TransformMap") {}
412 auto const &
keys = OldPersistenceHelper::get();
415 auto const & sysCat = catalogs[0];
416 auto const & connectionCat = catalogs[1];
423 for (
auto const & sysRecord : sysCat) {
424 auto sys =
keys.makeCameraSys(sysRecord);
425 sysById.emplace(sysRecord.get(
keys.id), sys);
428 auto const referenceSysIter = sysById.find(1);
431 for (
auto const & connectionRecord : connectionCat) {
432 auto const fromSysIter = sysById.find(connectionRecord.get(
keys.from));
434 auto const toSysIter = sysById.find(connectionRecord.get(
keys.to));
437 connectionRecord.get(
keys.transform)
443 connections = standardizeConnections(referenceSysIter->second,
std::move(connections));
449 if (catalogs.
size() == 2u) {
450 return readOld(archive, catalogs);
453 auto const &
keys = PersistenceHelper::get();
456 auto const & cat = catalogs[0];
460 for (
auto const & record : cat) {
469 auto const referenceSys = getReferenceSys(connections);
470 connections = standardizeConnections(referenceSys,
std::move(connections));
485 template class PersistableFacade<cameraGeom::TransformMap>;
Camera coordinate system; used as a key in in TransformMap.
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
A base class for factory classes used to reconstruct objects from records.
Point pointFromData(std::vector< double > const &data) const override
Get a single point from raw data.
std::ostream & operator<<(std::ostream &os, CameraSysPrefix const &detSysPrefix)
Transform< Point2Endpoint, Point2Endpoint > TransformPoint2ToPoint2
LSST DM logging module built on log4cxx.
Array arrayFromData(ndarray::Array< double, 2, 2 > const &data) const override
Get an array of points from raw data.
#define LOGLS_DEBUG(logger, message)
Log a debug-level message using an iostream-based interface.
A base class for image defects.
Frame is used to represent a coordinate system.
T throw_with_nested(T... args)
void swap(CameraSys &other) noexcept
std::vector< double > dataFromPoint(Point const &point) const override
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
A vector of catalogs used by Persistable.
Reports invalid arguments.
io::OutputArchiveHandle OutputArchiveHandle
An endpoint for lsst::geom::Point2D.
#define LOG_GET(logger)
Returns a Log object associated with logger.
ndarray::Array< double, 2, 2 > dataFromArray(Array const &arr) const override