LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
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
28namespace lsst {
29namespace afw {
30namespace cameraGeom {
31
32namespace {
33
34// Set this as a function to ensure FOCAL_PLANE is defined before use.
35CameraSys const getNativeCameraSys() { return FOCAL_PLANE; }
36
37} // anonymoous
38
39Camera::~Camera() noexcept = default;
40
41Camera::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
96std::shared_ptr<Detector::InCameraBuilder> Camera::makeDetectorBuilder(std::string const & name, int id) {
98}
99
100std::shared_ptr<Detector::InCameraBuilder> Camera::makeDetectorBuilder(Detector const & detector) {
101 return std::shared_ptr<Detector::InCameraBuilder>(new Detector::InCameraBuilder(detector));
102}
103
104
105std::vector<TransformMap::Connection> const & Camera::getDetectorBuilderConnections(
106 Detector::InCameraBuilder const & detector
107) {
108 return detector._connections;
109}
110
111
112namespace {
113
114class PersistenceHelper {
115public:
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
127private:
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
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
161public:
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
179 DetectorCollection(std::move(detectors)),
180 _name(name),
181 _pupilFactoryName(pupilFactoryName),
182 _transformMap(std::move(transformMap))
183{}
184
185Camera::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
201std::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
244Camera::Builder::~Builder() noexcept = default;
245
246std::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
280namespace {
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//
287template <typename Iter>
288Iter 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
337namespace table {
338namespace io {
339
340template 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::shared_ptr< TransformMap const > getTransformMap() const noexcept
Obtain the transform registry.
Definition: Camera.h:120
std::string getPupilFactoryName() const
Return the fully-qualified name of the Python class that provides this Camera's PupilFactory.
Definition: Camera.h:76
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
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