37int const EXPOSURE_TABLE_CURRENT_VERSION = 5;
38std::string
const EXPOSURE_TABLE_VERSION_KEY =
"EXPTABLE_VER";
43std::string
const WCS_FIELD_NAME =
"wcs";
44std::string
const PSF_FIELD_NAME =
"psf";
45std::string
const CALIB_FIELD_NAME =
"calib";
46std::string
const PHOTOCALIB_FIELD_NAME =
"photoCalib";
47std::string
const VISIT_INFO_FIELD_NAME =
"visitInfo";
48std::string
const AP_CORR_MAP_FIELD_NAME =
"apCorrMap";
49std::string
const VALID_POLYGON_FIELD_NAME =
"validPolygon";
50std::string
const TRANSMISSION_CURVE_FIELD_NAME =
"transmissionCurve";
51std::string
const DETECTOR_FIELD_NAME =
"detector";
53int getTableVersion(daf::base::PropertySet &metadata) {
54 return metadata.exists(EXPOSURE_TABLE_VERSION_KEY) ? metadata.get<
int>(EXPOSURE_TABLE_VERSION_KEY) : 1;
62struct PersistenceHelper {
69 Key<int> validPolygon;
71 Key<int> transmissionCurve;
75 SchemaMapper makeWriteMapper(Schema
const &inputSchema)
const {
76 std::vector<Schema> inSchemas;
77 inSchemas.
push_back(PersistenceHelper().schema);
81 result.editOutputSchema().setAliasMap(inputSchema.getAliasMap());
86 SchemaMapper makeReadMapper(Schema
const &inputSchema)
const {
88 result.editOutputSchema().setAliasMap(inputSchema.getAliasMap());
93 template <
typename OutputArchiveIsh>
94 void writeRecord(ExposureRecord
const &input, BaseRecord &output, SchemaMapper
const &mapper,
95 OutputArchiveIsh &archive,
bool permissive)
const {
96 output.assign(input, mapper);
97 output.set(psf, archive.put(input.getPsf(), permissive));
98 output.set(wcs, archive.put(input.getWcs(), permissive));
99 output.set(photoCalib, archive.put(input.getPhotoCalib(), permissive));
100 output.set(apCorrMap, archive.put(input.getApCorrMap(), permissive));
101 output.set(validPolygon, archive.put(input.getValidPolygon(), permissive));
102 output.set(visitInfo, archive.put(input.getVisitInfo(), permissive));
103 output.set(transmissionCurve, archive.put(input.getTransmissionCurve(), permissive));
104 output.set(detector, archive.put(input.getDetector(), permissive));
108 void readRecord(BaseRecord
const &input, ExposureRecord &output, SchemaMapper
const &mapper,
109 io::InputArchive
const &archive)
const {
110 output.assign(input, mapper);
112 output.setPsf(archive.get<detection::Psf>(input.get(psf)));
115 output.setWcs(archive.get<geom::SkyWcs>(input.get(wcs)));
117 if (calib.isValid()) {
118 output.setPhotoCalib(archive.get<image::PhotoCalib>(input.get(calib)));
120 if (photoCalib.isValid()) {
121 output.setPhotoCalib(archive.get<image::PhotoCalib>(input.get(photoCalib)));
123 if (apCorrMap.isValid()) {
124 output.setApCorrMap(archive.get<image::ApCorrMap>(input.get(apCorrMap)));
126 if (validPolygon.isValid()) {
127 output.setValidPolygon(archive.get<geom::polygon::Polygon>(input.get(validPolygon)));
129 if (visitInfo.isValid()) {
130 output.setVisitInfo(archive.get<image::VisitInfo>(input.get(visitInfo)));
132 if (transmissionCurve.isValid()) {
133 output.setTransmissionCurve(archive.get<image::TransmissionCurve>(input.get(transmissionCurve)));
135 if (detector.isValid()) {
136 output.setDetector(archive.get<cameraGeom::Detector>(input.get(detector)));
141 PersistenceHelper(
const PersistenceHelper &) =
delete;
142 PersistenceHelper &operator=(
const PersistenceHelper &) =
delete;
145 PersistenceHelper(PersistenceHelper &&) =
delete;
146 PersistenceHelper &operator=(PersistenceHelper &&) =
delete;
151 wcs(schema.addField<
int>(WCS_FIELD_NAME,
"archive ID for Wcs object")),
152 psf(schema.addField<
int>(PSF_FIELD_NAME,
"archive ID for Psf object")),
153 photoCalib(schema.addField<
int>(PHOTOCALIB_FIELD_NAME,
"archive ID for PhotoCalib object")),
154 apCorrMap(schema.addField<
int>(AP_CORR_MAP_FIELD_NAME,
"archive ID for ApCorrMap object")),
155 validPolygon(schema.addField<
int>(VALID_POLYGON_FIELD_NAME,
"archive ID for Polygon object")),
156 visitInfo(schema.addField<
int>(VISIT_INFO_FIELD_NAME,
"archive ID for VisitInfo object")),
157 transmissionCurve(schema.addField<
int>(TRANSMISSION_CURVE_FIELD_NAME,
158 "archive ID for TransmissionCurve object")),
159 detector(schema.addField<
int>(DETECTOR_FIELD_NAME,
"archive ID for Detector object")) {}
162 void addIfPresent(Schema
const &oldSchema, Key<int> &key, std::string
const &name) {
164 auto item = oldSchema.find<
int>(
name);
165 key = schema.addField(item.field);
166 }
catch (pex::exceptions::NotFoundError &) {
171 PersistenceHelper(Schema
const &oldSchema) {
172 addIfPresent(oldSchema, wcs, WCS_FIELD_NAME);
173 addIfPresent(oldSchema, psf, PSF_FIELD_NAME);
174 addIfPresent(oldSchema, calib, CALIB_FIELD_NAME);
175 addIfPresent(oldSchema, photoCalib, PHOTOCALIB_FIELD_NAME);
176 addIfPresent(oldSchema, apCorrMap, AP_CORR_MAP_FIELD_NAME);
177 addIfPresent(oldSchema, validPolygon, VALID_POLYGON_FIELD_NAME);
178 addIfPresent(oldSchema, visitInfo, VISIT_INFO_FIELD_NAME);
179 addIfPresent(oldSchema, transmissionCurve, TRANSMISSION_CURVE_FIELD_NAME);
180 addIfPresent(oldSchema, detector, DETECTOR_FIELD_NAME);
181 assert(oldSchema.contains(schema));
199 ExposureFitsWriter(Fits *fits, std::shared_ptr<io::OutputArchive> archive,
int flags)
200 : io::FitsWriter(fits,
flags), _doWriteArchive(false), _archive(archive), _helper() {
202 _doWriteArchive =
true;
203 _archive.reset(
new io::OutputArchive());
208 void _writeTable(std::shared_ptr<BaseTable const>
const &table,
std::size_t nRows)
override;
210 void _writeRecord(BaseRecord
const &r)
override;
212 void _finish()
override {
213 if (_doWriteArchive) _archive->writeFits(*_fits);
216 bool _doWriteArchive;
217 std::shared_ptr<io::OutputArchive> _archive;
218 std::shared_ptr<BaseRecord> _record;
219 PersistenceHelper _helper;
220 SchemaMapper _mapper;
223void ExposureFitsWriter::_writeTable(std::shared_ptr<BaseTable const>
const &t,
std::size_t nRows) {
226 throw LSST_EXCEPT(lsst::pex::exceptions::LogicError,
227 "Cannot use a ExposureFitsWriter on a non-Exposure table.");
229 _mapper = _helper.makeWriteMapper(inTable->getSchema());
230 std::shared_ptr<BaseTable> outTable = BaseTable::make(_mapper.
getOutputSchema());
232 outTable->setMetadata(inTable->getMetadata());
233 io::FitsWriter::_writeTable(outTable, nRows);
234 _fits->writeKey(
"AFW_TYPE",
"EXPOSURE",
"Tells lsst::afw to load this as an Exposure table.");
235 _fits->writeKey(EXPOSURE_TABLE_VERSION_KEY, EXPOSURE_TABLE_CURRENT_VERSION,
"Exposure table version");
236 _record = outTable->makeRecord();
239void ExposureFitsWriter::_writeRecord(BaseRecord
const &r) {
240 ExposureRecord
const &record =
static_cast<ExposureRecord
const &
>(
r);
241 _helper.writeRecord(record, *_record, _mapper, *_archive,
false);
242 io::FitsWriter::_writeRecord(*_record);
254template <
typename T,
void (ExposureRecord::*Setter)(std::shared_ptr<T const>)>
258 auto item = mapper.
find(name);
273 fits.readTableScalar<
int>(row, _column, id);
285class ExposureFitsReader :
public io::FitsReader {
287 ExposureFitsReader() :
afw::
table::io::FitsReader(
"EXPOSURE") {}
291 bool stripMetadata)
const override {
297 auto tableVersion = getTableVersion(*metadata);
298 PersistableObjectColumnReader<detection::Psf, &ExposureRecord::setPsf>::setup(
"psf", mapper);
299 PersistableObjectColumnReader<geom::SkyWcs, &ExposureRecord::setWcs>::setup(
"wcs", mapper);
300 PersistableObjectColumnReader<image::ApCorrMap, &ExposureRecord::setApCorrMap>::setup(
"apCorrMap",
302 PersistableObjectColumnReader<geom::polygon::Polygon, &ExposureRecord::setValidPolygon>::setup(
303 "validPolygon", mapper);
304 if (tableVersion > 1) {
305 PersistableObjectColumnReader<image::VisitInfo, &ExposureRecord::setVisitInfo>::setup(
"visitInfo",
308 if (tableVersion > 2) {
310 &ExposureRecord::setTransmissionCurve>::setup(
"transmissionCurve",
313 if (tableVersion > 3) {
314 PersistableObjectColumnReader<cameraGeom::Detector, &ExposureRecord::setDetector>::setup(
318 if (tableVersion <= 4) {
319 PersistableObjectColumnReader<image::PhotoCalib, &ExposureRecord::setPhotoCalib>::setup(
"calib",
322 PersistableObjectColumnReader<image::PhotoCalib, &ExposureRecord::setPhotoCalib>::setup(
323 "photoCalib", mapper);
326 auto schema = mapper.finalize();
327 std::shared_ptr<ExposureTable> table = ExposureTable::make(schema);
328 table->setMetadata(metadata);
332 bool usesArchive(
int ioFlags)
const override {
return true; }
335static ExposureFitsReader
const exposureFitsReader;
352 "ExposureRecord does not have a Wcs; cannot call contains()");
357 includeValidPolygon =
false;
362 if (includeValidPolygon)
373 bool includeValidPolygon)
const {
374 return contains(wcs.pixelToSky(point), includeValidPolygon);
384 _photoCalib = s._photoCalib;
385 _apCorrMap = s._apCorrMap;
386 _validPolygon = s._validPolygon;
387 _visitInfo = s._visitInfo;
388 _transmissionCurve = s._transmissionCurve;
389 _detector = s._detector;
398 "Schema for Exposure must contain at least the keys defined by makeMinimalSchema().");
401 table->getSchema().getAliasMap()->setTable(
table);
411ExposureTable::MinimalSchema::MinimalSchema() {
412 id = schema.addField<
RecordId>(
"id",
"unique ID");
416ExposureTable::MinimalSchema &ExposureTable::getMinimalSchema() {
417 static MinimalSchema it;
433 table->getSchema().getAliasMap()->setTable(
table);
445template <
typename RecordT>
447 PersistenceHelper helper{};
452 helper.writeRecord(*i, *outputCat.
addNew(), mapper, handle, permissive);
457template <
typename RecordT>
462 PersistenceHelper helper{catalog.getSchema()};
463 SchemaMapper mapper = helper.makeReadMapper(catalog.getSchema());
465 result.reserve(catalog.size());
467 helper.readRecord(*i, *result.addNew(), mapper, archive);
472template <
typename RecordT>
474 bool includeValidPolygon)
const {
477 if (i->contains(
coord, includeValidPolygon)) {
484template <
typename RecordT>
486 geom::SkyWcs
const &wcs,
487 bool includeValidPolygon)
const {
490 if (i->contains(point, wcs, includeValidPolygon)) {
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Implementation of the Photometric Calibration class.
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
A spatially-varying transmission curve as a function of wavelength.
Base class for all records.
Field< T >::Value get(Key< T > const &key) const
Return the value of a field for the given key.
BaseRecord(ConstructionToken const &, detail::RecordData &&data)
Construct a record with uninitialized data.
void set(Key< T > const &key, U const &value)
Set value of a field for the given key.
std::shared_ptr< RecordT > constructRecord(Args &&... args)
Helper function that must be used by all _makeRecord overrides to actually construct records.
Schema getSchema() const
Return the table's schema.
BaseTable(Schema const &schema, std::shared_ptr< daf::base::PropertyList > metadata=nullptr)
Construct from a schema.
static BoxKey addFields(Schema &schema, std::string const &name, std::string const &doc, std::string const &unit)
A custom container class for records, based on std::vector.
size_type size() const
Return the number of elements in the catalog.
std::shared_ptr< RecordT > addNew()
Create a new record, add it to the end of the catalog, and return a pointer to it.
iterator begin()
Iterator access.
CatalogIterator< typename Internal::const_iterator > const_iterator
void reserve(size_type n)
Increase the capacity of the catalog to the given size.
std::shared_ptr< Table > getTable() const
Return the table associated with the catalog.
Custom catalog class for ExposureRecord/Table.
typename Base::const_iterator const_iterator
static ExposureCatalogT readFromArchive(io::InputArchive const &archive, BaseCatalog const &catalog)
Convenience input function for Persistables that contain an ExposureCatalog.
void writeToArchive(io::OutputArchiveHandle &handle, bool ignoreUnpersistable=true) const
Convenience output function for Persistables that contain an ExposureCatalog.
ExposureCatalogT subsetContaining(lsst::geom::SpherePoint const &coord, bool includeValidPolygon=false) const
Return a shallow subset of the catalog with only those records that contain the given point.
ExposureCatalogT(std::shared_ptr< Table > const &table=std::shared_ptr< Table >())
Construct a vector from a table (or nothing).
Record class used to store exposure metadata.
bool contains(lsst::geom::SpherePoint const &coord, bool includeValidPolygon=false) const
Return true if the bounding box contains the given celestial coordinate point, taking into account th...
lsst::geom::Box2I getBBox() const
~ExposureRecord() override
std::shared_ptr< geom::polygon::Polygon const > getValidPolygon() const
std::shared_ptr< geom::SkyWcs const > getWcs() const
Get/Set the the attached Wcs, Psf, PhotoCalib, or ApCorrMap. No copies are made.
ExposureRecord(ConstructionToken const &token, detail::RecordData &&data)
Constructor used by ExposureTable.
void setBBox(lsst::geom::Box2I const &bbox)
void _assign(BaseRecord const &other) override
Called by assign() after transferring fields to allow subclass data members to be copied.
Table class used to store exposure metadata.
std::shared_ptr< BaseRecord > _makeRecord() override
Default-construct an associated record (protected implementation).
std::shared_ptr< io::FitsWriter > makeFitsWriter(fits::Fits *fitsfile, int flags) const override
static Box2IKey getBBoxKey()
Key for the full bbox.
~ExposureTable() override
static bool checkSchema(Schema const &other)
Return true if the given schema is a valid ExposureTable schema.
ExposureTable(Schema const &schema)
std::shared_ptr< BaseTable > _clone() const override
Clone implementation with noncovariant return types.
static std::shared_ptr< ExposureTable > make(Schema const &schema)
Construct a new table.
PersistableObjectColumnReader(int column)
static void setup(std::string const &name, io::FitsSchemaInputMapper &mapper)
void readCell(BaseRecord &record, std::size_t row, fits::Fits &fits, std::shared_ptr< io::InputArchive > const &archive) const override
Read values from a single row.
Defines the fields and offsets for a table.
A mapping between the keys of two Schemas, used to copy data between them.
Schema const getOutputSchema() const
Return the output schema (copy-on-write).
static SchemaMapper removeMinimalSchema(Schema const &input, Schema const &minimal)
Create a mapper by removing fields from the front of a schema.
static std::vector< SchemaMapper > join(std::vector< Schema > const &inputs, std::vector< std::string > const &prefixes=std::vector< std::string >())
Combine a sequence of schemas into one, creating a SchemaMapper for each.
Custom catalog class for record/table subclasses that are guaranteed to have an ID,...
Polymorphic reader interface used to read different kinds of objects from one or more FITS binary tab...
Writer object for FITS binary tables.
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.
A floating-point coordinate rectangle geometry.
bool contains(Point2D const &point) const noexcept
Return true if the box contains the point.
An integer coordinate rectangle.
Point in an unspecified spherical coordinate system.
Reports arguments outside the domain of an operation.
Reports invalid arguments.
Reports errors in the logical structure of the program.
CatalogT< BaseRecord > BaseCatalog
std::int64_t RecordId
Type used for unique IDs for records.
Point< double, 2 > Point2D
decltype(sizeof(void *)) size_t
T dynamic_pointer_cast(T... args)