LSST Applications 26.0.0,g0265f82a02+6660c170cc,g07994bdeae+30b05a742e,g0a0026dc87+17526d298f,g0a60f58ba1+17526d298f,g0e4bf8285c+96dd2c2ea9,g0ecae5effc+c266a536c8,g1e7d6db67d+6f7cb1f4bb,g26482f50c6+6346c0633c,g2bbee38e9b+6660c170cc,g2cc88a2952+0a4e78cd49,g3273194fdb+f6908454ef,g337abbeb29+6660c170cc,g337c41fc51+9a8f8f0815,g37c6e7c3d5+7bbafe9d37,g44018dc512+6660c170cc,g4a941329ef+4f7594a38e,g4c90b7bd52+5145c320d2,g58be5f913a+bea990ba40,g635b316a6c+8d6b3a3e56,g67924a670a+bfead8c487,g6ae5381d9b+81bc2a20b4,g93c4d6e787+26b17396bd,g98cecbdb62+ed2cb6d659,g98ffbb4407+81bc2a20b4,g9ddcbc5298+7f7571301f,ga1e77700b3+99e9273977,gae46bcf261+6660c170cc,gb2715bf1a1+17526d298f,gc86a011abf+17526d298f,gcf0d15dbbd+96dd2c2ea9,gdaeeff99f8+0d8dbea60f,gdb4ec4c597+6660c170cc,ge23793e450+96dd2c2ea9,gf041782ebf+171108ac67
LSST Data Management Base Package
Loading...
Searching...
No Matches
Schema.cc
Go to the documentation of this file.
1#include <list>
2#include <memory>
3#include <stdexcept>
4#include <type_traits>
5#include <variant>
6
7#include "boost/preprocessor/seq/for_each.hpp"
8#include "boost/preprocessor/tuple/to_seq.hpp"
9
14#include "lsst/afw/fits.h"
15
16namespace lsst {
17namespace afw {
18namespace table {
19
20//-----------------------------------------------------------------------------------------------------------
21//----- Miscellaneous Utilities -----------------------------------------------------------------------------
22//-----------------------------------------------------------------------------------------------------------
23
24namespace {
25
26inline char getDelimiter() { return '_'; }
27
28// Concatenate two strings with a single-character delimiter between them
29std::string join(std::string const &a, std::string const &b, char delimiter) {
30 std::string full;
31 full.reserve(a.size() + b.size() + 1);
32 full += a;
33 full.push_back(delimiter);
34 full += b;
35 return full;
36}
37
38// Functor to compare two ItemVariants for Key equality.
39class ItemFunctors {
40 using ItemVariant = detail::SchemaImpl::ItemVariant;
41
42 // Compares keys (including types).
43 struct KeyHelper {
44
45 template <typename T>
46 bool operator()(SchemaItem<T> const &a, SchemaItem<T> const &b) const {
47 return a.key == b.key;
48 }
49
50 template <typename T, typename U>
51 bool operator()(SchemaItem<T> const &a, SchemaItem<U> const &b) const {
52 return false;
53 }
54 };
55
56public:
57 static bool compareKeys(ItemVariant const &a, ItemVariant const &b) {
58 return std::visit(KeyHelper(), a, b);
59 }
60
61 static bool compareNames(ItemVariant const &a, ItemVariant const &b) {
62 return std::visit(
63 [](auto const & a, auto const & b) { return a.field.getName() == b.field.getName(); },
64 a, b
65 );
66 }
67
68 static bool compareDocs(ItemVariant const &a, ItemVariant const &b) {
69 return std::visit(
70 [](auto const & a, auto const & b) { return a.field.getDoc() == b.field.getDoc(); },
71 a, b
72 );
73 }
74
75 static bool compareUnits(ItemVariant const &a, ItemVariant const &b) {
76 return std::visit(
77 [](auto const & a, auto const & b) { return a.field.getUnits() == b.field.getUnits(); },
78 a, b
79 );
80 }
81};
82
83} // namespace
84
85//-----------------------------------------------------------------------------------------------------------
86//----- SchemaImpl implementation ---------------------------------------------------------------------------
87//-----------------------------------------------------------------------------------------------------------
88
89namespace detail {
90
91template <typename T>
93 NameMap::const_iterator i = _names.lower_bound(name);
94 if (i != _names.end() && i->first == name) {
95 // got an exact match; we're done if it has the right type, and dead if it doesn't.
96 try {
97 return std::get<SchemaItem<T>>(_items[i->second]);
98 } catch (std::bad_variant_access &err) {
100 (boost::format("Field '%s' does not have the given type.") % name).str());
101 }
102 }
104 (boost::format("Field with name '%s' not found with type '%s'.") % name %
106 .str());
107}
108
109template <typename T>
111 OffsetMap::const_iterator i = _offsets.lower_bound(key.getOffset());
112 if (i != _offsets.end() && i->first == key.getOffset()) {
113 try {
114 return std::get<SchemaItem<T>>(_items[i->second]);
115 } catch (std::bad_variant_access &err) {
116 // just swallow the exception; this might be a subfield key that points to the beginning.
117 }
118 }
120 (boost::format("Field or subfield with offset %d not found with type '%s'.") %
122 .str());
123}
124
125// We handle Flag fields separately when searching for keys, because their keys aren't like the others.
127 FlagMap::const_iterator i = _flags.lower_bound(std::make_pair(key.getOffset(), key.getBit()));
128 if (i != _flags.end()) {
129 if (i->first.first == key.getOffset() && i->first.second == key.getBit()) {
130 try {
131 return std::get<SchemaItem<Flag>>(_items[i->second]);
132 } catch (std::bad_variant_access &err) {
134 (boost::format("Flag field with offset %d and bit %d not found.") %
135 key.getOffset() % key.getBit())
136 .str());
137 }
138 }
139 }
141 (boost::format("Flag field with offset %d and bit %d not found.") % key.getOffset() %
142 key.getBit())
143 .str());
144}
145
146//----- Replacing an existing SchemaItem --------------------------------------------------------------------
147
148// This is easier to understand if you start reading from the bottom of this section, with
149// SchemaImpl::replaceField, then work your way up.
150
151namespace {
152
153// Find an exact SchemaItem by key ('exact' means no subfields, unlike the find member function above)
154// Return the index into the item container.
155template <typename T>
156inline std::size_t findKey(SchemaImpl::OffsetMap const &offsets, SchemaImpl::FlagMap const &flags, Key<T> const &key,
157 bool throwIfMissing = true) {
158 SchemaImpl::OffsetMap::const_iterator i = offsets.find(key.getOffset());
159 if (i == offsets.end()) {
160 if (throwIfMissing) {
162 (boost::format("Key of type %s with offset %d not found in Schema") %
164 .str());
165 } else {
167 }
168 }
169 return i->second;
170}
171
172// Like the above, but special-cased for Flag
173inline std::size_t findKey(SchemaImpl::OffsetMap const &offsets, SchemaImpl::FlagMap const &flags,
174 Key<Flag> const &key, bool throwIfMissing = true) {
175 SchemaImpl::FlagMap::const_iterator i = flags.find(std::make_pair(key.getOffset(), key.getBit()));
176 if (i == flags.end()) {
177 if (throwIfMissing) {
178 throw LSST_EXCEPT(
179 pex::exceptions::NotFoundError,
180 (boost::format("Key of type Flag with offset %d and bit %d not found in Schema") %
181 key.getOffset() % key.getBit())
182 .str());
183 } else {
185 }
186 }
187 return i->second;
188}
189
190} // namespace
191
192template <typename T>
193void SchemaImpl::replaceField(Key<T> const &key, Field<T> const &field) {
194 NameMap::iterator j = _names.find(field.getName());
195 SchemaItem<T> *item = nullptr;
196 if (j != _names.end()) {
197 // The field name is already present in the Schema; see if it's the one we're replacing.
198 // If we can get the old item with this, we don't need to update the name map at all.
199 item = std::get_if<SchemaItem<T>>(&_items[j->second]);
200 if (!item || key != item->key) {
201 throw LSST_EXCEPT(
203 (boost::format("Field with name '%s' already present in schema with a different key.") %
204 field.getName())
205 .str());
206 }
207 }
208 if (!item) { // Need to find the original item by key, since it's a new name.
209 std::size_t index = findKey(_offsets, _flags, key);
210 item = std::get_if<SchemaItem<T>>(&_items[index]);
211 if (!item) {
213 (boost::format("Incorrect key type '%s'.") % key).str());
214 }
215 j = _names.find(item->field.getName());
216 _names.insert(j, std::pair<std::string, std::size_t>(field.getName(), j->second));
217 _names.erase(j);
218 }
219 item->field = field;
220}
221
222//----- Other SchemaImpl things -----------------------------------------------------------------------------
223
224template <typename T>
225int SchemaImpl::contains(SchemaItem<T> const &item, int flags) const {
226 if (!(flags & Schema::EQUAL_KEYS)) {
228 "Can only check whether item is in schema if flags & EQUAL_KEYS");
229 }
230 SchemaItem<T> const *cmpItem = nullptr;
231 std::size_t index = findKey(_offsets, _flags, item.key, false);
232 if (index != std::numeric_limits<size_t>::max()) {
233 cmpItem = std::get_if<SchemaItem<T> >(&_items[index]);
234 if (!cmpItem) {
235 if ((flags & Schema::EQUAL_NAMES) && cmpItem->field.getName() != item.field.getName()) {
236 flags &= ~Schema::EQUAL_NAMES;
237 }
238 if ((flags & Schema::EQUAL_DOCS) && cmpItem->field.getDoc() != item.field.getDoc()) {
239 flags &= ~Schema::EQUAL_DOCS;
240 }
241 if ((flags & Schema::EQUAL_UNITS) && cmpItem->field.getUnits() != item.field.getUnits()) {
242 flags &= ~Schema::EQUAL_UNITS;
243 }
244 }
245 } else {
246 flags = 0;
247 }
248 return flags;
249}
250
253 if (topOnly) {
254 for (auto const &_name : _names) {
255 std::size_t sep = _name.first.find(getDelimiter());
256 if (sep == std::string::npos) {
257 result.insert(result.end(), _name.first);
258 } else {
259 result.insert(result.end(), _name.first.substr(0, sep));
260 }
261 }
262 } else {
263 for (auto const &_name : _names) {
264 result.insert(result.end(), _name.first);
265 }
266 }
267 return result;
268}
269
272 if (topOnly) {
273 for (NameMap::const_iterator i = _names.lower_bound(prefix); i != _names.end(); ++i) {
274 if (i->first.compare(0, prefix.size(), prefix) != 0) break;
275 std::size_t sep = i->first.find(getDelimiter(), prefix.size() + 1);
276 if (sep == std::string::npos) {
277 result.insert(result.end(),
278 i->first.substr(prefix.size() + 1, i->first.size() - prefix.size()));
279 } else {
280 result.insert(result.end(), i->first.substr(prefix.size() + 1, sep - prefix.size() - 1));
281 }
282 }
283 } else {
284 for (NameMap::const_iterator i = _names.lower_bound(prefix); i != _names.end(); ++i) {
285 if (i->first.compare(0, prefix.size(), prefix) != 0) break;
286 result.insert(result.end(),
287 i->first.substr(prefix.size() + 1, i->first.size() - prefix.size() - 1));
288 }
289 }
290 return result;
291}
292
293template <typename T>
294Key<Array<T> > SchemaImpl::addField(Field<Array<T> > const &field, bool doReplace) {
295 if (field.isVariableLength()) {
296 // Variable-length array: allocate space for one ndarray
297 return addFieldImpl(sizeof(ndarray::Array<T, 1, 1>), 1, field, doReplace);
298 }
299 // Fixed-length array: allocate space for getElementCount() elements of type T
300 return addFieldImpl(sizeof(typename Field<T>::Element), field.getElementCount(), field, doReplace);
301}
302
304 if (field.isVariableLength()) {
305 // Variable-length string: allocate space for one std::string
306 return addFieldImpl(sizeof(std::string), 1, field, doReplace);
307 }
308 // Fixed-length string: allocate space for getElementCount() chars
309 return addFieldImpl(sizeof(typename Field<std::string>::Element), field.getElementCount(), field,
310 doReplace);
311}
312
313template <typename T>
314Key<T> SchemaImpl::addField(Field<T> const &field, bool doReplace) {
315 return addFieldImpl(sizeof(typename Field<T>::Element), field.getElementCount(), field, doReplace);
316}
317
318Key<Flag> SchemaImpl::addField(Field<Flag> const &field, bool doReplace) {
319 static std::size_t const ELEMENT_SIZE = sizeof(Field<Flag>::Element);
321 _names.insert(std::pair<std::string, std::size_t>(field.getName(), _items.size()));
322 if (!result.second) {
323 if (doReplace) {
324 SchemaItem<Flag> *item = std::get_if<SchemaItem<Flag>>(&_items[result.first->second]);
325 if (!item) {
326 throw LSST_EXCEPT(
328 (boost::format("Cannot replace field with name '%s' because types differ.") %
329 field.getName())
330 .str());
331 }
332 if (item->field.getElementCount() != field.getElementCount()) {
333 throw LSST_EXCEPT(
335 (boost::format("Cannot replace field with name '%s' because sizes differ.") %
336 field.getName())
337 .str());
338 }
339 item->field = field;
340 return item->key;
341 } else {
342 throw LSST_EXCEPT(
344 (boost::format("Field with name '%s' already present in schema.") % field.getName())
345 .str());
346 }
347 } else {
348 if (!_initFlag || _lastFlagBit >= ELEMENT_SIZE * 8) {
349 std::size_t padding = ELEMENT_SIZE - _recordSize % ELEMENT_SIZE;
350 if (padding != ELEMENT_SIZE) {
351 _recordSize += padding;
352 }
353 _lastFlagField = _recordSize;
354 _lastFlagBit = 0;
355 _initFlag = true;
356 _recordSize += field.getElementCount() * ELEMENT_SIZE;
357 }
358 SchemaItem<Flag> item(detail::Access::makeKey(_lastFlagField, _lastFlagBit), field);
359 ++_lastFlagBit;
361 std::make_pair(item.key.getOffset(), item.key.getBit()), _items.size()));
362 _items.push_back(item);
363 return item.key;
364 }
365}
366
367template <typename T>
368Key<T> SchemaImpl::addFieldImpl(std::size_t elementSize, std::size_t elementCount, Field<T> const &field, bool doReplace) {
370 _names.insert(std::pair<std::string, std::size_t>(field.getName(), _items.size()));
371 if (!result.second) {
372 if (doReplace) {
373 SchemaItem<T> *item = std::get_if<SchemaItem<T>>(&_items[result.first->second]);
374 if (!item) {
375 throw LSST_EXCEPT(
377 (boost::format("Cannot replace field with name '%s' because types differ.") %
378 field.getName())
379 .str());
380 }
381 // n.b. we don't use elementCount here because we *do* want variable length arrays (for
382 // which we set elementCount == 1, but field->getElementCount() == -1) to compare as different
383 // from fixed-length arrays with a single element.
384 if (item->field.getElementCount() != field.getElementCount()) {
385 throw LSST_EXCEPT(
387 (boost::format("Cannot replace field with name '%s' because sizes differ.") %
388 field.getName())
389 .str());
390 }
391 item->field = field;
392 return item->key;
393 } else {
394 throw LSST_EXCEPT(
396 (boost::format("Field with name '%s' already present in schema.") % field.getName())
397 .str());
398 }
399 } else {
400 std::size_t padding = elementSize - _recordSize % elementSize;
401 if (padding != elementSize) {
402 _recordSize += padding;
403 }
404 SchemaItem<T> item(detail::Access::makeKey(field, _recordSize), field);
405 _recordSize += elementCount * elementSize;
406 _offsets.insert(std::pair<std::size_t, std::size_t>(item.key.getOffset(), _items.size()));
407 _items.push_back(item);
408 return item.key;
409 }
410}
411
412} // namespace detail
413
414//-----------------------------------------------------------------------------------------------------------
415//----- Schema implementation -------------------------------------------------------------------------------
416//-----------------------------------------------------------------------------------------------------------
417
418int const Schema::VERSION;
419
420Schema::Schema() : _impl(std::make_shared<Impl>()), _aliases(std::make_shared<AliasMap>()) {}
421
422Schema::Schema(Schema const &other) = default;
423// Delegate to copy constructor for backwards compatibility
424Schema::Schema(Schema &&other) : Schema(other) {}
425
426Schema &Schema::operator=(Schema const &) = default;
427Schema &Schema::operator=(Schema &&) = default;
428Schema::~Schema() = default;
429
430Schema Schema::readFits(std::string const &filename, int hdu) {
432 fp.setHdu(hdu);
433 return readFits(fp);
434}
435
438 fp.setHdu(hdu);
439 return readFits(fp);
440}
441
444 fitsfile.readMetadata(header, false);
445 return fromFitsMetadata(header);
446}
447
449 return io::FitsSchemaInputMapper(header, stripMetadata).finalize();
450}
451
453 // delegate to utility funcs at top of this file
454 return afw::table::join(a, b, getDelimiter());
455}
456
457void Schema::_edit() {
458 if (!_impl.unique()) {
459 std::shared_ptr<Impl> data(std::make_shared<Impl>(*_impl));
460 _impl.swap(data);
461 }
462}
463
464std::set<std::string> Schema::getNames(bool topOnly) const { return _impl->getNames(topOnly); }
465
466template <typename T>
468 std::string tmp(name);
469 _aliases->_apply(tmp);
470 return _impl->find<T>(tmp);
471}
472
473template <typename T>
475 return _impl->find(key);
476}
477
478template <typename T>
479Key<T> Schema::addField(Field<T> const &field, bool doReplace) {
480 _edit();
481 return _impl->addField(field, doReplace);
482}
483
484template <typename T>
485void Schema::replaceField(Key<T> const &key, Field<T> const &field) {
486 _edit();
487 _impl->replaceField(key, field);
488}
489
490int Schema::contains(Schema const &other, int flags) const {
491 if (_impl == other._impl) return flags;
492 if (_impl->getItems().size() < other._impl->getItems().size()) return 0;
493 int result = flags;
494 if (result & EQUAL_FIELDS) {
495 for (Impl::ItemContainer::const_iterator i1 = _impl->getItems().begin(),
496 i2 = other._impl->getItems().begin();
497 i2 != other._impl->getItems().end(); ++i1, ++i2) {
498 if ((result & EQUAL_KEYS) && !ItemFunctors::compareKeys(*i1, *i2)) result &= ~EQUAL_KEYS;
499 if ((result & EQUAL_NAMES) && !ItemFunctors::compareNames(*i1, *i2)) result &= ~EQUAL_NAMES;
500 if ((result & EQUAL_DOCS) && !ItemFunctors::compareDocs(*i1, *i2)) result &= ~EQUAL_DOCS;
501 if ((result & EQUAL_UNITS) && !ItemFunctors::compareUnits(*i1, *i2)) result &= ~EQUAL_UNITS;
502 if (!result) break;
503 }
504 }
505 if ((result & EQUAL_ALIASES) && !getAliasMap()->contains(*other.getAliasMap())) result &= ~EQUAL_ALIASES;
506 return result;
507}
508
509int Schema::compare(Schema const &other, int flags) const {
510 int result = contains(other, flags);
511 if (_impl->getItems().size() != other._impl->getItems().size()) {
512 result &= ~EQUAL_FIELDS;
513 }
514 if (getAliasMap()->size() != other.getAliasMap()->size()) {
515 result &= ~EQUAL_ALIASES;
516 }
517 return result;
518}
519
521 // Completely arbitrary seed
522 std::size_t result = 17;
523 auto hasher = [&result](auto const &item) { result = utils::hashCombine(result, item.key); };
524 forEach(hasher);
525 return result;
526}
527
528template <typename T>
529int Schema::contains(SchemaItem<T> const &item, int flags) const {
530 return _impl->contains(item, flags);
531}
532
534 if (!aliases) {
535 aliases = std::make_shared<AliasMap>();
536 }
537 _aliases = aliases;
538}
539
540void Schema::disconnectAliases() { _aliases = std::make_shared<AliasMap>(*_aliases); }
541
542//----- Stringification -------------------------------------------------------------------------------------
543
544namespace {
545
546// Schema::forEach functor used for stringificationx
547struct Stream {
548 using result_type = void;
549
550 template <typename T>
551 void operator()(SchemaItem<T> const &item) const {
552 *os << " (" << item.field << ", " << item.key << "),\n";
553 }
554
555 explicit Stream(std::ostream *os_) : os(os_) {}
556
558};
559
560} // namespace
561
563 os << "Schema(\n";
564 schema.forEach(Stream(&os));
565 for (auto const &iter : *schema.getAliasMap()) {
566 os << " '" << iter.first << "'->'" << iter.second << "'\n";
567 }
568 return os << ")\n";
569}
570
571//-----------------------------------------------------------------------------------------------------------
572//----- SubSchema implementation ----------------------------------------------------------------------------
573//-----------------------------------------------------------------------------------------------------------
574
576 // delegate to utility funcs at top of this file
577 return afw::table::join(a, b, getDelimiter());
578}
579
580SubSchema::SubSchema(std::shared_ptr<Impl> impl, std::shared_ptr<AliasMap> aliases, std::string const &name)
581 : _impl(impl), _aliases(aliases), _name(name) {}
582
583template <typename T>
585 return _impl->find<T>(_aliases->apply(join(_name, name)));
586}
587
589 return SubSchema(_impl, _aliases, join(_name, name));
590}
591
592std::set<std::string> SubSchema::getNames(bool topOnly) const { return _impl->getNames(topOnly, _name); }
593
594//-----------------------------------------------------------------------------------------------------------
595//----- Explicit instantiation ------------------------------------------------------------------------------
596//-----------------------------------------------------------------------------------------------------------
597
598// Note: by instantiating the public functions below, we also instantiate a lot of the private
599// implementation functions. If you move some of those to a different source file, you'll need
600// more explicit instantiation.
601
602#define INSTANTIATE_LAYOUT(r, data, elem) \
603 template Key<elem> Schema::addField(Field<elem> const &, bool); \
604 template SchemaItem<elem> Schema::find(std::string const &) const; \
605 template SchemaItem<elem> Schema::find(Key<elem> const &) const; \
606 template SchemaItem<elem> detail::SchemaImpl::find(std::string const &name) const; \
607 template int Schema::contains(SchemaItem<elem> const &, int) const; \
608 template void Schema::replaceField(Key<elem> const &, Field<elem> const &); \
609 template SchemaItem<elem> SubSchema::find(std::string const &) const;
610
613} // namespace table
614} // namespace afw
615} // namespace lsst
py::object result
Definition _schema.cc:429
table::Key< std::string > name
Definition Amplifier.cc:116
table::Key< int > field
Definition ApCorrMap.cc:77
char * data
Definition BaseRecord.cc:61
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
#define INSTANTIATE_LAYOUT(r, data, elem)
Definition Schema.cc:602
std::ostream * os
Definition Schema.cc:557
std::string prefix
table::Key< int > b
table::Key< int > a
table::Schema schema
Definition python.h:134
T begin(T... args)
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition fits.h:308
void readMetadata(daf::base::PropertySet &metadata, bool strip=false)
Read a FITS header into a PropertySet or PropertyList.
Definition fits.cc:1102
Lifetime-management for memory that goes into FITS memory files.
Definition fits.h:125
Mapping class that holds aliases for a Schema.
Definition AliasMap.h:36
Tag types used to declare specialized field types.
Definition misc.h:31
A class used as a handle to a particular field in a table.
Definition Key.h:53
std::size_t getOffset() const noexcept
Return the offset (in bytes) of this field within a record.
Definition Key.h:87
Defines the fields and offsets for a table.
Definition Schema.h:51
void forEach(F &func) const
Apply a functor to each SchemaItem in the Schema.
Definition Schema.h:214
static int const VERSION
Definition Schema.h:57
Schema()
Construct an empty Schema.
Definition Schema.cc:420
void disconnectAliases()
Sever the connection between this schema and any others with which it shares aliases.
Definition Schema.cc:540
Schema & operator=(Schema const &other)
std::string join(std::string const &a, std::string const &b) const
Join strings using the field delimiter appropriate for this Schema.
Definition Schema.cc:452
void setAliasMap(std::shared_ptr< AliasMap > aliases)
Set the alias map.
Definition Schema.cc:533
std::shared_ptr< AliasMap > getAliasMap() const
Return the map of aliases.
Definition Schema.h:279
std::set< std::string > getNames(bool topOnly=false) const
Return a set of field names in the schema.
Definition Schema.cc:464
static Schema fromFitsMetadata(daf::base::PropertyList &header, bool stripMetadata=true)
Construct from reading a FITS header.
Definition Schema.cc:448
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
static Schema readFits(std::string const &filename, int hdu=fits::DEFAULT_HDU)
Construct from reading a FITS file.
Definition Schema.cc:430
std::size_t hash_value() const noexcept
Return a hash of this object.
Definition Schema.cc:520
int contains(Schema const &other, int flags=EQUAL_KEYS) const
Test whether the given schema is a subset of this.
Definition Schema.cc:490
int compare(Schema const &other, int flags=EQUAL_KEYS) const
Do a detailed equality comparison of two schemas.
Definition Schema.cc:509
void replaceField(Key< T > const &key, Field< T > const &field)
Replace the Field (name/description) for an existing Key.
Definition Schema.cc:485
SchemaItem< T > find(std::string const &name) const
Find a SchemaItem in the Schema by name.
Definition Schema.cc:467
@ EQUAL_DOCS
Fields have the same documentation (ordered).
Definition Schema.h:68
@ EQUAL_NAMES
Fields have the same names (ordered).
Definition Schema.h:67
@ EQUAL_UNITS
Fields have the same units (ordered).
Definition Schema.h:69
@ EQUAL_KEYS
Keys have the same types offsets, and sizes.
Definition Schema.h:66
@ EQUAL_FIELDS
Fields are identical (but aliases may not be).
Definition Schema.h:70
@ EQUAL_ALIASES
Schemas have identical AliasMaps.
Definition Schema.h:71
A proxy type for name lookups in a Schema.
Definition Schema.h:367
std::string join(std::string const &a, std::string const &b) const
Join strings using the field delimiter appropriate for this Schema.
Definition Schema.cc:575
SubSchema operator[](std::string const &name) const
Return a nested proxy.
Definition Schema.cc:588
std::set< std::string > getNames(bool topOnly=false) const
Return a set of nested names that start with the SubSchema's prefix.
Definition Schema.cc:592
SchemaItem< T > find(std::string const &name) const
Find a nested SchemaItem by name.
Definition Schema.cc:584
static Key< T > makeKey(std::size_t offset)
Definition Access.h:65
A private implementation class to hide the messy details of Schema.
Definition SchemaImpl.h:45
std::set< std::string > getNames(bool topOnly) const
Return a set of field names (used to implement Schema::getNames).
Definition Schema.cc:251
Key< T > addField(Field< T > const &field, bool doReplace=false)
Add a field to the schema (used to implement Schema::addField).
Definition Schema.cc:314
int contains(SchemaItem< T > const &item, int flags) const
Definition Schema.cc:225
void replaceField(Key< T > const &key, Field< T > const &field)
Replace the Field in an existing SchemaItem without changing the Key.
Definition Schema.cc:193
SchemaItem< T > find(std::string const &name) const
Find an item by name (used to implement Schema::find).
Definition Schema.cc:92
std::map< std::pair< std::size_t, std::size_t >, std::size_t > FlagMap
A map from Flag field offset/bit pairs to position in the vector, so we can do Flag field lookups.
Definition SchemaImpl.h:63
ItemContainer const & getItems() const
Return the vector of SchemaItem variants.
Definition SchemaImpl.h:133
decltype(makeItemVariantType(FieldTypes{})) ItemVariant
A Boost.Variant type that can hold any one of the allowed SchemaItem types.
Definition SchemaImpl.h:55
std::map< std::size_t, std::size_t > OffsetMap
A map from standard field offsets to position in the vector, so we can do field lookups.
Definition SchemaImpl.h:61
A class that describes a mapping from a FITS binary table to an afw::table Schema.
Schema finalize()
Map any remaining items into regular Schema items, and return the final Schema.
Class for storing ordered metadata with comments.
Reports invalid arguments.
Definition Runtime.h:66
Reports errors in the logical structure of the program.
Definition Runtime.h:46
Reports attempts to access elements using an invalid key.
Definition Runtime.h:151
Reports errors from accepting an object of an unexpected or inappropriate type.
Definition Runtime.h:167
T end(T... args)
T erase(T... args)
T find(T... args)
T insert(T... args)
T lower_bound(T... args)
T make_pair(T... args)
T max(T... args)
std::ostream & operator<<(std::ostream &os, BaseRecord const &record)
BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_COLUMNVIEW_SCALAR, _, BOOST_PP_TUPLE_TO_SEQ(AFW_TABLE_SCALAR_FIELD_TYPE_N, AFW_TABLE_SCALAR_FIELD_TYPE_TUPLE)) BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_COLUMNVIEW_ARRAY
std::size_t hashCombine(std::size_t seed) noexcept
Combine hashes.
Definition hashCombine.h:35
STL namespace.
T push_back(T... args)
T reserve(T... args)
T size(T... args)
A description of a field in a table.
Definition Field.h:24
typename FieldBase< T >::Element Element
Type used to store field data in the table (a field may have multiple elements).
Definition Field.h:26
A simple pair-like struct for mapping a Field (name and description) with a Key (used for actual data...
Definition SchemaImpl.h:22
T substr(T... args)
T swap(T... args)
#define AFW_TABLE_FIELD_TYPE_N
Definition types.h:38
#define AFW_TABLE_FIELD_TYPE_TUPLE
Definition types.h:43
T unique(T... args)