LSSTApplications  20.0.0
LSSTDataManagementBasePackage
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
lsst::afw::cameraGeom::Camera::Factory::Factory
Factory()
Definition: Camera.cc:163
lsst::afw::cameraGeom::Camera
An immutable representation of a camera.
Definition: Camera.h:43
std::string
STL class.
std::shared_ptr
STL class.
lsst::afw::cameraGeom::DetectorCollection::write
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
Definition: DetectorCollection.cc:250
std::move
T move(T... args)
lsst::afw::table::io::OutputArchiveHandle
An object passed to Persistable::write to allow it to persist itself.
Definition: OutputArchive.h:118
lsst::afw::cameraGeom::Camera::getName
std::string getName() const
Return the name of the camera.
Definition: Camera.h:71
std::vector
STL class.
std::find_if
T find_if(T... args)
std::vector::size
T size(T... args)
Persistable.cc
lsst::geom::Box2D::contains
bool contains(Point2D const &point) const noexcept
Return true if the box contains the point.
Definition: Box.cc:322
lsst::afw::table::io::OutputArchiveHandle::saveCatalog
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
Definition: OutputArchive.cc:211
lsst::afw::cameraGeom::Camera::Factory::registration
static Factory const registration
Definition: Camera.cc:171
lsst::afw::cameraGeom::CameraSys::getSysName
std::string getSysName() const
Get coordinate system name.
Definition: CameraSys.h:115
pex.config.history.format
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
transformMap
table::Key< int > transformMap
Definition: Camera.cc:125
lsst::afw::table._match.first
first
Definition: _match.py:76
lsst::afw
Definition: imageAlgorithm.dox:1
lsst::afw::table::io::InputArchive
A multi-catalog archive object used to load table::io::Persistable objects.
Definition: InputArchive.h:31
lsst::afw::cameraGeom::DetectorCollectionBase< Detector const >::size
std::size_t size() const noexcept
Get the number of detectors.
Definition: DetectorCollection.h:67
astshim.keyMap.keyMapContinued.keys
def keys(self)
Definition: keyMapContinued.py:6
CatalogVector.h
end
int end
Definition: BoundedField.cc:105
lsst::afw::table::io::PersistableFactory::PersistableFactory
PersistableFactory(std::string const &name)
Constructor for the factory.
Definition: Persistable.cc:74
lsst::afw::cameraGeom::Camera::Builder::Builder
Builder(std::string const &name)
Construct a Builder for a completely new Camera with the given name.
Definition: Camera.cc:204
lsst::afw::cameraGeom::Camera::Builder::~Builder
virtual ~Builder() noexcept
lsst::afw::cameraGeom::Camera::getTransformMap
std::shared_ptr< TransformMap const > getTransformMap() const noexcept
Obtain the transform registry.
Definition: Camera.h:120
std::vector::push_back
T push_back(T... args)
lsst::afw::table::io::OutputArchiveHandle::makeCatalog
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
Definition: OutputArchive.cc:207
LSST_ARCHIVE_ASSERT
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
Definition: Persistable.h:48
lsst::afw::cameraGeom::TransformMap::make
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.
Definition: TransformMap.cc:174
lsst::pex::exceptions::LogicError
Reports errors in the logical structure of the program.
Definition: Runtime.h:46
lsst::afw::table::io::CatalogVector
A vector of catalogs used by Persistable.
Definition: CatalogVector.h:29
lsst::afw::cameraGeom::Camera::~Camera
virtual ~Camera() noexcept
lsst::afw::table::io::PersistableFactory
A base class for factory classes used to reconstruct objects from records.
Definition: Persistable.h:228
lsst::afw::cameraGeom::Camera::DetectorList
DetectorCollection::List DetectorList
Definition: Camera.h:48
lsst::afw::cameraGeom::Camera::transform
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
pupilFactoryName
table::Key< std::string > pupilFactoryName
Definition: Camera.cc:124
lsst::afw::cameraGeom::Detector::InCameraBuilder
A helper class that allows the properties of a detector to be modified in the course of modifying a f...
Definition: Detector.h:555
lsst::afw::cameraGeom::DetectorCollectionBase< Detector const >::getIdMap
IdMap const & getIdMap() const noexcept
Get a map keyed and ordered by ID.
Definition: DetectorCollection.h:62
lsst
A base class for image defects.
Definition: imageAlgorithm.dox:1
LSST_EXCEPT
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
lsst::afw::cameraGeom::DetectorCollection
An immutable collection of Detectors that can be accessed by name or ID.
Definition: DetectorCollection.h:151
schema
table::Schema schema
Definition: Camera.cc:122
lsst::afw::cameraGeom::Camera::Camera
Camera(Camera const &)=delete
Camera.h
lsst::afw::cameraGeom::Camera::Factory::read
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
lsst::afw::cameraGeom::FOCAL_PLANE
CameraSys const FOCAL_PLANE
Focal plane coordinates: Position on a 2-d planar approximation to the focal plane (x,...
Definition: CameraSys.cc:30
lsst::afw::cameraGeom::Camera::Builder::setTransformFromFocalPlaneTo
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
lsst::afw::cameraGeom::Camera::getTransform
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
lsst::afw::cameraGeom::Camera::Builder::add
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
std
STL namespace.
lsst::afw::cameraGeom::DetectorCollectionBase< Detector::InCameraBuilder >::add
void add(std::shared_ptr< Detector::InCameraBuilder > detector)
Add a detector to the collection.
Definition: DetectorCollection.cc:89
lsst::afw::cameraGeom::CameraSys::getDetectorName
std::string getDetectorName() const
Get detector name, or "" if not a detector-specific coordinate system.
Definition: CameraSys.h:120
lsst::afw::cameraGeom::Camera::findDetectors
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
std::vector::insert
T insert(T... args)
detector
table::Key< int > detector
Definition: DetectorCollection.cc:172
lsst::geom::Point< double, 2 >
lsst::afw::cameraGeom::Camera::Factory
Definition: Camera.cc:160
lsst::afw::cameraGeom::Camera::Builder
A helper class for creating and modifying cameras.
Definition: Camera.h:208
name
table::Key< std::string > name
Definition: Camera.cc:123
lsst::afw::cameraGeom::Camera::getPupilFactoryName
std::string getPupilFactoryName() const
Return the fully-qualified name of the Python class that provides this Camera's PupilFactory.
Definition: Camera.h:76
InputArchive.h
std::size_t
lsst::afw::table::io::OutputArchiveHandle::put
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...
Definition: OutputArchive.cc:216
std::vector::end
T end(T... args)
lsst::afw::table::CatalogT::addNew
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:485
lsst::afw::cameraGeom::Camera::write
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
Definition: Camera.cc:149
lsst::geom::Box2D
A floating-point coordinate rectangle geometry.
Definition: Box.h:413
lsst::afw::cameraGeom::TransformMap
A registry of 2-dimensional coordinate transforms for a specific camera.
Definition: TransformMap.h:62
lsst::afw::cameraGeom::CameraSysPrefix
Camera coordinate system prefix.
Definition: CameraSys.h:44
lsst::afw::cameraGeom::CameraSys::hasDetectorName
bool hasDetectorName() const noexcept
Does this have a non-blank detector name?
Definition: CameraSys.h:125
lsst::afw::cameraGeom::Camera::findDetectorsList
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::afw::cameraGeom::PIXELS
CameraSysPrefix const PIXELS
Pixel coordinates: Nominal position on the entry surface of a given detector (x, y unbinned pixels).
Definition: CameraSys.cc:34
lsst::afw::cameraGeom::Camera::Builder::discardTransformFromFocalPlaneTo
bool discardTransformFromFocalPlaneTo(CameraSys const &toSys)
Remove any transformation from FOCAL_PLANE to the given coordinate system.
Definition: Camera.cc:320
astshim.fitsChanContinued.iter
def iter(self)
Definition: fitsChanContinued.py:88
OutputArchive.h
lsst::afw::cameraGeom::CameraSys
Camera coordinate system; used as a key in in TransformMap.
Definition: CameraSys.h:83
lsst::afw::cameraGeom::TransformMap::Connection
Representation of a single edge in the graph defined by a TransformMap.
Definition: TransformMap.h:80
lsst::afw::table::io::InputArchive::get
std::shared_ptr< Persistable > get(int id) const
Load the Persistable with the given ID and return it.
Definition: InputArchive.cc:182