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());
160 return connections.
front().fromSys;
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;
234 CameraSys
const &toSys)
const {
235 return _frameSet->
getMapping(_getFrame(fromSys), _getFrame(toSys));
242 _connections(
std::move(connections))
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() :
306 "Camera coordinate system name.",
"", 0)),
308 "Camera coordinate system detector name.",
"", 0)),
310 "Camera coordinate system name.",
"", 0)),
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 {
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.",
"")),
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";
390 void TransformMap::write(OutputArchiveHandle& handle)
const {
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);
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);
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) {
461 CameraSys const fromSys(record.get(
keys.fromSysName), record.get(
keys.fromSysDetectorName));
462 CameraSys const toSys(record.get(
keys.toSysName), record.get(
keys.toSysDetectorName));
469 auto const referenceSys = getReferenceSys(connections);
470 connections = standardizeConnections(referenceSys,
std::move(connections));
485 template 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)
Transform< Point2Endpoint, Point2Endpoint > TransformPoint2ToPoint2
FilterProperty & operator=(FilterProperty const &)=default
Point< double, 2 > Point2D
A base class for image defects.
T throw_with_nested(T... args)