26 #include <type_traits> 29 #include "boost/optional.hpp" 35 #include "lsst/afw/table/io/Persistable.cc" 40 namespace cameraGeom {
56 auto mapping = _getMapping(fromSys, toSys);
63 auto mapping = _getMapping(fromSys, toSys);
71 return std::make_shared<geom::TransformPoint2ToPoint2>(*_getMapping(fromSys, toSys));
74 int TransformMap::_getFrame(
CameraSys const &system)
const {
76 return _frameIds.
at(system);
79 buffer <<
"Unsupported coordinate system: " << system;
86 return _transforms->
getMapping(_getFrame(fromSys), _getFrame(toSys));
96 _canonicalConnections(
std::move(canonicalConnections))
102 struct PersistenceHelper {
104 static PersistenceHelper
const &
get() {
105 static PersistenceHelper
const instance;
127 CameraSys makeCameraSys(table::BaseRecord
const & record)
const {
128 return CameraSys(record.get(sysName), record.get(detectorName));
133 PersistenceHelper() :
135 sysName(sysSchema.addField<
std::string>(
"sysName",
"Camera coordinate system name",
"", 0)),
137 "Camera coordinate system detector name",
"", 0)),
138 id(sysSchema.addField<
int>(
"id",
"AST ID of the Frame for the CameraSys",
"")),
140 from(connectionSchema.addField<
int>(
"from",
"AST ID of the Frame this transform maps from.",
"")),
141 to(connectionSchema.addField<
int>(
"to",
"AST ID of the Frame this transform maps to.",
"")),
142 transform(connectionSchema.addField<
int>(
"transform",
"Archive ID of the transform.",
""))
144 sysSchema.getCitizen().markPersistent();
145 connectionSchema.getCitizen().markPersistent();
148 PersistenceHelper(PersistenceHelper
const &) =
delete;
149 PersistenceHelper(PersistenceHelper &&) =
delete;
151 PersistenceHelper &
operator=(PersistenceHelper
const &) =
delete;
152 PersistenceHelper &
operator=(PersistenceHelper &&) =
delete;
158 if (sys.hasDetectorName()) {
160 r += sys.getDetectorName();
168 std::string TransformMap::getPersistenceName()
const {
169 return "TransformMap";
172 std::string TransformMap::getPythonModule()
const {
173 return "lsst.afw.cameraGeom";
177 auto const &
keys = PersistenceHelper::get();
179 auto sysCat = handle.makeCatalog(
keys.sysSchema);
180 for (
auto const & sysPair : _frameIds) {
181 auto sysRecord = sysCat.addNew();
182 sysRecord->set(
keys.sysName, sysPair.first.getSysName());
183 sysRecord->set(
keys.detectorName, sysPair.first.getDetectorName());
184 sysRecord->set(
keys.id, sysPair.second);
186 sysCat.sort(
keys.id);
187 handle.saveCatalog(sysCat);
189 auto connectionCat = handle.makeCatalog(
keys.connectionSchema);
190 for (
auto const & connectionPair : _canonicalConnections) {
191 auto connectionRecord = connectionCat.addNew();
192 connectionRecord->set(
keys.from, connectionPair.first);
193 connectionRecord->set(
keys.to, connectionPair.second);
195 *_transforms->getMapping(connectionPair.first, connectionPair.second));
196 connectionRecord->set(
keys.transform, handle.put(
transform));
198 handle.saveCatalog(connectionCat);
204 Factory() : PersistableFactory(
"TransformMap") {}
208 auto const &
keys = PersistenceHelper::get();
211 auto const & sysCat = catalogs[0];
212 auto const & connectionCat = catalogs[1];
220 for (
auto const & sysRecord : sysCat) {
221 auto sys =
keys.makeCameraSys(sysRecord);
222 frameIdsBySys.emplace(sys, sysRecord.get(
keys.id));
226 auto baseFrameIter = framesById.
find(1);
228 auto frameSet = std::make_unique<ast::FrameSet>(baseFrameIter->second);
230 for (
auto const & connectionRecord : connectionCat) {
231 int const fromId = connectionRecord.get(
keys.from);
232 int const toId = connectionRecord.get(
keys.to);
234 connectionRecord.get(
keys.transform)
236 canonicalConnections.emplace_back(fromId, toId);
237 auto toFrameIter = framesById.
find(toId);
239 frameSet->addFrame(fromId, *
transform->getMapping(), toFrameIter->second);
267 if (fromSys == toSys) {
269 buffer <<
"Identity connection detected for " << fromSys <<
".";
272 if (!transform->hasForward()) {
274 buffer <<
"Connection from " << fromSys <<
" to " 275 << toSys <<
" has no forward transform.";
278 if (!transform->hasInverse()) {
280 buffer <<
"Connection from " << fromSys <<
" to " 281 << toSys <<
" has no inverse transform.";
294 for (
auto const & item : transforms) {
295 other.
connect(fromSys, item.first, item.second);
297 _connections.
insert(_connections.
end(), other._connections.
begin(), other._connections.
end());
307 template <
typename Callable>
311 explicit OnScopeExit(Callable callable) : _callable(
std::move(callable)) {}
313 ~OnScopeExit() noexcept(noexcept(std::declval<Callable>())) {
322 template <
typename Callable>
323 OnScopeExit<Callable> onScopeExit(Callable callable) {
324 return OnScopeExit<Callable>(
std::move(callable));
338 auto findFrameIdForSys = [&frameIds](
CameraSys const & sys) -> boost::optional<int> {
339 auto iter = frameIds.
find(sys);
340 if (iter != frameIds.
end()) {
341 return boost::optional<int>(iter->second);
351 frameIds.
emplace(sys, ++nFrames);
357 auto frameSet = std::make_unique<ast::FrameSet>(addFrameForSys(_reference));
360 auto guard = onScopeExit(
362 for (
auto const & c : _connections) { c.processed =
false; }
367 while (nProcessedTotal != _connections.size()) {
372 for (
auto const & c : _connections) {
373 if (c.processed)
continue;
374 auto fromId = findFrameIdForSys(c.fromSys);
375 auto toId = findFrameIdForSys(c.toSys);
376 if (fromId && toId) {
378 buffer <<
"Duplicate connection from " << c.fromSys <<
" to " << c.toSys <<
".";
381 frameSet->addFrame(*fromId, *c.transform->getMapping(), addFrameForSys(c.toSys));
384 ++nProcessedThisPass;
386 frameSet->addFrame(*toId, *c.transform->inverted()->getMapping(), addFrameForSys(c.fromSys));
389 ++nProcessedThisPass;
395 if (nProcessedThisPass == 0u) {
399 for (
auto const & c : _connections) {
401 orphaned.
insert(c.fromSys);
406 auto o = orphaned.
begin();
407 buffer <<
"Orphaned coordinate system(s) found: " << *o;
408 for (++o; o != orphaned.
end(); ++o) {
409 buffer <<
", " << *o;
415 nProcessedTotal += nProcessedThisPass;
420 assert(
frameSet->getNFrame() == nFrames);
434 template class PersistableFacade<cameraGeom::TransformMap>;
Camera coordinate system; used as a key in in TransformMap.
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.
Transform< Point2Endpoint, Point2Endpoint > TransformPoint2ToPoint2
Array arrayFromData(ndarray::Array< double, 2, 2 > const &data) const override
Get an array of points from raw data.
A base class for image defects.
Frame is used to represent a coordinate system.
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
T throw_with_nested(T... args)
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.
ItemVariant const * other
std::shared_ptr< Mapping > getMapping(int from=BASE, int to=CURRENT) const
Obtain a Mapping that converts between two Frames in a FrameSet.
ndarray::Array< double, 2, 2 > dataFromArray(Array const &arr) const override
T emplace_back(T... args)