LSST Applications g0f08755f38+82efc23009,g12f32b3c4e+e7bdf1200e,g1653933729+a8ce1bb630,g1a0ca8cf93+50eff2b06f,g28da252d5a+52db39f6a5,g2bbee38e9b+37c5a29d61,g2bc492864f+37c5a29d61,g2cdde0e794+c05ff076ad,g3156d2b45e+41e33cbcdc,g347aa1857d+37c5a29d61,g35bb328faa+a8ce1bb630,g3a166c0a6a+37c5a29d61,g3e281a1b8c+fb992f5633,g414038480c+7f03dfc1b0,g41af890bb2+11b950c980,g5fbc88fb19+17cd334064,g6b1c1869cb+12dd639c9a,g781aacb6e4+a8ce1bb630,g80478fca09+72e9651da0,g82479be7b0+04c31367b4,g858d7b2824+82efc23009,g9125e01d80+a8ce1bb630,g9726552aa6+8047e3811d,ga5288a1d22+e532dc0a0b,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc28159a63d+37c5a29d61,gcf0d15dbbd+2acd6d4d48,gd7358e8bfb+778a810b6e,gda3e153d99+82efc23009,gda6a2b7d83+2acd6d4d48,gdaeeff99f8+1711a396fd,ge2409df99d+6b12de1076,ge79ae78c31+37c5a29d61,gf0baf85859+d0a5978c5a,gf3967379c6+4954f8c433,gfb92a5be7c+82efc23009,gfec2e1e490+2aaed99252,w.2024.46
LSST Data Management Base Package
Loading...
Searching...
No Matches
InputArchive.cc
Go to the documentation of this file.
1// -*- lsst-c++ -*-
2
3#include "boost/format.hpp"
4
10#include "lsst/afw/fits.h"
11
12namespace lsst {
13namespace afw {
14namespace table {
15namespace io {
16
17namespace {
18
19ArchiveIndexSchema const& indexKeys = ArchiveIndexSchema::get();
20
21// Functor to sort records by ID and then by catPersistable
22struct IndexSortCompare {
23 bool operator()(BaseRecord const& a, BaseRecord const& b) const {
24 if (a.get(indexKeys.id) < b.get(indexKeys.id)) {
25 return true;
26 }
27 if (a.get(indexKeys.id) == b.get(indexKeys.id)) {
28 return a.get(indexKeys.catPersistable) < b.get(indexKeys.catPersistable);
29 }
30 return false;
31 }
32};
33
34} // namespace
35
36// ----- InputArchive::Impl ---------------------------------------------------------------------------------
37
39public:
42 if (id == 0) return empty;
44 if (r.second) {
45 // insertion successful means we haven't reassembled this object yet; do that now.
47 // iterate over records in index with this ID; we know they're sorted by ID and then
48 // by catPersistable, so we can just append to factoryArgs.
50 std::string module;
52 indexIter != _index.end() && indexIter->get(indexKeys.id) == id; ++indexIter) {
53 if (name.empty()) {
54 name = indexIter->get(indexKeys.name);
55 } else if (name != indexIter->get(indexKeys.name)) {
56 throw LSST_EXCEPT(
58 (boost::format("Inconsistent name in index for ID %d; got '%s', expected '%s'") %
59 indexIter->get(indexKeys.id) % indexIter->get(indexKeys.name) % name)
60 .str());
61 }
62 if (module.empty()) {
63 module = indexIter->get(indexKeys.module);
64 } else if (module != indexIter->get(indexKeys.module)) {
65 throw LSST_EXCEPT(
67 (boost::format(
68 "Inconsistent module in index for ID %d; got '%s', expected '%s'") %
69 indexIter->get(indexKeys.id) % indexIter->get(indexKeys.module) % module)
70 .str());
71 }
72 int catArchive = indexIter->get(indexKeys.catArchive);
73 if (catArchive == ArchiveIndexSchema::NO_CATALOGS_SAVED) {
74 break; // object was written with saveEmpty, and hence no catalogs.
75 }
76 std::size_t catN = catArchive - 1;
77 if (catN >= _catalogs.size()) {
78 throw LSST_EXCEPT(
80 (boost::format(
81 "Invalid catalog number in index for ID %d; got '%d', max is '%d'") %
82 indexIter->get(indexKeys.id) % catN % _catalogs.size())
83 .str());
84 }
86 std::size_t i1 = indexIter->get(indexKeys.row0);
87 std::size_t i2 = i1 + indexIter->get(indexKeys.nRows);
88 if (i2 > fullCatalog.size()) {
90 (boost::format("Index and data catalogs do not agree for ID %d; "
91 "catalog %d has %d rows, not %d") %
92 indexIter->get(indexKeys.id) % indexIter->get(indexKeys.catArchive) %
93 fullCatalog.size() % i2)
94 .str());
95 }
96 factoryArgs.push_back(BaseCatalog(fullCatalog.getTable(), fullCatalog.begin() + i1,
97 fullCatalog.begin() + i2));
98 }
99 try {
100 PersistableFactory const& factory = PersistableFactory::lookup(name, module);
101 r.first->second = factory.read(self, factoryArgs);
104 (boost::format("loading object with id=%d, name='%s'") % id % name).str());
105 throw;
106 }
107 // If we're loading the object for the first time, and we've failed, we should have already
108 // thrown an exception, and we assert that here.
109 assert(r.first->second);
110 } else if (!r.first->second) {
111 // If we'd already tried and failed to load this object before - but we'd caught the exception
112 // previously (because the calling code didn't consider that to be a fatal error) - we'll
113 // just throw an exception again. While we can't know exactly what was thrown before,
114 // it's most likely it was a NotFoundError because a needed extension package was not setup.
115 // And conveniently it's appropriate to throw that here too, since now the problem is that
116 // the object should have been loaded into the cache and it wasn't found there.
118 (boost::format("Not trying to reload object with id=%d; a previous attempt to "
119 "load it already failed.") %
120 id)
121 .str());
122 }
123 return r.first->second;
124 }
125
126 Map const& getAll(InputArchive const& self) {
127 int id = 0;
129 if (indexIter->get(indexKeys.id) != id) {
130 id = indexIter->get(indexKeys.id);
131 get(id, self);
132 }
133 }
134 return _map;
135 }
136
138
139 Impl(BaseCatalog const& index, CatalogVector const& catalogs) : _index(index), _catalogs(catalogs) {
140 if (index.getSchema() != indexKeys.schema) {
141 throw LSST_EXCEPT(pex::exceptions::RuntimeError, "Incorrect schema for index catalog");
142 }
144 _index.sort(IndexSortCompare());
145 }
146
147 // No copying
148 Impl(const Impl&) = delete;
149 Impl& operator=(const Impl&) = delete;
150
151 // No moving
152 Impl(Impl&&) = delete;
153 Impl& operator=(Impl&&) = delete;
154
158};
159
160// ----- InputArchive ---------------------------------------------------------------------------------------
161
163
165
167 : _impl(new Impl(index, catalogs)) {}
168
169InputArchive::InputArchive(InputArchive const& other) = default;
170// Delegate to copy constructor for backwards compatibility
172
173InputArchive& InputArchive::operator=(InputArchive const& other) = default;
174// Delegate to copy assignment for backwards compatibility
175InputArchive& InputArchive::operator=(InputArchive&& other) { return *this = other; }
176
178
179std::shared_ptr<Persistable> InputArchive::get(int id) const { return _impl->get(id, *this); }
180
181InputArchive::Map const& InputArchive::getAll() const { return _impl->getAll(*this); }
182
185 std::shared_ptr<daf::base::PropertyList> metadata = index.getTable()->popMetadata();
186 assert(metadata); // BaseCatalog::readFits should always read metadata, even if there's nothing there
187 if (metadata->get<std::string>("EXTTYPE") != "ARCHIVE_INDEX") {
189 boost::format("Wrong value for archive index EXTTYPE: '%s'") %
190 metadata->get<std::string>("EXTTYPE"));
191 }
192 int nCatalogs = metadata->get<int>("AR_NCAT");
193 CatalogVector catalogs;
194 catalogs.reserve(nCatalogs);
195 for (int n = 1; n < nCatalogs; ++n) {
196 fitsfile.setHdu(1, true); // increment HDU by one
197 catalogs.push_back(BaseCatalog::readFits(fitsfile));
198 metadata = catalogs.back().getTable()->popMetadata();
199 if (metadata->get<std::string>("EXTTYPE") != "ARCHIVE_DATA") {
201 boost::format("Wrong value for archive data EXTTYPE: '%s'") %
202 metadata->get<std::string>("EXTTYPE"));
203 }
204 if (metadata->get<int>("AR_CATN") != n) {
205 throw LSST_FITS_EXCEPT(
207 boost::format("Incorrect order for archive catalogs: AR_CATN=%d found at position %d") %
208 metadata->get<int>("AR_CATN") % n);
209 }
210 }
211 std::shared_ptr<Impl> impl(new Impl(index, catalogs));
212 return InputArchive(impl);
213}
214} // namespace io
215} // namespace table
216} // namespace afw
217} // namespace lsst
table::Key< std::string > name
Definition Amplifier.cc:116
table::Key< int > id
Definition Detector.cc:162
#define LSST_EXCEPT_ADD(e, m)
Add the current location and a message to an existing exception before rethrowing it.
Definition Exception.h:54
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
table::Key< int > b
table::Schema schema
Definition python.h:134
An exception thrown when problems are found when reading or writing FITS files.
Definition fits.h:36
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition fits.h:308
Tag types used to declare specialized field types.
Definition misc.h:31
static CatalogT readFits(std::string const &filename, int hdu=fits::DEFAULT_HDU, int flags=0)
Read a FITS binary table from a regular file.
Definition Catalog.h:347
iterator find(typename Field< T >::Value const &value, Key< T > const &key)
Return an iterator to the record with the given value.
Definition Catalog.h:762
iterator begin()
Iterator access.
Definition Catalog.h:400
void sort(Key< T > const &key)
Sort the catalog in-place by the field with the given key.
Definition Catalog.h:755
std::shared_ptr< Table > getTable() const
Return the table associated with the catalog.
Definition Catalog.h:114
Schema getSchema() const
Return the schema associated with the catalog's table.
Definition Catalog.h:117
A vector of catalogs used by Persistable.
Impl & operator=(const Impl &)=delete
Impl(BaseCatalog const &index, CatalogVector const &catalogs)
std::shared_ptr< Persistable > get(int id, InputArchive const &self)
Map const & getAll(InputArchive const &self)
A multi-catalog archive object used to load table::io::Persistable objects.
static InputArchive readFits(fits::Fits &fitsfile)
Read an object from an already open FITS object.
InputArchive & operator=(InputArchive const &other)
Assignment. Does not deep-copy loaded Persistables.
Map const & getAll() const
Load and return all objects in the archive.
std::shared_ptr< Persistable > get(int id) const
Load the Persistable with the given ID and return it.
InputArchive()
Construct an empty InputArchive that contains no objects.
An exception thrown when an InputArchive's contents do not make sense.
Definition Persistable.h:39
A base class for factory classes used to reconstruct objects from records.
virtual std::shared_ptr< Persistable > read(InputArchive const &archive, CatalogVector const &catalogs) const =0
Construct a new object from the given InputArchive and vector of catalogs.
static PersistableFactory const & lookup(std::string const &name, std::string const &module="")
Return the factory that has been registered with the given name.
Provides consistent interface for LSST exceptions.
Definition Exception.h:107
Reports attempts to access elements using an invalid key.
Definition Runtime.h:151
Reports errors that are due to events beyond the control of the program.
Definition Runtime.h:104
#define LSST_FITS_EXCEPT(type, fitsObj,...)
A FITS-related replacement for LSST_EXCEPT that takes an additional Fits object and uses makeErrorMes...
Definition fits.h:105
T get(T... args)
T insert(T... args)
T make_pair(T... args)
CatalogT< BaseRecord > BaseCatalog
Definition fwd.h:72
T size(T... args)
Schema for the index catalog that specifies where objects are stored in the data catalogs.
static constexpr int const NO_CATALOGS_SAVED
Special value used for catArchive, catPersistable, and row0 when an object with no state is saved.
static ArchiveIndexSchema const & get()
Return the singleton instance.