LSST Applications 24.1.6,g063fba187b+56b85ce14a,g0f08755f38+df8a265115,g12f32b3c4e+891a09f10d,g1524ad2192+7a5d7b3fbd,g1653933729+a8ce1bb630,g168dd56ebc+a8ce1bb630,g28da252d5a+07cb1400be,g2bbee38e9b+ae03bbfc84,g2bc492864f+ae03bbfc84,g3156d2b45e+6e55a43351,g347aa1857d+ae03bbfc84,g35bb328faa+a8ce1bb630,g3a166c0a6a+ae03bbfc84,g3e281a1b8c+c5dd892a6c,g414038480c+6b9177ef31,g41af890bb2+8f257c4c0b,g781aacb6e4+a8ce1bb630,g7af13505b9+7137b3b17d,g80478fca09+6df6903293,g82479be7b0+091ce1d07f,g858d7b2824+df8a265115,g89c8672015+f4add4ffd5,g9125e01d80+a8ce1bb630,g9726552aa6+414189b318,ga5288a1d22+4a2bca08d7,gacef1a1666+c9a8ff65f4,gb58c049af0+d64f4d3760,gbcfae0f0a0+de1d42d831,gc28159a63d+ae03bbfc84,gcf0d15dbbd+72117bf34e,gda6a2b7d83+72117bf34e,gdaeeff99f8+1711a396fd,ge500cccec5+c8c9c9af63,ge79ae78c31+ae03bbfc84,gf0baf85859+c1f95f4921,gfa517265be+df8a265115,gfa999e8aa5+17cd334064,gfb92a5be7c+df8a265115
LSST Data Management Base Package
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Attributes | List of all members
lsst::afw::table::io::FitsSchemaInputMapper Class Reference

A class that describes a mapping from a FITS binary table to an afw::table Schema. More...

#include <FitsSchemaInputMapper.h>

Classes

class  Impl
 

Public Types

using Item = FitsSchemaItem
 

Public Member Functions

 FitsSchemaInputMapper (daf::base::PropertyList &metadata, bool stripMetadata)
 Construct a mapper from a PropertyList of FITS header values, stripping recognized keys if desired.
 
 FitsSchemaInputMapper (FitsSchemaInputMapper const &)
 
 FitsSchemaInputMapper (FitsSchemaInputMapper &&)
 
FitsSchemaInputMapperoperator= (FitsSchemaInputMapper const &)
 
FitsSchemaInputMapperoperator= (FitsSchemaInputMapper &&)
 
 ~FitsSchemaInputMapper ()
 
void setArchive (std::shared_ptr< InputArchive > archive)
 Set the Archive to an externally-provided one, overriding any that may have been read.
 
bool readArchive (afw::fits::Fits &fits)
 Set the Archive by reading from the HDU specified by the AR_HDU header entry.
 
bool hasArchive () const
 Return true if the mapper has an InputArchive.
 
Item constfind (std::string const &ttype) const
 Find an item with the given column name (ttype), returning nullptr if no such column exists.
 
Item constfind (int column) const
 Find an item with the given column number, returning nullptr if no such column exists.
 
void erase (Item const *item)
 Remove the given item (which should have been retrieved via find()) from the mapping, preventing it from being included in the regular fields added by finalize().
 
void erase (std::string const &ttype)
 Remove the item with the given column name (ttype) from the mapping, preventing it from being included in the regular fields added by finalize().
 
void erase (int column)
 Remove the item at the given column position from the mapping, preventing it from being included in the regular fields added by finalize().
 
void customize (std::unique_ptr< FitsColumnReader > reader)
 Customize a mapping by providing a FitsColumnReader instance that will be invoked by readRecords().
 
Schema finalize ()
 Map any remaining items into regular Schema items, and return the final Schema.
 
void readRecord (BaseRecord &record, afw::fits::Fits &fits, std::size_t row)
 Fill a record from a FITS binary table row.
 

Static Public Attributes

static std::size_t PREPPED_ROWS_FACTOR = 1 << 15
 When processing each column, divide this number by the record size (in bytes) and ask CFITSIO to read this many that of values from that column in a single call.
 

Detailed Description

A class that describes a mapping from a FITS binary table to an afw::table Schema.

A FitsSchemaInputMapper is created every time a FITS binary table is read into an afw::table catalog, allowing limited customization of the mapping between on-disk FITS table columns an in-memory fields by subclasses of BaseTable.

The object is constructed from a daf::base::PropertyList that represents the FITS header, which is used to populate a custom container of FitsSchemaItems. These can then be retrieved by name or column number via the find() methods, allowing the user to create custom readers for columns or groups of columns via addColumnReader(). They can also be removed from the "regular" fields via the erase() method. Those regular fields are filled in by the finalize() method, which automatically generates mappings for any FitsSchemaItems that have not been removed by calls to erase(). Once finalize() has been called, readRecord() may be called repeatedly to read FITS rows into record objects according to the mapping that has been defined.

Definition at line 91 of file FitsSchemaInputMapper.h.

Member Typedef Documentation

◆ Item

Definition at line 93 of file FitsSchemaInputMapper.h.

Constructor & Destructor Documentation

◆ FitsSchemaInputMapper() [1/3]

lsst::afw::table::io::FitsSchemaInputMapper::FitsSchemaInputMapper ( daf::base::PropertyList & metadata,
bool stripMetadata )

Construct a mapper from a PropertyList of FITS header values, stripping recognized keys if desired.

Definition at line 89 of file FitsSchemaInputMapper.cc.

90 : _impl(std::make_shared<Impl>()) {
91 // Set the table version. If AFW_TABLE_VERSION tag exists, use that
92 // If not, set to 0 if it has an AFW_TYPE, Schema default otherwise (DM-590)
93 if (!metadata.exists("AFW_TYPE")) {
95 }
96 _impl->version = metadata.get("AFW_TABLE_VERSION", _impl->version);
97 _impl->type = metadata.get("AFW_TYPE", _impl->type);
98 if (stripMetadata) {
99 metadata.remove("AFW_TABLE_VERSION");
100 }
101 if (stripMetadata) {
102 metadata.remove("AFW_TYPE");
103 }
104
105 // Find a key that indicates an Archive stored on other HDUs
106 _impl->archiveHdu = metadata.get("AR_HDU", -1);
107 if (_impl->archiveHdu > 0) {
108 --_impl->archiveHdu; // AR_HDU is 1-indexed for historical reasons (RFC-304; see Source.cc)
109 if (stripMetadata) {
110 metadata.remove("AR_HDU");
111 }
112 }
113
114 // Read aliases, stored as header entries with key 'ALIAS'
115 try {
116 std::vector<std::string> rawAliases = metadata.getArray<std::string>("ALIAS");
117 for (auto const &rawAliase : rawAliases) {
118 std::size_t pos = rawAliase.find_first_of(':');
119 if (pos == std::string::npos) {
120 throw LSST_EXCEPT(afw::fits::FitsError,
121 (boost::format("Malformed alias definition: '%s'") % rawAliase).str());
122 }
123 _impl->schema.getAliasMap()->set(rawAliase.substr(0, pos), rawAliase.substr(pos + 1, std::string::npos));
124 }
125 if (stripMetadata) {
126 metadata.remove("ALIAS");
127 }
128 } catch (pex::exceptions::NotFoundError &) {
129 // if there are no aliases, just move on
130 }
131
132 if (_impl->version == 0) {
133 // Read slots saved using an old mechanism in as aliases, since the new slot mechanism delegates
134 // slot definition to the AliasMap.
135 static std::array<std::pair<std::string, std::string>, 7> oldSlotKeys = {
136 {std::make_pair("PSF_FLUX", "slot_PsfFlux"), std::make_pair("AP_FLUX", "slot_ApFlux"),
137 std::make_pair("INST_FLUX", "slot_GaussianFlux"),
138 std::make_pair("MODEL_FLUX", "slot_ModelFlux"),
139 std::make_pair("CALIB_FLUX", "slot_CalibFlux"), std::make_pair("CENTROID", "slot_Centroid"),
140 std::make_pair("SHAPE", "slot_Shape")}};
141 for (auto const &oldSlotKey : oldSlotKeys) {
142 std::string target = metadata.get(oldSlotKey.first + "_SLOT", std::string(""));
143 if (!target.empty()) {
144 _impl->schema.getAliasMap()->set(oldSlotKey.second, target);
145 if (stripMetadata) {
146 metadata.remove(oldSlotKey.first);
147 metadata.remove(oldSlotKey.first + "_ERR_SLOT");
148 metadata.remove(oldSlotKey.first + "_FLAG_SLOT");
149 }
150 }
151 }
152 }
153
154 // Read the rest of the header into the intermediate inputs container.
155 std::vector<std::string> keyList = metadata.getOrderedNames();
156 for (auto const &key : keyList) {
157 if (key.compare(0, 5, "TTYPE") == 0) {
158 int column = std::stoi(key.substr(5)) - 1;
159 auto iter = _impl->byColumn().lower_bound(column);
160 if (iter == _impl->byColumn().end() || iter->column != column) {
161 iter = _impl->byColumn().insert(iter, FitsSchemaItem(column, -1));
162 }
163 std::string v = metadata.get<std::string>(key);
164 _impl->byColumn().modify(iter, Impl::SetTTYPE(v));
165 if (iter->doc.empty()) { // don't overwrite if already set with TDOCn
166 _impl->byColumn().modify(iter, Impl::SetDoc(metadata.getComment(key)));
167 }
168 if (stripMetadata) {
169 metadata.remove(key);
170 }
171 } else if (key.compare(0, 5, "TFLAG") == 0) {
172 int bit = std::stoi(key.substr(5)) - 1;
173 auto iter = _impl->byBit().lower_bound(bit);
174 if (iter == _impl->byBit().end() || iter->bit != bit) {
175 iter = _impl->byBit().insert(iter, FitsSchemaItem(-1, bit));
176 }
177 std::string v = metadata.get<std::string>(key);
178 _impl->byBit().modify(iter, Impl::SetTTYPE(v));
179 if (iter->doc.empty()) { // don't overwrite if already set with TFDOCn
180 _impl->byBit().modify(iter, Impl::SetDoc(metadata.getComment(key)));
181 }
182 if (stripMetadata) {
183 metadata.remove(key);
184 }
185 } else if (key.compare(0, 4, "TDOC") == 0) {
186 int column = std::stoi(key.substr(4)) - 1;
187 auto iter = _impl->byColumn().lower_bound(column);
188 if (iter == _impl->byColumn().end() || iter->column != column) {
189 iter = _impl->byColumn().insert(iter, FitsSchemaItem(column, -1));
190 }
191 _impl->byColumn().modify(iter, Impl::SetDoc(metadata.get<std::string>(key)));
192 if (stripMetadata) {
193 metadata.remove(key);
194 }
195 } else if (key.compare(0, 5, "TFDOC") == 0) {
196 int bit = std::stoi(key.substr(5)) - 1;
197 auto iter = _impl->byBit().lower_bound(bit);
198 if (iter == _impl->byBit().end() || iter->bit != bit) {
199 iter = _impl->byBit().insert(iter, FitsSchemaItem(-1, bit));
200 }
201 _impl->byBit().modify(iter, Impl::SetDoc(metadata.get<std::string>(key)));
202 if (stripMetadata) {
203 metadata.remove(key);
204 }
205 } else if (key.compare(0, 5, "TUNIT") == 0) {
206 int column = std::stoi(key.substr(5)) - 1;
207 auto iter = _impl->byColumn().lower_bound(column);
208 if (iter == _impl->byColumn().end() || iter->column != column) {
209 iter = _impl->byColumn().insert(iter, FitsSchemaItem(column, -1));
210 }
211 _impl->byColumn().modify(iter, Impl::SetTUNIT(metadata.get<std::string>(key)));
212 if (stripMetadata) {
213 metadata.remove(key);
214 }
215 } else if (key.compare(0, 5, "TCCLS") == 0) {
216 int column = std::stoi(key.substr(5)) - 1;
217 auto iter = _impl->byColumn().lower_bound(column);
218 if (iter == _impl->byColumn().end() || iter->column != column) {
219 iter = _impl->byColumn().insert(iter, FitsSchemaItem(column, -1));
220 }
221 _impl->byColumn().modify(iter, Impl::SetTCCLS(metadata.get<std::string>(key)));
222 if (stripMetadata) {
223 metadata.remove(key);
224 }
225 } else if (key.compare(0, 5, "TFORM") == 0) {
226 int column = std::stoi(key.substr(5)) - 1;
227 auto iter = _impl->byColumn().lower_bound(column);
228 if (iter == _impl->byColumn().end() || iter->column != column) {
229 iter = _impl->byColumn().insert(iter, FitsSchemaItem(column, -1));
230 }
231 _impl->byColumn().modify(iter, Impl::SetTFORM(metadata.get<std::string>(key)));
232 if (stripMetadata) {
233 metadata.remove(key);
234 }
235 } else if (key.compare(0, 5, "TZERO") == 0) {
236 if (stripMetadata) {
237 metadata.remove(key);
238 }
239 } else if (key.compare(0, 5, "TSCAL") == 0) {
240 if (stripMetadata) {
241 metadata.remove(key);
242 }
243 } else if (key.compare(0, 5, "TNULL") == 0) {
244 if (stripMetadata) {
245 metadata.remove(key);
246 }
247 } else if (key.compare(0, 5, "TDISP") == 0) {
248 if (stripMetadata) {
249 metadata.remove(key);
250 }
251 }
252 }
253
254 // Find the column used to store flags, and setup the flag-handling data members from it.
255 _impl->flagColumn = metadata.get("FLAGCOL", 0);
256 if (_impl->flagColumn > 0) {
257 if (stripMetadata) {
258 metadata.remove("FLAGCOL");
259 }
260 --_impl->flagColumn; // switch from 1-indexed to 0-indexed
261 auto iter = _impl->byColumn().find(_impl->flagColumn);
262 if (iter == _impl->byColumn().end()) {
263 throw LSST_EXCEPT(
264 afw::fits::FitsError,
265 (boost::format("Column for flag data not found; FLAGCOL=%d") % _impl->flagColumn).str());
266 }
267 // Regex to unpack a FITS TFORM value for a bit array column (TFORM code 'X'). The number
268 // that precedes the code is the size of the array; the number that follows it (if present)
269 // is ignored.
270 static std::regex const regex("(\\d+)?X\\(?(\\d)*\\)?");
272 if (!std::regex_match(iter->tform, m, regex)) {
273 throw LSST_EXCEPT(
274 afw::fits::FitsError,
275 (boost::format("Invalid TFORM key for flags column: '%s'") % iter->tform).str());
276 }
277 int nFlags = 1;
278 if (m[1].matched) {
279 nFlags = std::stoi(m[1].str());
280 }
281 _impl->flagKeys.resize(nFlags);
282 _impl->flagWorkspace.reset(new bool[nFlags]);
283 // Delete the flag column from the input list so we don't interpret it as a
284 // regular field.
285 _impl->byColumn().erase(iter);
286 }
287}
Key< Flag > const & target
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
int nFlags
Definition FitsWriter.cc:91
int m
Definition SpanSet.cc:48
static int const VERSION
Definition Schema.h:57
std::shared_ptr< AliasMap > getAliasMap() const
Return the map of aliases.
Definition Schema.h:279
SetFitsSchemaString<&FitsSchemaItem::tccls > SetTCCLS
SetFitsSchemaString<&FitsSchemaItem::ttype > SetTTYPE
SetFitsSchemaString<&FitsSchemaItem::doc > SetDoc
SetFitsSchemaString<&FitsSchemaItem::tform > SetTFORM
SetFitsSchemaString<&FitsSchemaItem::tunit > SetTUNIT
T make_pair(T... args)
T regex_match(T... args)
T reset(T... args)
T stoi(T... args)

◆ FitsSchemaInputMapper() [2/3]

lsst::afw::table::io::FitsSchemaInputMapper::FitsSchemaInputMapper ( FitsSchemaInputMapper const & )
default

◆ FitsSchemaInputMapper() [3/3]

lsst::afw::table::io::FitsSchemaInputMapper::FitsSchemaInputMapper ( FitsSchemaInputMapper && )
default

◆ ~FitsSchemaInputMapper()

lsst::afw::table::io::FitsSchemaInputMapper::~FitsSchemaInputMapper ( )
default

Member Function Documentation

◆ customize()

void lsst::afw::table::io::FitsSchemaInputMapper::customize ( std::unique_ptr< FitsColumnReader > reader)

Customize a mapping by providing a FitsColumnReader instance that will be invoked by readRecords().

Definition at line 353 of file FitsSchemaInputMapper.cc.

353 {
354 _impl->readers.push_back(std::move(reader));
355}
std::vector< std::unique_ptr< FitsColumnReader > > readers
T move(T... args)

◆ erase() [1/3]

void lsst::afw::table::io::FitsSchemaInputMapper::erase ( int column)

Remove the item at the given column position from the mapping, preventing it from being included in the regular fields added by finalize().

Definition at line 344 of file FitsSchemaInputMapper.cc.

344 {
345 auto iter = _impl->byColumn().lower_bound(column);
346 if (iter != _impl->byColumn().end() && iter->column == column) {
347 _impl->byColumn().erase(iter);
348 }
349}

◆ erase() [2/3]

void lsst::afw::table::io::FitsSchemaInputMapper::erase ( Item const * item)

Remove the given item (which should have been retrieved via find()) from the mapping, preventing it from being included in the regular fields added by finalize().

Definition at line 331 of file FitsSchemaInputMapper.cc.

331 {
332 auto iter = _impl->byColumn().lower_bound(item->column);
333 assert(iter != _impl->byColumn().end() && iter->column == item->column);
334 _impl->byColumn().erase(iter);
335}

◆ erase() [3/3]

void lsst::afw::table::io::FitsSchemaInputMapper::erase ( std::string const & ttype)

Remove the item with the given column name (ttype) from the mapping, preventing it from being included in the regular fields added by finalize().

Definition at line 337 of file FitsSchemaInputMapper.cc.

337 {
338 auto iter = _impl->byName().find(ttype);
339 if (iter != _impl->byName().end() && iter->ttype == ttype) {
340 _impl->byName().erase(iter);
341 }
342}

◆ finalize()

Schema lsst::afw::table::io::FitsSchemaInputMapper::finalize ( )

Map any remaining items into regular Schema items, and return the final Schema.

This method must be called before any calls to readRecords().

Definition at line 771 of file FitsSchemaInputMapper.cc.

771 {
772 if (_impl->version == 0) {
773 AliasMap &aliases = *_impl->schema.getAliasMap();
774 for (auto iter = _impl->asList().begin(); iter != _impl->asList().end(); ++iter) {
775 std::size_t flagPos = iter->ttype.find("flags");
776 if (flagPos != std::string::npos) {
777 // We want to create aliases that resolve "(.*)_flag" to "$1_flags"; old schemas will have
778 // the latter, but new conventions (including slots) expect the former.
779 // But we can't do that, because adding that alias directly results in a cycle in the
780 // aliases (since aliases do partial matches, and keep trying until there are no matches,
781 // we'd have "(.*)_flag" resolve to "$1_flagssssssssssssss...").
782 // Instead, we *rename* from "flags" to "flag", then create the reverse alias.
783 std::string ttype = iter->ttype;
784 std::string prefix = iter->ttype.substr(0, flagPos);
785 ttype.replace(flagPos, 5, "flag");
786 _impl->asList().modify(iter, Impl::SetTTYPE(ttype));
787 // Note that we're not aliasing the full field, just the first part - if we have multiple
788 // flag fields, one alias should be sufficient for all of them (because of partial matching).
789 // Of course, we'll try to recreate that alias every time we handle another flag field with
790 // the same prefix, but AliasMap know hows to handle that no-op set.
791 aliases.set(prefix + "flags", prefix + "flag");
792 } else if (isInstFlux(*iter)) {
793 // Create an alias that resolves "X_instFlux" to "X" or "X_instFluxErr" to "X_err".
794 if (endswith(iter->ttype, "_err")) {
795 aliases.set(replace(iter->ttype, "_err", "_instFluxErr"), iter->ttype);
796 } else {
797 aliases.set(iter->ttype + "_instFlux", iter->ttype);
798 }
799 } else if (endswith(iter->ttype, "_err")) {
800 // Create aliases that resolve "(.*)_(.*)Err" and "(.*)_(.*)_(.*)_Cov" to
801 // "$1_err_$2Err" and "$1_err_$2_$3_Cov", to make centroid and shape uncertainties
802 // available under the new conventions. We don't have to create aliases for the
803 // centroid and shape values themselves, as those will automatically be correct
804 // after the PointConversionReader and MomentsConversionReader do their work.
805 if (iter->tccls == "Covariance(Point)") {
806 aliases.set(replace(iter->ttype, "_err", "_yErr"), iter->ttype + "_yErr");
807 aliases.set(replace(iter->ttype, "_err", "_xErr"), iter->ttype + "_xErr");
808 aliases.set(replace(iter->ttype, "_err", "_x_y_Cov"), iter->ttype + "_x_y_Cov");
809 } else if (iter->tccls == "Covariance(Moments)") {
810 aliases.set(replace(iter->ttype, "_err", "_xxErr"), iter->ttype + "_xxErr");
811 aliases.set(replace(iter->ttype, "_err", "_yyErr"), iter->ttype + "_yyErr");
812 aliases.set(replace(iter->ttype, "_err", "_xyErr"), iter->ttype + "_xyErr");
813 aliases.set(replace(iter->ttype, "_err", "_xx_yy_Cov"), iter->ttype + "_xx_yy_Cov");
814 aliases.set(replace(iter->ttype, "_err", "_xx_xy_Cov"), iter->ttype + "_xx_xy_Cov");
815 aliases.set(replace(iter->ttype, "_err", "_yy_xy_Cov"), iter->ttype + "_yy_xy_Cov");
816 }
817 }
818 }
819 } else if (_impl->version < 3) {
820 // Version == 1 tables use Sigma when we should use Err (see RFC-333) and had no fields
821 // that should have been named Sigma. So provide aliases xErr -> xSigma.
822 // Version <= 2 tables used _flux when we should use _instFlux (see RFC-322).
823 AliasMap &aliases = *_impl->schema.getAliasMap();
824 for (auto iter = _impl->asList().begin(); iter != _impl->asList().end(); ++iter) {
825 std::string name = iter->ttype;
826 if (_impl->version < 2 && endswith(name, "Sigma")) {
827 name = replace(std::move(name), "Sigma", "Err");
828 }
829 if (_impl->version < 3 && isInstFlux(*iter)) {
830 name = replace(std::move(name), "flux", "instFlux");
831 }
832 if (name != iter->ttype) {
833 aliases.set(name, iter->ttype);
834 }
835 }
836 }
837 for (auto iter = _impl->asList().begin(); iter != _impl->asList().end(); ++iter) {
838 if (iter->bit < 0) { // not a Flag column
839 std::unique_ptr<FitsColumnReader> reader = makeColumnReader(_impl->schema, *iter);
840 if (reader) {
841 _impl->readers.push_back(std::move(reader));
842 } else {
843 LOGLS_WARN("lsst.afw.FitsSchemaInputMapper", "Format " << iter->tform << " for column "
844 << iter->ttype
845 << " not supported; skipping.");
846 }
847 } else { // is a Flag column
848 if (static_cast<std::size_t>(iter->bit) >= _impl->flagKeys.size()) {
849 throw LSST_EXCEPT(afw::fits::FitsError,
850 (boost::format("Flag field '%s' is is in bit %d (0-indexed) of only %d") %
851 iter->ttype % iter->bit % _impl->flagKeys.size())
852 .str());
853 }
854 _impl->flagKeys[iter->bit] = _impl->schema.addField<Flag>(iter->ttype, iter->doc);
855 }
856 }
857 _impl->asList().clear();
858 if (_impl->schema.getRecordSize() <= 0) {
859 throw LSST_EXCEPT(
860 pex::exceptions::LengthError,
861 (boost::format("Non-positive record size: %d; file is corrupt or invalid.") %
862 _impl->schema.getRecordSize()).str()
863 );
864 }
866 return _impl->schema;
867}
#define LOGLS_WARN(logger, message)
Log a warn-level message using an iostream-based interface.
Definition Log.h:659
std::string prefix
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
std::size_t getRecordSize() const
Return the raw size of a record in bytes.
Definition Schema.h:149
static std::size_t PREPPED_ROWS_FACTOR
When processing each column, divide this number by the record size (in bytes) and ask CFITSIO to read...
T max(T... args)
T replace(T... args)

◆ find() [1/2]

FitsSchemaItem const * lsst::afw::table::io::FitsSchemaInputMapper::find ( int column) const

Find an item with the given column number, returning nullptr if no such column exists.

The returned pointer is owned by the mapper object, and should not be deleted. It is invalidated by calls to either erase() or finalize().

Definition at line 323 of file FitsSchemaInputMapper.cc.

323 {
324 auto iter = _impl->byColumn().lower_bound(column);
325 if (iter == _impl->byColumn().end() || iter->column != column) {
326 return nullptr;
327 }
328 return &(*iter);
329}

◆ find() [2/2]

FitsSchemaItem const * lsst::afw::table::io::FitsSchemaInputMapper::find ( std::string const & ttype) const

Find an item with the given column name (ttype), returning nullptr if no such column exists.

The returned pointer is owned by the mapper object, and should not be deleted. It is invalidated by calls to either erase() or finalize().

Definition at line 315 of file FitsSchemaInputMapper.cc.

315 {
316 auto iter = _impl->byName().find(ttype);
317 if (iter == _impl->byName().end()) {
318 return nullptr;
319 }
320 return &(*iter);
321}

◆ hasArchive()

bool lsst::afw::table::io::FitsSchemaInputMapper::hasArchive ( ) const

Return true if the mapper has an InputArchive.

Definition at line 313 of file FitsSchemaInputMapper.cc.

313{ return static_cast<bool>(_impl->archive); }

◆ operator=() [1/2]

FitsSchemaInputMapper & lsst::afw::table::io::FitsSchemaInputMapper::operator= ( FitsSchemaInputMapper && )
default

◆ operator=() [2/2]

FitsSchemaInputMapper & lsst::afw::table::io::FitsSchemaInputMapper::operator= ( FitsSchemaInputMapper const & )
default

◆ readArchive()

bool lsst::afw::table::io::FitsSchemaInputMapper::readArchive ( afw::fits::Fits & fits)

Set the Archive by reading from the HDU specified by the AR_HDU header entry.

Returns true on success, false if there is no AR_HDU entry.

Definition at line 297 of file FitsSchemaInputMapper.cc.

297 {
298 int oldHdu = fits.getHdu();
299 if (_impl->archiveHdu < 0) _impl->archiveHdu = oldHdu + 1;
300 try {
301 fits.setHdu(_impl->archiveHdu);
302 _impl->archive.reset(new io::InputArchive(InputArchive::readFits(fits)));
303 fits.setHdu(oldHdu);
304 return true;
305 } catch (afw::fits::FitsError &) {
306 fits.status = 0;
307 fits.setHdu(oldHdu);
308 _impl->archiveHdu = -1;
309 return false;
310 }
311}
static InputArchive readFits(fits::Fits &fitsfile)
Read an object from an already open FITS object.

◆ readRecord()

void lsst::afw::table::io::FitsSchemaInputMapper::readRecord ( BaseRecord & record,
afw::fits::Fits & fits,
std::size_t row )

Fill a record from a FITS binary table row.

Definition at line 869 of file FitsSchemaInputMapper.cc.

869 {
870 if (!_impl->flagKeys.empty()) {
871 fits.readTableArray<bool>(row, _impl->flagColumn, _impl->flagKeys.size(), _impl->flagWorkspace.get());
872 for (std::size_t bit = 0; bit < _impl->flagKeys.size(); ++bit) {
873 record.set(_impl->flagKeys[bit], _impl->flagWorkspace[bit]);
874 }
875 }
876 if (_impl->nRowsToPrep != 1 && row % _impl->nRowsToPrep == 0) {
877 // Give readers a chance to read and cache up to nRowsToPrep rows-
878 // worth of values.
879 std::size_t size = std::min(_impl->nRowsToPrep, fits.countRows() - row);
880 for (auto const &reader : _impl->readers) {
881 reader->prepRead(row, size, fits);
882 }
883 }
884 for (auto const & reader : _impl->readers) {
885 reader->readCell(record, row, fits, _impl->archive);
886 }
887}
T get(T... args)
T min(T... args)
int row
Definition CR.cc:145

◆ setArchive()

void lsst::afw::table::io::FitsSchemaInputMapper::setArchive ( std::shared_ptr< InputArchive > archive)

Set the Archive to an externally-provided one, overriding any that may have been read.

Definition at line 295 of file FitsSchemaInputMapper.cc.

295{ _impl->archive = archive; }

Member Data Documentation

◆ PREPPED_ROWS_FACTOR

std::size_t lsst::afw::table::io::FitsSchemaInputMapper::PREPPED_ROWS_FACTOR = 1 << 15
static

When processing each column, divide this number by the record size (in bytes) and ask CFITSIO to read this many that of values from that column in a single call.

Both FITS binary tables and afw.table are stored row-major, so reading multiple rows from a single column at a time leads to nonsequential reads. But given the way the I/O code is structured, we tend to get nonsequential reads anyway, and it seems the per-call overload to CFITSIO is sufficiently high that it's best to do this anyway for all but the largest record sizes.

Definition at line 107 of file FitsSchemaInputMapper.h.


The documentation for this class was generated from the following files: