4 #include "boost/format.hpp" 
   25 struct PersistenceHelper {
 
   51 class SourceFitsWriter : 
public io::FitsWriter {
 
   53     explicit SourceFitsWriter(Fits *
fits, 
int flags) : io::FitsWriter(
fits, flags) {}
 
   58     void _writeRecord(BaseRecord 
const &record) 
override;
 
   60     void _finish()
 override {
 
   70     Key<int> _footprintKey;
 
   78                           "Cannot use a SourceFitsWriter on a non-Source table.");
 
   81         _mapper = SchemaMapper(t->getSchema(), 
true);
 
   87             metadata = std::static_pointer_cast<daf::base::PropertyList>(metadata->deepCopy());
 
   89             metadata.
reset(
new daf::base::PropertyList());
 
   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();  
 
  105     _fits->writeKey(
"AFW_TYPE", 
"SOURCE", 
"Tells lsst::afw to load this as a Source table.");
 
  108 void SourceFitsWriter::_writeRecord(BaseRecord 
const &r) {
 
  109     SourceRecord 
const &record = 
static_cast<SourceRecord 
const &
>(r);
 
  111         _outRecord->assign(record, 
_mapper);
 
  117             int footprintArchiveId = 
_archive.put(footprint);
 
  118             _outRecord->set(_footprintKey, footprintArchiveId);
 
  151 class OldSourceFootprintReader : 
public io::FitsColumnReader {
 
  153     static int readSpecialColumn(io::FitsSchemaInputMapper &
mapper, daf::base::PropertyList &metadata,
 
  155         int column = metadata.get(
name, 0);
 
  159                 metadata.remove(
name);
 
  166     static void setup(io::FitsSchemaInputMapper &
mapper, daf::base::PropertyList &metadata, 
int ioFlags,
 
  167                       bool stripMetadata) {
 
  169         reader->_spanCol = readSpecialColumn(
mapper, metadata, stripMetadata, 
"SPANCOL");
 
  170         reader->_peakCol = readSpecialColumn(
mapper, metadata, stripMetadata, 
"PEAKCOL");
 
  171         reader->_heavyPixCol = readSpecialColumn(
mapper, metadata, stripMetadata, 
"HVYPIXCO");
 
  172         reader->_heavyMaskCol = readSpecialColumn(
mapper, metadata, stripMetadata, 
"HVYMSKCO");
 
  173         reader->_heavyVarCol = readSpecialColumn(
mapper, metadata, stripMetadata, 
"HVYVARCO");
 
  178             reader->_heavyPixCol = -1;
 
  179             reader->_heavyMaskCol = -1;
 
  180             reader->_heavyVarCol = -1;
 
  184         if ((reader->_spanCol >= 0) != (reader->_peakCol >= 0)) {
 
  186                               "Corrupted catalog: either both or none of the Footprint Span/Peak columns " 
  189         if (reader->_spanCol < 0) {
 
  192         if ((reader->_heavyPixCol >= 0) != (reader->_heavyMaskCol >= 0) ||
 
  193             (reader->_heavyPixCol >= 0) != (reader->_heavyVarCol >= 0)) {
 
  195                     afw::fits::FitsError,
 
  196                     "Corrupted catalog: either all or none of the HeavyFootprint columns must be present.");
 
  198         if (reader->_heavyPixCol >= 0 && reader->_spanCol < 0) {
 
  200                               "Corrupted catalog: HeavyFootprint columns with no Span/Peak columns.");
 
  208         SourceRecord &record = 
static_cast<SourceRecord &
>(baseRecord);
 
  214         if (spanElementCount) {
 
  215             if (spanElementCount % 3) {
 
  217                         afw::fits::FitsError,
 
  220                                 boost::format(
"Number of span elements (%d) must divisible by 3 (row %d)") %
 
  221                                         spanElementCount % 
row));
 
  224             fits.readTableArray(
row, _spanCol, spanElementCount, &spanElements.front());
 
  226             while (j != spanElements.end()) {
 
  234                 std::make_shared<geom::SpanSet>(
std::move(spansVector)));
 
  235         if (peakElementCount) {
 
  236             if (peakElementCount % 3) {
 
  238                         afw::fits::FitsError,
 
  241                                 boost::format(
"Number of peak elements (%d) must divisible by 3 (row %d)") %
 
  242                                         peakElementCount % 
row));
 
  245             fits.readTableArray(
row, _peakCol, peakElementCount, &peakElements.front());
 
  247             while (j != peakElements.end()) {
 
  251                 fp->addPeak(
x, 
y, value);
 
  254         record.setFootprint(fp);
 
  257         if (_heavyPixCol < 0) {
 
  263         if (heavyPixElementCount > 0) {
 
  265             if ((heavyPixElementCount != N) || (heavyMaskElementCount != N) || (heavyVarElementCount != N)) {
 
  267                         afw::fits::FitsError,
 
  270                                 boost::format(
"Number of HeavyFootprint elements (pix %d, mask %d, var %d) " 
  271                                               "must all be equal to footprint area (%d)") %
 
  272                                         heavyPixElementCount % heavyMaskElementCount % heavyVarElementCount %
 
  276             using HeavyFootprint = detection::HeavyFootprint<float>;
 
  278             fits.readTableArray(
row, _heavyPixCol, N, heavy->getImageArray().getData());
 
  279             fits.readTableArray(
row, _heavyMaskCol, N, heavy->getMaskArray().getData());
 
  280             fits.readTableArray(
row, _heavyVarCol, N, heavy->getVarianceArray().getData());
 
  281             record.setFootprint(heavy);
 
  294 class SourceFootprintReader : 
public io::FitsColumnReader {
 
  296     static void setup(io::FitsSchemaInputMapper &
mapper, 
int ioFlags) {
 
  297         auto item = 
mapper.find(
"footprint");
 
  299             if (
mapper.hasArchive()) {
 
  308     SourceFootprintReader(
bool noHeavy, 
int column) : _noHeavy(noHeavy), _column(column) {}
 
  313         fits.readTableScalar<
int>(
row, _column, 
id);
 
  315         if (_noHeavy && footprint->isHeavy()) {
 
  325             footprint.reset(
new Footprint(*footprint));
 
  327         static_cast<SourceRecord &
>(record).setFootprint(footprint);
 
  335 class SourceFitsReader : 
public io::FitsReader {
 
  337     SourceFitsReader() : 
afw::table::io::FitsReader(
"SOURCE") {}
 
  341                                          bool stripMetadata)
 const override {
 
  345         OldSourceFootprintReader::setup(
mapper, *metadata, ioFlags, stripMetadata);
 
  348         SourceFootprintReader::setup(
mapper, ioFlags);
 
  350         table->setMetadata(metadata);
 
  358 static SourceFitsReader 
const sourceFitsReader;
 
  377         _footprint = s._footprint;
 
  386                           "Schema for Source must contain at least the keys defined by getMinimalSchema().");
 
  399     if (alias.
compare(0, 4, 
"slot") != 0) {
 
  405 SourceTable::MinimalSchema::MinimalSchema() {
 
  407     parent = 
schema.addField<
RecordId>(
"parent", 
"unique ID of parent source");
 
  410 SourceTable::MinimalSchema &SourceTable::getMinimalSchema() {
 
  411     static MinimalSchema it;
 
  416     return std::make_shared<SourceFitsWriter>(fitsfile, flags);
 
  424     auto record = constructRecord<SourceRecord>();
 
table::Key< std::string > name
 
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
 
table::Key< table::Array< std::uint8_t > > wcs
 
afw::table::Key< int > footprintKey
 
Base class for all records.
 
Field< T >::Value get(Key< T > const &key) const
Return the value of a field for the given key.
 
Schema getSchema() const
Return the table's schema.
 
static std::shared_ptr< BaseTable > make(Schema const &schema)
Construct a new table.
 
A custom container class for records, based on std::vector.
 
Defines the fields and offsets for a table.
 
Key< T > addField(Field< T > const &field, bool doReplace=false)
Add a new field to the Schema, and return the associated Key.
 
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)
 
Table class that must contain a unique ID field and a celestial coordinate field.
 
std::shared_ptr< IdFactory > getIdFactory()
Return the object that generates IDs for the table (may be null).
 
static Schema makeMinimalSchema()
Return a minimal schema for Simple tables and records.
 
Custom catalog class for record/table subclasses that are guaranteed to have an ID,...
 
Record class that contains measurements made on a single exposure.
 
virtual void _assign(BaseRecord const &other)
Called by assign() after transferring fields to allow subclass data members to be copied.
 
void updateCoord(geom::SkyWcs const &wcs)
Update the coord field using the given Wcs and the field in the centroid slot.
 
CentroidSlotDefinition::MeasValue getCentroid() const
Get the value of the Centroid slot measurement.
 
Table class that contains measurements made on a single exposure.
 
static std::shared_ptr< SourceTable > make(Schema const &schema, std::shared_ptr< IdFactory > const &idFactory)
Construct a new table.
 
SourceTable(Schema const &schema, std::shared_ptr< IdFactory > const &idFactory)
 
std::shared_ptr< BaseRecord > _makeRecord() override
Default-construct an associated record (protected implementation).
 
std::shared_ptr< BaseTable > _clone() const override
Clone implementation with noncovariant return types.
 
void handleAliasChange(std::string const &alias) override
 
static bool checkSchema(Schema const &other)
Return true if the given schema is a valid SourceTable schema.
 
virtual void _writeRecord(BaseRecord const &source)
Write an individual record.
 
virtual void _writeTable(std::shared_ptr< BaseTable const > const &table, std::size_t nRows)
Write a table and its schema.
 
Reports invalid arguments.
 
Reports errors in the logical structure of the program.
 
T emplace_back(T... args)
 
std::string makeErrorMessage(std::string const &fileName="", int status=0, std::string const &msg="")
Return an error message reflecting FITS I/O errors.
 
lsst::afw::detection::Footprint Footprint
 
@ SOURCE_IO_NO_FOOTPRINTS
Do not read/write footprints at all.
 
@ SOURCE_IO_NO_HEAVY_FOOTPRINTS
Read/write heavy footprints as non-heavy footprints.
 
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
 
A base class for image defects.
 
void handleAliasChange(std::string const &alias, Schema const &schema)
Handle a callback from an AliasMap informing the table that an alias has changed.
 
std::shared_ptr< io::OutputArchive > _archive