LSST Applications g042eb84c57+730a74494b,g04e9c324dd+8c5ae1fdc5,g134cb467dc+1f1e3e7524,g199a45376c+0ba108daf9,g1fd858c14a+fa7d31856b,g210f2d0738+f66ac109ec,g262e1987ae+83a3acc0e5,g29ae962dfc+d856a2cb1f,g2cef7863aa+aef1011c0b,g35bb328faa+8c5ae1fdc5,g3fd5ace14f+a1e0c9f713,g47891489e3+0d594cb711,g4d44eb3520+c57ec8f3ed,g4d7b6aa1c5+f66ac109ec,g53246c7159+8c5ae1fdc5,g56a1a4eaf3+fd7ad03fde,g64539dfbff+f66ac109ec,g67b6fd64d1+0d594cb711,g67fd3c3899+f66ac109ec,g6985122a63+0d594cb711,g74acd417e5+3098891321,g786e29fd12+668abc6043,g81db2e9a8d+98e2ab9f28,g87389fa792+8856018cbb,g89139ef638+0d594cb711,g8d7436a09f+80fda9ce03,g8ea07a8fe4+760ca7c3fc,g90f42f885a+033b1d468d,g97be763408+a8a29bda4b,g99822b682c+e3ec3c61f9,g9d5c6a246b+0d5dac0c3d,ga41d0fce20+9243b26dd2,gbf99507273+8c5ae1fdc5,gd7ef33dd92+0d594cb711,gdab6d2f7ff+3098891321,ge410e46f29+0d594cb711,geaed405ab2+c4bbc419c6,gf9a733ac38+8c5ae1fdc5,w.2025.38
LSST Data Management Base Package
Loading...
Searching...
No Matches
Source.cc
Go to the documentation of this file.
1// -*- lsst-c++ -*-
2#include <typeinfo>
3
4#include "boost/format.hpp"
5
14
15namespace lsst {
16namespace afw {
17namespace table {
18
19//-----------------------------------------------------------------------------------------------------------
20//----- PersistenceHelpers ----------------------------------------------------------------------------------
21//-----------------------------------------------------------------------------------------------------------
22
23namespace {
24
25struct PersistenceHelper {
26 SchemaMapper mapper;
27 afw::table::Key<int> footprintKey;
28};
29
30} // namespace
31
32//-----------------------------------------------------------------------------------------------------------
33//----- SourceFitsWriter ------------------------------------------------------------------------------------
34//-----------------------------------------------------------------------------------------------------------
35
36// A custom FitsWriter for Sources. It also sets the AFW_TYPE key to SOURCE, which should
37// ensure we use SourceFitsReader to read it.
38
39// Because it also holds Footprints, a SourceCatalog isn't persisted with the same Schema
40// it has in-memory; instead, it's saved in a Schema that has an additional int field
41// appended to the end, which contains the afw::table::io "archive ID" that's used to
42// extract the Footprint from additional FITS HDUs. (If we disable saving Footprints via
43// SourceFitsFlags, we do save using the original Schema).
44
45// The only public access point to this class is SourceTable::makeFitsWriter. If we
46// subclass SourceTable someday, it may be necessary to put SourceFitsWriter in a header
47// file so we can subclass it too.
48
49namespace {
50
51class SourceFitsWriter : public io::FitsWriter {
52public:
53 explicit SourceFitsWriter(Fits *fits, int flags) : io::FitsWriter(fits, flags) {}
54
55protected:
56 void _writeTable(std::shared_ptr<BaseTable const> const &table, std::size_t nRows) override;
57
58 void _writeRecord(BaseRecord const &record) override;
59
60 void _finish() override {
61 if (!(_flags & SOURCE_IO_NO_FOOTPRINTS)) {
62 _archive.writeFits(*_fits);
63 }
64 }
65
66private:
67 SchemaMapper _mapper;
68 std::shared_ptr<BaseRecord> _outRecord;
69 std::shared_ptr<BaseTable> _outTable;
70 Key<int> _footprintKey;
71 io::OutputArchive _archive;
72};
73
74void SourceFitsWriter::_writeTable(std::shared_ptr<BaseTable const> const &t, std::size_t nRows) {
75 std::shared_ptr<SourceTable const> table = std::dynamic_pointer_cast<SourceTable const>(t);
76 if (!table) {
77 throw LSST_EXCEPT(lsst::pex::exceptions::LogicError,
78 "Cannot use a SourceFitsWriter on a non-Source table.");
79 }
80 if (!(_flags & SOURCE_IO_NO_FOOTPRINTS)) {
81 _mapper = SchemaMapper(t->getSchema(), true);
82 _mapper.addMinimalSchema(t->getSchema(), true);
83 _footprintKey = _mapper.editOutputSchema().addField<int>("footprint", "archive ID for Footprint");
84 _outTable = BaseTable::make(_mapper.getOutputSchema());
85 std::shared_ptr<daf::base::PropertyList> metadata = table->getMetadata();
86 if (metadata) {
87 metadata = std::static_pointer_cast<daf::base::PropertyList>(metadata->deepCopy());
88 } else {
89 metadata.reset(new daf::base::PropertyList());
90 }
91 // HDU 0 is empty (primary HDU can't be a table)
92 // HDU 1 is the SourceCatalog's records
93 // HDU 2 is the index for the afw::table::io archive that holds more complex objects
94 //
95 // Historically the AR_HDU keyword was 1-indexed (see RFC-304), and to maintain file compatibility
96 // this is still the case so we're setting AR_HDU to 3 == 2 + 1
97 metadata->set("AR_HDU", 3,
98 "HDU (1-indexed) containing the archive index for non-record data (e.g. Footprints)");
99 _outTable->setMetadata(metadata);
100 _outRecord = _outTable->makeRecord(); // make temporary record to use as a workspace
101 io::FitsWriter::_writeTable(_outTable, nRows);
102 } else {
103 io::FitsWriter::_writeTable(table, nRows);
104 }
105 _fits->writeKey("AFW_TYPE", "SOURCE", "Tells lsst::afw to load this as a Source table.");
106}
107
108void SourceFitsWriter::_writeRecord(BaseRecord const &r) {
109 SourceRecord const &record = static_cast<SourceRecord const &>(r);
110 if (!(_flags & SOURCE_IO_NO_FOOTPRINTS)) {
111 _outRecord->assign(record, _mapper);
112 std::shared_ptr<afw::detection::Footprint> footprint = record.getFootprint();
113 if (footprint) {
114 if ((_flags & SOURCE_IO_NO_HEAVY_FOOTPRINTS) && footprint->isHeavy()) {
115 footprint.reset(new afw::detection::Footprint(*footprint));
116 }
117 int footprintArchiveId = _archive.put(footprint);
118 _outRecord->set(_footprintKey, footprintArchiveId);
119 } else {
120 _outRecord->set(_footprintKey, _archive.put(nullptr));
121 }
122 io::FitsWriter::_writeRecord(*_outRecord);
123 } else {
124 io::FitsWriter::_writeRecord(record);
125 }
126}
127
128} // namespace
129
130//-----------------------------------------------------------------------------------------------------------
131//----- SourceFitsReader ------------------------------------------------------------------------------------
132//-----------------------------------------------------------------------------------------------------------
133
134// A custom FitsReader for Sources - this reads footprints in addition to the regular fields. It
135// gets registered with name SOURCE, so it should get used whenever we read a table with AFW_TYPE
136// set to that value. (The actual SourceFitsReader class is a bit further down, after some helper
137// classes.)
138
139// As noted in the comments for SourceFitsWriter, we add a column for the Footprint archive ID when
140// we save a SourceCatalog.
141
142// Things are a bit more complicated than that when reading, because we also need to be able to read files
143// saved with an older version of the pipeline, in which there were 2-5 additional columns, all variable-
144// length arrays, holding the Spans, Peaks, and HeavyFootprint arrays. Those are handled by explicit
145// calls to the FITS I/O routines here.
146
147// The only public access point to this class is through the registry. If we subclass SourceTable
148// someday, it may be necessary to put SourceFitsReader in a header file so we can subclass it too.
149
150namespace {
151
152// FitsColumnReader subclass for backwards-compatible Footprint reading from variable-length arrays
153class OldSourceFootprintReader : public io::FitsColumnReader {
154public:
155 static int readSpecialColumn(io::FitsSchemaInputMapper &mapper, daf::base::PropertyList &metadata,
156 bool stripMetadata, std::string const &name) {
157 int column = metadata.get(name, 0);
158 --column; // switch from 1-indexed to 0-indexed convention
159 if (column >= 0) {
160 if (stripMetadata) {
161 metadata.remove(name);
162 }
163 mapper.erase(name);
164 }
165 return column;
166 }
167
168 static void setup(io::FitsSchemaInputMapper &mapper, daf::base::PropertyList &metadata, int ioFlags,
169 bool stripMetadata) {
170 std::unique_ptr<OldSourceFootprintReader> reader(new OldSourceFootprintReader());
171 reader->_spanCol = readSpecialColumn(mapper, metadata, stripMetadata, "SPANCOL");
172 reader->_peakCol = readSpecialColumn(mapper, metadata, stripMetadata, "PEAKCOL");
173 reader->_heavyPixCol = readSpecialColumn(mapper, metadata, stripMetadata, "HVYPIXCO");
174 reader->_heavyMaskCol = readSpecialColumn(mapper, metadata, stripMetadata, "HVYMSKCO");
175 reader->_heavyVarCol = readSpecialColumn(mapper, metadata, stripMetadata, "HVYVARCO");
176 if ((ioFlags & SOURCE_IO_NO_FOOTPRINTS) || mapper.hasArchive()) {
177 return; // don't want to load anything, so we're done after just removing the special columns
178 }
179 if (ioFlags & SOURCE_IO_NO_HEAVY_FOOTPRINTS) {
180 reader->_heavyPixCol = -1;
181 reader->_heavyMaskCol = -1;
182 reader->_heavyVarCol = -1;
183 }
184 // These checks are really basically assertions - they should only happen if we get
185 // a corrupted catalog - but we still don't want to crash if that happens.
186 if ((reader->_spanCol >= 0) != (reader->_peakCol >= 0)) {
187 throw LSST_EXCEPT(afw::fits::FitsError,
188 "Corrupted catalog: either both or none of the Footprint Span/Peak columns "
189 "must be present.");
190 }
191 if (reader->_spanCol < 0) {
192 return;
193 }
194 if ((reader->_heavyPixCol >= 0) != (reader->_heavyMaskCol >= 0) ||
195 (reader->_heavyPixCol >= 0) != (reader->_heavyVarCol >= 0)) {
196 throw LSST_EXCEPT(
197 afw::fits::FitsError,
198 "Corrupted catalog: either all or none of the HeavyFootprint columns must be present.");
199 }
200 if (reader->_heavyPixCol >= 0 && reader->_spanCol < 0) {
201 throw LSST_EXCEPT(afw::fits::FitsError,
202 "Corrupted catalog: HeavyFootprint columns with no Span/Peak columns.");
203 }
204 // If we do want to load old-style Footprints, add the column reader to the mapper.
205 mapper.customize(std::move(reader));
206 }
207
208 void readCell(BaseRecord &baseRecord, std::size_t row, fits::Fits &fits,
209 std::shared_ptr<io::InputArchive> const &archive) const override {
210 SourceRecord &record = static_cast<SourceRecord &>(baseRecord);
211 std::vector<geom::Span> spansVector;
212
213 // Load a regular Footprint from the span and peak columns.
214 std::size_t spanElementCount = fits.getTableArraySize(row, _spanCol);
215 std::size_t peakElementCount = fits.getTableArraySize(row, _peakCol);
216 if (spanElementCount) {
217 if (spanElementCount % 3) {
218 throw LSST_EXCEPT(
219 afw::fits::FitsError,
220 afw::fits::makeErrorMessage(
221 fits.fptr, fits.status,
222 boost::format("Number of span elements (%d) must divisible by 3 (row %d)") %
223 spanElementCount % row));
224 }
225 std::vector<int> spanElements(spanElementCount);
226 fits.readTableArray(row, _spanCol, spanElementCount, &spanElements.front());
227 std::vector<int>::iterator j = spanElements.begin();
228 while (j != spanElements.end()) {
229 int y = *j++;
230 int x0 = *j++;
231 int x1 = *j++;
232 spansVector.emplace_back(y, x0, x1);
233 }
234 }
235 std::shared_ptr<Footprint> fp = std::make_shared<detection::Footprint>(
237 if (peakElementCount) {
238 if (peakElementCount % 3) {
239 throw LSST_EXCEPT(
240 afw::fits::FitsError,
241 afw::fits::makeErrorMessage(
242 fits.fptr, fits.status,
243 boost::format("Number of peak elements (%d) must divisible by 3 (row %d)") %
244 peakElementCount % row));
245 }
246 std::vector<float> peakElements(peakElementCount);
247 fits.readTableArray(row, _peakCol, peakElementCount, &peakElements.front());
248 std::vector<float>::iterator j = peakElements.begin();
249 while (j != peakElements.end()) {
250 float x = *j++;
251 float y = *j++;
252 float value = *j++;
253 fp->addPeak(x, y, value);
254 }
255 }
256 record.setFootprint(fp);
257
258 // If we're setup to read HeavyFootprints
259 if (_heavyPixCol < 0) {
260 return;
261 }
262 std::size_t heavyPixElementCount = fits.getTableArraySize(row, _heavyPixCol);
263 std::size_t heavyMaskElementCount = fits.getTableArraySize(row, _heavyMaskCol);
264 std::size_t heavyVarElementCount = fits.getTableArraySize(row, _heavyVarCol);
265 if (heavyPixElementCount > 0) {
266 std::size_t N = fp->getArea();
267 if ((heavyPixElementCount != N) || (heavyMaskElementCount != N) || (heavyVarElementCount != N)) {
268 throw LSST_EXCEPT(
269 afw::fits::FitsError,
270 afw::fits::makeErrorMessage(
271 fits.fptr, fits.status,
272 boost::format("Number of HeavyFootprint elements (pix %d, mask %d, var %d) "
273 "must all be equal to footprint area (%d)") %
274 heavyPixElementCount % heavyMaskElementCount % heavyVarElementCount %
275 N));
276 }
277 // float HeavyFootprints were the only kind we ever saved using the old format
278 using HeavyFootprint = detection::HeavyFootprint<float>;
279 std::shared_ptr<HeavyFootprint> heavy = std::make_shared<HeavyFootprint>(*fp);
280 fits.readTableArray(row, _heavyPixCol, N, heavy->getImageArray().getData());
281 fits.readTableArray(row, _heavyMaskCol, N, heavy->getMaskArray().getData());
282 fits.readTableArray(row, _heavyVarCol, N, heavy->getVarianceArray().getData());
283 record.setFootprint(heavy);
284 }
285 }
286
287private:
288 int _spanCol;
289 int _peakCol;
290 int _heavyPixCol;
291 int _heavyMaskCol;
292 int _heavyVarCol;
293};
294
295// FitsColumnReader for new-style Footprint persistence using archives.
296class SourceFootprintReader : public io::FitsColumnReader {
297public:
298 static void setup(io::FitsSchemaInputMapper &mapper, int ioFlags) {
299 auto item = mapper.find("footprint");
300 if (item) {
301 if (mapper.hasArchive()) {
302 std::unique_ptr<io::FitsColumnReader> reader(
303 new SourceFootprintReader(ioFlags & SOURCE_IO_NO_HEAVY_FOOTPRINTS, item->column));
304 mapper.customize(std::move(reader));
305 }
306 mapper.erase(item);
307 }
308 }
309
310 SourceFootprintReader(bool noHeavy, int column) : _noHeavy(noHeavy), _column(column) {}
311
312 void readCell(BaseRecord &record, std::size_t row, fits::Fits &fits,
313 std::shared_ptr<io::InputArchive> const &archive) const override {
314 int id = 0;
315 fits.readTableScalar<int>(row, _column, id);
316 std::shared_ptr<Footprint> footprint = archive->get<Footprint>(id);
317 if (_noHeavy && footprint->isHeavy()) {
318 // It sort of defeats the purpose of the flag if we have to do the I/O to read
319 // a HeavyFootprint before we can downgrade it to a regular Footprint, but that's
320 // what we're going to do - at least this will save on on some memory usage, which
321 // might still be useful. It'd be really hard to fix this
322 // (because we have no way to pass something like the ioFlags to the InputArchive).
323 // The good news is that if someone's concerned about performance of reading
324 // SourceCatalogs, they'll almost certainly use SOURCE_IO_NO_FOOTPRINTS, which
325 // will do what we want. SOURCE_IO_NO_HEAVY_FOOTPRINTS is more useful for writing
326 // sources, and that still works just fine.
327 footprint.reset(new Footprint(*footprint));
328 }
329 static_cast<SourceRecord &>(record).setFootprint(footprint);
330 }
331
332private:
333 bool _noHeavy;
334 int _column;
335};
336
337class SourceFitsReader : public io::FitsReader {
338public:
339 SourceFitsReader() : afw::table::io::FitsReader("SOURCE") {}
340
341 std::shared_ptr<BaseTable> makeTable(io::FitsSchemaInputMapper &mapper,
342 std::shared_ptr<daf::base::PropertyList> metadata, int ioFlags,
343 bool stripMetadata) const override {
344 // Look for old-style persistence of Footprints. If we have both that and an archive, we
345 // load the footprints from the archive, but still need to remove the old-style header keys
346 // from the metadata and the corresponding fields from the FitsSchemaInputMapper.
347 OldSourceFootprintReader::setup(mapper, *metadata, ioFlags, stripMetadata);
348 // Look for new-style persistence of Footprints. We'll only read them if we have an archive,
349 // but we'll strip fields out regardless.
350 SourceFootprintReader::setup(mapper, ioFlags);
351 std::shared_ptr<SourceTable> table = SourceTable::make(mapper.finalize());
352 table->setMetadata(metadata);
353 return table;
354 }
355
356 bool usesArchive(int ioFlags) const override { return !(ioFlags & SOURCE_IO_NO_FOOTPRINTS); }
357};
358
359// registers the reader so FitsReader::make can use it.
360static SourceFitsReader const sourceFitsReader;
361
362} // namespace
363
364//-----------------------------------------------------------------------------------------------------------
365//----- SourceTable/Record member function implementations --------------------------------------------------
366//-----------------------------------------------------------------------------------------------------------
367
369
370void SourceRecord::updateCoord(geom::SkyWcs const &wcs, bool include_covariance) {
372 setCoord(wcs.pixelToSky(center));
373 if (include_covariance) {
374 // Get coordinate covariance:
375 auto err = getCentroidErr();
377 Eigen::Matrix2f skyCov = calculateCoordCovariance(wcs, center, err);
378 set(coordErrKey, skyCov);
379 }
380}
381
382void SourceRecord::updateCoord(geom::SkyWcs const &wcs, PointKey<double> const &key, bool include_covariance) {
383 lsst::geom::Point2D center = get(key);
384 setCoord(wcs.pixelToSky(center));
385 if (include_covariance) {
386 // Get coordinate covariance:
387 auto err = getCentroidErr();
389 Eigen::Matrix2f skyCov = calculateCoordCovariance(wcs, center, err);
390 set(coordErrKey, skyCov);
391 }
392}
393
395 try {
396 SourceRecord const &s = dynamic_cast<SourceRecord const &>(other);
397 _footprint = s._footprint;
398 } catch (std::bad_cast &) {
399 }
400}
401
403 std::shared_ptr<IdFactory> const &idFactory) {
404 if (!checkSchema(schema)) {
406 "Schema for Source must contain at least the keys defined by getMinimalSchema().");
407 }
408 std::shared_ptr<SourceTable> table(new SourceTable(schema, idFactory));
409 table->getSchema().getAliasMap()->setTable(table);
410 return table;
411}
412
414 : SimpleTable(schema, idFactory), _slots(schema) {}
415
416SourceTable::SourceTable(SourceTable const &other) = default;
417
419 if (alias.compare(0, 4, "slot") != 0) {
420 return;
421 }
422 _slots.handleAliasChange(alias, getSchema());
423}
424
425SourceTable::MinimalSchema::MinimalSchema() {
427 parent = schema.addField<RecordId>("parent", "unique ID of parent source");
428}
429
430SourceTable::MinimalSchema &SourceTable::getMinimalSchema() {
431 static MinimalSchema it;
432 return it;
433}
434
438
441 table->getSchema().getAliasMap()->setTable(table);
442 return table;
443}
444
446 auto record = constructRecord<SourceRecord>();
447 if (getIdFactory()) record->setId((*getIdFactory())());
448 return record;
449}
450
451template class CatalogT<SourceRecord>;
452template class CatalogT<SourceRecord const>;
453
454template class SortedCatalogT<SourceRecord>;
456} // namespace table
457} // namespace afw
458} // namespace lsst
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition fits.h:308
Base class for all records.
Definition BaseRecord.h:31
Field< T >::Value get(Key< T > const &key) const
Return the value of a field for the given key.
Definition BaseRecord.h:151
Schema getSchema() const
Return the Schema that holds this record's fields and keys.
Definition BaseRecord.h:80
void set(Key< T > const &key, U const &value)
Set value of a field for the given key.
Definition BaseRecord.h:164
std::shared_ptr< RecordT > constructRecord(Args &&... args)
Helper function that must be used by all _makeRecord overrides to actually construct records.
Definition BaseRecord.h:227
Schema getSchema() const
Return the table's schema.
Definition BaseTable.h:137
A custom container class for records, based on std::vector.
Definition Catalog.h:98
CovarianceMatrixKey< float, 2 > ErrorKey
Definition aggregates.h:304
static ErrorKey getErrorKey(Schema const &schema)
A FunctorKey used to get or set a lsst::geom::Point from an (x,y) pair of int or double Keys.
Definition aggregates.h:51
Defines the fields and offsets for a table.
Definition Schema.h:51
Key< T > addField(Field< T > const &field, bool doReplace=false)
Add a new field to the Schema, and return the associated Key.
Definition Schema.cc:479
Schema const getOutputSchema() const
Return the output schema (copy-on-write).
Schema & editOutputSchema()
Return a reference to the output schema that allows it to be modified in place.
void addMinimalSchema(Schema const &minimal, bool doMap=true)
Add the given minimal schema to the output schema.
void setCoord(lsst::geom::SpherePoint const &coord)
Definition Simple.h:231
static Schema makeMinimalSchema()
Return a minimal schema for Simple tables and records.
Definition Simple.h:140
std::shared_ptr< IdFactory > getIdFactory()
Return the object that generates IDs for the table (may be null).
Definition Simple.h:155
SimpleTable(Schema const &schema, std::shared_ptr< IdFactory > const &idFactory)
Definition Simple.cc:86
Custom catalog class for record/table subclasses that are guaranteed to have an ID,...
virtual void _assign(BaseRecord const &other)
Called by assign() after transferring fields to allow subclass data members to be copied.
Definition Source.cc:394
CentroidSlotDefinition::MeasValue getCentroid() const
Get the value of the Centroid slot measurement.
Definition Source.h:569
CentroidSlotDefinition::ErrValue getCentroidErr() const
Get the uncertainty on the Centroid slot measurement.
Definition Source.h:573
SourceRecord(ConstructionToken const &token, detail::RecordData &&data)
Constructor used by SourceTable.
Definition Source.h:94
void updateCoord(geom::SkyWcs const &wcs, bool include_covariance=true)
Update the coord field using the given Wcs and the field in the centroid slot.
Definition Source.cc:370
Table class that contains measurements made on a single exposure.
Definition Source.h:217
static std::shared_ptr< SourceTable > make(Schema const &schema, std::shared_ptr< IdFactory > const &idFactory)
Construct a new table.
Definition Source.cc:402
SourceTable(Schema const &schema, std::shared_ptr< IdFactory > const &idFactory)
Definition Source.cc:413
std::shared_ptr< BaseRecord > _makeRecord() override
Default-construct an associated record (protected implementation).
Definition Source.cc:445
std::shared_ptr< io::FitsWriter > makeFitsWriter(fits::Fits *fitsfile, int flags) const override
Definition Source.cc:435
std::shared_ptr< BaseTable > _clone() const override
Clone implementation with noncovariant return types.
Definition Source.cc:439
void handleAliasChange(std::string const &alias) override
Definition Source.cc:418
static bool checkSchema(Schema const &other)
Return true if the given schema is a valid SourceTable schema.
Definition Source.h:270
Writer object for FITS binary tables.
Definition FitsWriter.h:25
int put(std::shared_ptr< 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...
Reports invalid arguments.
Definition Runtime.h:66
T compare(T... args)
T emplace_back(T... args)
T get(T... args)
T make_shared(T... args)
T move(T... args)
lsst::afw::detection::Footprint Footprint
Definition Source.h:57
Eigen::Matrix2f calculateCoordCovariance(geom::SkyWcs const &wcs, lsst::geom::Point2D center, Eigen::Matrix2f err)
Calculate covariance for sky coordinates.
Definition wcsUtils.cc:95
@ SOURCE_IO_NO_FOOTPRINTS
Do not read/write footprints at all.
Definition Source.h:53
std::int64_t RecordId
Type used for unique IDs for records.
Definition misc.h:21
Point< double, 2 > Point2D
Definition Point.h:324
decltype(sizeof(void *)) size_t
Definition doctest.h:524
T dynamic_pointer_cast(T... args)
T reset(T... args)