LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
Camera.cc
Go to the documentation of this file.
1 /*
2  * Developed for the LSST Data Management System.
3  * This product includes software developed by the LSST Project
4  * (https://www.lsst.org).
5  * See the COPYRIGHT file at the top-level directory of this distribution
6  * for details of code ownership.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
27 
28 namespace lsst {
29 namespace afw {
30 namespace cameraGeom {
31 
32 namespace {
33 
34 // Set this as a function to ensure FOCAL_PLANE is defined before use.
35 CameraSys const getNativeCameraSys() { return FOCAL_PLANE; }
36 
37 } // anonymoous
38 
39 Camera::~Camera() noexcept = default;
40 
41 Camera::Builder Camera::rebuild() const {
42  return Camera::Builder(*this);
43 }
44 
46  CameraSys const &cameraSys) const {
47  auto nativePoint = transform(point, cameraSys, getNativeCameraSys());
48 
49  DetectorList detectorList;
50  for (auto const &item : getIdMap()) {
51  auto detector = item.second;
52  auto pointPixels = detector->transform(nativePoint, getNativeCameraSys(), PIXELS);
53  if (lsst::geom::Box2D(detector->getBBox()).contains(pointPixels)) {
54  detectorList.push_back(std::move(detector));
55  }
56  }
57  return detectorList;
58 }
59 
61  CameraSys const &cameraSys) const {
62  std::vector<DetectorList> detectorListList(pointList.size());
63  auto nativePointList = transform(pointList, cameraSys, getNativeCameraSys());
64 
65  for (auto const &item: getIdMap()) {
66  auto const &detector = item.second;
67  auto pointPixelsList = detector->transform(nativePointList, getNativeCameraSys(), PIXELS);
68  for (std::size_t i = 0; i < pointPixelsList.size(); ++i) {
69  auto const &pointPixels = pointPixelsList[i];
70  if (lsst::geom::Box2D(detector->getBBox()).contains(pointPixels)) {
71  detectorListList[i].push_back(detector);
72  }
73  }
74  }
75  return detectorListList;
76 }
77 
79  CameraSys const &toSys) const {
80  return getTransformMap()->getTransform(fromSys, toSys);
81 }
82 
84  CameraSys const &toSys) const {
85  auto transform = getTransform(fromSys, toSys);
86  return transform->applyForward(point);
87 }
88 
90  CameraSys const &fromSys,
91  CameraSys const &toSys) const {
92  auto transform = getTransform(fromSys, toSys);
93  return transform->applyForward(points);
94 }
95 
96 std::shared_ptr<Detector::InCameraBuilder> Camera::makeDetectorBuilder(std::string const & name, int id) {
98 }
99 
100 std::shared_ptr<Detector::InCameraBuilder> Camera::makeDetectorBuilder(Detector const & detector) {
101  return std::shared_ptr<Detector::InCameraBuilder>(new Detector::InCameraBuilder(detector));
102 }
103 
104 
105 std::vector<TransformMap::Connection> const & Camera::getDetectorBuilderConnections(
106  Detector::InCameraBuilder const & detector
107 ) {
108  return detector._connections;
109 }
110 
111 
112 namespace {
113 
114 class PersistenceHelper {
115 public:
116 
117  static PersistenceHelper const & get() {
118  static PersistenceHelper const instance;
119  return instance;
120  }
121 
122  table::Schema schema;
123  table::Key<std::string> name;
124  table::Key<std::string> pupilFactoryName;
125  table::Key<int> transformMap;
126 
127 private:
128 
129  PersistenceHelper() :
130  schema(),
131  name(schema.addField<std::string>("name", "Camera name", "", 0)),
132  pupilFactoryName(schema.addField<std::string>("pupilFactoryName",
133  "Fully-qualified name of a Python PupilFactory class",
134  "", 0)),
135  transformMap(schema.addField<int>("transformMap", "archive ID for Camera's TransformMap"))
136  {
137  }
138 
139  PersistenceHelper(PersistenceHelper const &) = delete;
140  PersistenceHelper(PersistenceHelper &&) = delete;
141 
142  PersistenceHelper & operator=(PersistenceHelper const &) = delete;
143  PersistenceHelper & operator=(PersistenceHelper &&) = delete;
144 
145 };
146 
147 } // anonymous
148 
149 void Camera::write(OutputArchiveHandle& handle) const {
151  auto const & keys = PersistenceHelper::get();
152  auto cat = handle.makeCatalog(keys.schema);
153  auto record = cat.addNew();
154  record->set(keys.name, getName());
155  record->set(keys.pupilFactoryName, getPupilFactoryName());
156  record->set(keys.transformMap, handle.put(getTransformMap()));
157  handle.saveCatalog(cat);
158 }
159 
161 public:
162 
163  Factory() : table::io::PersistableFactory("Camera") {}
164 
166  CatalogVector const& catalogs) const override {
167  // can't use make_shared because ctor is protected
168  return std::shared_ptr<Camera>(new Camera(archive, catalogs));
169  }
170 
171  static Factory const registration;
172 
173 };
174 
176 
177 Camera::Camera(std::string const & name, DetectorList detectors,
179  DetectorCollection(std::move(detectors)),
180  _name(name),
181  _pupilFactoryName(pupilFactoryName),
182  _transformMap(std::move(transformMap))
183 {}
184 
185 Camera::Camera(table::io::InputArchive const & archive, table::io::CatalogVector const & catalogs) :
186  DetectorCollection(archive, catalogs)
187  // deferred initalization for data members is not ideal, but better than
188  // trying to initialize them before validating the archive
189 {
190  auto const & keys = PersistenceHelper::get();
191  LSST_ARCHIVE_ASSERT(catalogs.size() >= 2u);
192  auto const & cat = catalogs[1];
193  LSST_ARCHIVE_ASSERT(cat.getSchema() == keys.schema);
194  LSST_ARCHIVE_ASSERT(cat.size() == 1u);
195  auto const & record = cat.front();
196  _name = record.get(keys.name);
197  _pupilFactoryName = record.get(keys.pupilFactoryName);
198  _transformMap = archive.get<TransformMap>(record.get(keys.transformMap));
199 }
200 
201 std::string Camera::getPersistenceName() const { return "Camera"; }
202 
203 
205 
207  _name(camera.getName()),
208  _pupilFactoryName(camera.getPupilFactoryName())
209 {
210  // Add Detector Builders for all Detectors; does not (yet) include
211  // coordinate transform information.
212  for (auto const & pair : camera.getIdMap()) {
213  BaseCollection::add(Camera::makeDetectorBuilder(*pair.second));
214  }
215  // Iterate over connections in TransformMap, distributing them between the
216  // Camera Builder and the Detector Builders.
217  for (auto const & connection : camera.getTransformMap()->getConnections()) {
218  // asserts below are on Detector, Camera, and TransformMap invariants:
219  // - Connections should always be from native sys to something else.
220  // - The only connections between full-camera and per-detector sys
221  // should be from the camera native sys (FOCAL_PLANE) to the
222  // detector native sys (PIXELS).
223  // - When TransformMap standardizes connections, it should maintain
224  // these directions, as that's consistent with "pointing away" from
225  // the overall reference sys (the camera native sys).
226  if (connection.fromSys.hasDetectorName()) {
227  assert(connection.toSys.getDetectorName() == connection.fromSys.getDetectorName());
228  auto detector = (*this)[connection.fromSys.getDetectorName()];
229  assert(connection.fromSys == detector->getNativeCoordSys());
230  detector->setTransformFromPixelsTo(CameraSysPrefix(connection.toSys.getSysName()),
231  connection.transform);
232  } else {
233  assert(connection.fromSys == getNativeCameraSys());
234  if (!connection.toSys.hasDetectorName()) {
235  _connections.push_back(connection);
236  }
237  // We ignore the FOCAL_PLANE to PIXELS transforms transforms, as
238  // those are always regenerated from the Orientation when we
239  // rebuild the Camera.
240  }
241  }
242 }
243 
244 Camera::Builder::~Builder() noexcept = default;
245 
246 std::shared_ptr<Camera const> Camera::Builder::finish() const {
247  // Make a big vector of all coordinate transform connections;
248  // start with general transforms for the camera as a whole:
249  std::vector<TransformMap::Connection> connections(_connections);
250  // Loop over detectors and add the transforms from FOCAL_PLANE
251  // to PIXELS (via the Orientation), and then any extra transforms
252  // from PIXELS to other things.
253  for (auto const & pair : getIdMap()) {
254  auto const & detectorBuilder = *pair.second;
255  connections.push_back(
257  detectorBuilder.getOrientation().makeFpPixelTransform(detectorBuilder.getPixelSize()),
258  getNativeCameraSys(),
259  detectorBuilder.getNativeCoordSys()
260  }
261  );
262  connections.insert(connections.end(),
263  getDetectorBuilderConnections(detectorBuilder).begin(),
264  getDetectorBuilderConnections(detectorBuilder).end());
265  }
266  // Make a single big TransformMap.
267  auto transformMap = TransformMap::make(getNativeCameraSys(), connections);
268  // Make actual Detector objects, giving each the full TransformMap.
269  DetectorList detectors;
270  detectors.reserve(size());
271  for (auto const & pair : getIdMap()) {
272  auto const & detectorBuilder = *pair.second;
273  detectors.push_back(detectorBuilder.finish(transformMap));
274  }
275  return std::shared_ptr<Camera>(new Camera(_name, std::move(detectors), std::move(transformMap),
276  _pupilFactoryName));
277 }
278 
279 
280 namespace {
281 
282 // Return the first connection in the given range that has toSys as its "to"
283 // endpoint.
284 //
285 // @tparam Iter Iterator that dereferences to `Connection const &`.
286 //
287 template <typename Iter>
288 Iter findConnection(Iter first, Iter last, CameraSys const & toSys) {
289  return std::find_if(
290  first, last,
291  [&toSys](auto const & connection) {
292  return connection.toSys == toSys;
293  }
294  );
295 }
296 
297 } // anonymous
298 
300  CameraSys const & toSys,
302 ) {
303  if (toSys.hasDetectorName()) {
304  throw LSST_EXCEPT(
306  (boost::format("%s should be added to Detector %s, not Camera") %
307  toSys.getSysName() % toSys.getDetectorName()).str()
308  );
309  }
310  auto iter = findConnection(_connections.begin(), _connections.end(), toSys);
311  if (iter == _connections.end()) {
312  _connections.push_back(
313  TransformMap::Connection{transform, getNativeCameraSys(), toSys}
314  );
315  } else {
316  iter->transform = transform;
317  }
318 }
319 
321  auto iter = findConnection(_connections.begin(), _connections.end(), toSys);
322  if (iter != _connections.end()) {
323  _connections.erase(iter);
324  return true;
325  }
326  return false;
327 }
328 
330  auto detector = makeDetectorBuilder(name, id);
331  BaseCollection::add(detector);
332  return detector;
333 }
334 
335 } // namespace cameraGeom
336 
337 namespace table {
338 namespace io {
339 
340 template class PersistableFacade<cameraGeom::Camera>;
341 
342 } // namespace io
343 } // namespace table
344 
345 } // namespace afw
346 } // namespace lsst
int end
table::Key< std::string > name
Definition: Camera.cc:123
table::Key< std::string > pupilFactoryName
Definition: Camera.cc:124
table::Schema schema
Definition: Camera.cc:122
table::Key< int > transformMap
Definition: Camera.cc:125
table::Key< int > detector
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
Definition: Persistable.h:48
A helper class for creating and modifying cameras.
Definition: Camera.h:208
void setTransformFromFocalPlaneTo(CameraSys const &toSys, std::shared_ptr< afw::geom::TransformPoint2ToPoint2 const > transform)
Set the transformation from FOCAL_PLANE to the given coordinate system.
Definition: Camera.cc:299
Builder(std::string const &name)
Construct a Builder for a completely new Camera with the given name.
Definition: Camera.cc:204
std::shared_ptr< Detector::InCameraBuilder > add(std::string const &name, int id)
Add a new Detector with the given name and ID.
Definition: Camera.cc:329
bool discardTransformFromFocalPlaneTo(CameraSys const &toSys)
Remove any transformation from FOCAL_PLANE to the given coordinate system.
Definition: Camera.cc:320
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.
Definition: Camera.cc:165
static Factory const registration
Definition: Camera.cc:171
An immutable representation of a camera.
Definition: Camera.h:43
Camera(Camera const &)=delete
DetectorCollection::List DetectorList
Definition: Camera.h:48
std::string getPupilFactoryName() const
Return the fully-qualified name of the Python class that provides this Camera's PupilFactory.
Definition: Camera.h:76
std::shared_ptr< TransformMap const > getTransformMap() const noexcept
Obtain the transform registry.
Definition: Camera.h:120
std::string getName() const
Return the name of the camera.
Definition: Camera.h:71
DetectorList findDetectors(lsst::geom::Point2D const &point, CameraSys const &cameraSys) const
Find the detectors that cover a point in any camera system.
Definition: Camera.cc:45
virtual ~Camera() noexcept
std::vector< DetectorList > findDetectorsList(std::vector< lsst::geom::Point2D > const &pointList, CameraSys const &cameraSys) const
Find the detectors that cover a list of points in any camera system.
Definition: Camera.cc:60
lsst::geom::Point2D transform(lsst::geom::Point2D const &point, CameraSys const &fromSys, CameraSys const &toSys) const
Transform a point from one camera coordinate system to another.
Definition: Camera.cc:83
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
Definition: Camera.cc:149
std::shared_ptr< afw::geom::TransformPoint2ToPoint2 > getTransform(CameraSys const &fromSys, CameraSys const &toSys) const
Get a transform from one CameraSys to another.
Definition: Camera.cc:78
Camera coordinate system; used as a key in in TransformMap.
Definition: CameraSys.h:83
bool hasDetectorName() const noexcept
Does this have a non-blank detector name?
Definition: CameraSys.h:125
std::string getSysName() const
Get coordinate system name.
Definition: CameraSys.h:115
std::string getDetectorName() const
Get detector name, or "" if not a detector-specific coordinate system.
Definition: CameraSys.h:120
Camera coordinate system prefix.
Definition: CameraSys.h:44
A helper class that allows the properties of a detector to be modified in the course of modifying a f...
Definition: Detector.h:555
std::size_t size() const noexcept
Get the number of detectors.
IdMap const & getIdMap() const noexcept
Get a map keyed and ordered by ID.
void add(std::shared_ptr< Detector::InCameraBuilder > detector)
Add a detector to the collection.
An immutable collection of Detectors that can be accessed by name or ID.
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
A registry of 2-dimensional coordinate transforms for a specific camera.
Definition: TransformMap.h:62
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.
std::shared_ptr< RecordT > addNew()
Create a new record, add it to the end of the catalog, and return a pointer to it.
Definition: Catalog.h:490
A vector of catalogs used by Persistable.
Definition: CatalogVector.h:29
A multi-catalog archive object used to load table::io::Persistable objects.
Definition: InputArchive.h:31
std::shared_ptr< Persistable > get(int id) const
Load the Persistable with the given ID and return it.
An object passed to Persistable::write to allow it to persist itself.
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.
Definition: Persistable.h:228
PersistableFactory(std::string const &name)
Constructor for the factory.
Definition: Persistable.cc:74
A floating-point coordinate rectangle geometry.
Definition: Box.h:413
bool contains(Point2D const &point) const noexcept
Return true if the box contains the point.
Definition: Box.cc:322
Reports errors in the logical structure of the program.
Definition: Runtime.h:46
T end(T... args)
T find_if(T... args)
T insert(T... args)
T move(T... args)
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
FilterProperty & operator=(FilterProperty const &)=default
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
A base class for image defects.
STL namespace.
T push_back(T... args)
T size(T... args)
Representation of a single edge in the graph defined by a TransformMap.
Definition: TransformMap.h:80