LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
LSST Data Management Base Package
OutputArchive.cc
Go to the documentation of this file.
1// -*- lsst-c++ -*-
2
3#include <typeinfo>
4#include <vector>
5#include <map>
6#include <memory>
7
8#include "boost/format.hpp"
9
10#include "lsst/pex/exceptions.h"
15#include "lsst/afw/fits.h"
16
17namespace lsst {
18namespace afw {
19namespace table {
20namespace io {
21
22namespace {
23
24ArchiveIndexSchema const &indexKeys = ArchiveIndexSchema::get();
25
26// we don't need sorting, but you can't use weak_ptrs as keys in an
27// unordered_map
30
31using MapItem = Map::value_type;
32
33} // namespace
34
35// ----- OutputArchive::Impl --------------------------------------------------------------------------------
36
38public:
40 int catArchive = 1;
41 CatalogVector::iterator iter = _catalogs.begin();
43 for (; iter != _catalogs.end(); ++iter, ++catArchive) {
44 if (iter->getSchema().compare(schema, flags) == flags) {
45 break;
46 }
47 }
48 if (iter == _catalogs.end()) {
50 }
51 if (!iter->getTable()->getMetadata()) {
53 iter->getTable()->setMetadata(metadata);
54 metadata->set("EXTTYPE", "ARCHIVE_DATA");
55 metadata->set("AR_CATN", catArchive, "# of this catalog relative to the start of this archive");
56 }
57 return BaseCatalog(iter->getTable());
58 }
59
61 auto indexRecord = _index.addNew();
62 indexRecord->set(indexKeys.id, id);
63 indexRecord->set(indexKeys.name, name);
64 indexRecord->set(indexKeys.module, module);
65 return indexRecord;
66 }
67
68 void saveEmpty(int id, std::string const &name, std::string const &module) {
69 auto indexRecord = addIndexRecord(id, name, module);
70 indexRecord->set(indexKeys.nRows, 0);
71 indexRecord->set(indexKeys.catPersistable, ArchiveIndexSchema::NO_CATALOGS_SAVED);
72 indexRecord->set(indexKeys.row0, ArchiveIndexSchema::NO_CATALOGS_SAVED);
73 indexRecord->set(indexKeys.catArchive, ArchiveIndexSchema::NO_CATALOGS_SAVED);
74 }
75
76 void saveCatalog(BaseCatalog const &catalog, int id, std::string const &name, std::string const &module,
77 int catPersistable) {
78 auto indexRecord = addIndexRecord(id, name, module);
79 indexRecord->set(indexKeys.catPersistable, catPersistable);
80 indexRecord->set(indexKeys.nRows, catalog.size());
81 int catArchive = 1;
82 CatalogVector::iterator iter = _catalogs.begin();
83 for (; iter != _catalogs.end(); ++iter, ++catArchive) {
84 if (iter->getTable() == catalog.getTable()) {
85 break;
86 }
87 }
88 if (iter == _catalogs.end()) {
90 "All catalogs passed to saveCatalog must be created by makeCatalog");
91 }
92 // Add the name of the class to the header so anyone looking at it can
93 // tell what's stored there. But we don't want to add it multiple times.
94 try {
95 auto names = iter->getTable()->getMetadata()->getArray<std::string>("AR_NAME");
96 if (std::find(names.begin(), names.end(), name) == names.end()) {
97 iter->getTable()->getMetadata()->add("AR_NAME", name, "Class name for objects stored here");
98 }
100 iter->getTable()->getMetadata()->add("AR_NAME", name, "Class name for objects stored here");
101 }
102 // Also add an EXTNAME. The most recent AR_NAME given will be used.
103 iter->getTable()->getMetadata()->set("EXTNAME", name);
104 indexRecord->set(indexKeys.row0, iter->size());
105 indexRecord->set(indexKeys.catArchive, catArchive);
106 iter->insert(iter->end(), catalog.begin(), catalog.end(), false);
107 }
108
109 int put(Persistable const *obj, std::shared_ptr<Impl> const &self, bool permissive) {
110 if (!obj) return 0;
111 if (permissive && !obj->isPersistable()) return 0;
112 int const currentId = _nextId;
113 ++_nextId;
114 OutputArchiveHandle handle(currentId, obj->getPersistenceName(), obj->getPythonModule(), self);
115 obj->write(handle);
116 return currentId;
117 }
118
120 if (!obj) return 0;
121 if (permissive && !obj->isPersistable()) return 0;
122 MapItem item(obj, _nextId);
123 std::pair<Map::iterator, bool> r = _map.insert(item);
124 if (r.second) {
125 // We've never seen this object before. Save it.
126 return put(obj.get(), self, permissive);
127 } else {
128 // We had already saved this object, and insert returned an iterator
129 // to the ID we used before; return that.
130 return r.first->second;
131 }
132 }
133
134 void writeFits(fits::Fits &fitsfile) {
135 _index.getTable()->getMetadata()->set("AR_NCAT", int(_catalogs.size() + 1),
136 "# of catalogs in this archive, including the index");
137 _index.writeFits(fitsfile);
138 int n = 1;
139 for (CatalogVector::const_iterator iter = _catalogs.begin(); iter != _catalogs.end(); ++iter, ++n) {
140 iter->writeFits(fitsfile);
141 }
142 }
143
146 metadata->set("EXTTYPE", "ARCHIVE_INDEX");
147 metadata->set("EXTNAME", "ARCHIVE_INDEX");
148 metadata->set("AR_CATN", 0, "# of this catalog relative to the start of this archive");
149 _index.getTable()->setMetadata(metadata);
150 }
151
152 int _nextId{1};
153 Map _map;
156};
157
158// ----- OutputArchive --------------------------------------------------------------------------------------
159
161
162OutputArchive::OutputArchive(OutputArchive const &other) = default;
163// Delegate to copy constructor for backward compatibility
165
167// Delegate to copy assignment for backward compatibility
168OutputArchive &OutputArchive::operator=(OutputArchive &&other) { return *this = other; }
169
171
172int OutputArchive::put(Persistable const *obj, bool permissive) {
173 if (!_impl.unique()) { // copy on write
174 std::shared_ptr<Impl> tmp(new Impl(*_impl));
175 _impl.swap(tmp);
176 }
177 return _impl->put(obj, _impl, permissive);
178}
179
181 if (!_impl.unique()) { // copy on write
182 std::shared_ptr<Impl> tmp(new Impl(*_impl));
183 _impl.swap(tmp);
184 }
185 return _impl->put(std::move(obj), _impl, permissive);
186}
187
188BaseCatalog const &OutputArchive::getIndexCatalog() const { return _impl->_index; }
189
191 if (n == 0) return _impl->_index;
192 if (std::size_t(n) > _impl->_catalogs.size() || n < 0) {
193 throw LSST_EXCEPT(
195 (boost::format("Catalog number %d is out of range [0,%d]") % n % _impl->_catalogs.size())
196 .str());
197 }
198 return _impl->_catalogs[n - 1];
199}
200
201std::size_t OutputArchive::countCatalogs() const { return _impl->_catalogs.size() + 1; }
202
203void OutputArchive::writeFits(fits::Fits &fitsfile) const { _impl->writeFits(fitsfile); }
204
205// ----- OutputArchiveHandle ------------------------------------------------------------------------------
206
207BaseCatalog OutputArchiveHandle::makeCatalog(Schema const &schema) { return _impl->makeCatalog(schema); }
208
209void OutputArchiveHandle::saveEmpty() { _impl->saveEmpty(_id, _name, _module); }
210
212 _impl->saveCatalog(catalog, _id, _name, _module, _catPersistable);
213 ++_catPersistable;
214}
215
216int OutputArchiveHandle::put(Persistable const *obj, bool permissive) {
217 // Handle doesn't worry about copy-on-write, because Handles should only exist
218 // while an OutputArchive::put() call is active.
219 return _impl->put(obj, _impl, permissive);
220}
221
223 // Handle doesn't worry about copy-on-write, because Handles should only exist
224 // while an OutputArchive::put() call is active.
225 return _impl->put(std::move(obj), _impl, permissive);
226}
227
230 : _id(id), _catPersistable(0), _name(name), _module(module), _impl(impl) {}
231
233} // namespace io
234} // namespace table
235} // namespace afw
236} // namespace lsst
table::Key< std::string > name
Definition: Amplifier.cc:116
table::Key< int > id
Definition: Detector.cc:162
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
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:297
size_type size() const
Return the number of elements in the catalog.
Definition: Catalog.h:413
std::shared_ptr< RecordT > addNew()
Create a new record, add it to the end of the catalog, and return a pointer to it.
Definition: Catalog.h:490
iterator begin()
Iterator access.
Definition: Catalog.h:401
std::shared_ptr< Table > getTable() const
Return the table associated with the catalog.
Definition: Catalog.h:115
void writeFits(std::string const &filename, std::string const &mode="w", int flags=0) const
Write a FITS binary table to a regular file.
Definition: Catalog.h:311
Defines the fields and offsets for a table.
Definition: Schema.h:51
@ EQUAL_NAMES
Fields have the same names (ordered).
Definition: Schema.h:67
@ EQUAL_KEYS
Keys have the same types offsets, and sizes.
Definition: Schema.h:66
A vector of catalogs used by Persistable.
Definition: CatalogVector.h:29
std::shared_ptr< BaseRecord > addIndexRecord(int id, std::string const &name, std::string const &module)
int put(Persistable const *obj, std::shared_ptr< Impl > const &self, bool permissive)
BaseCatalog makeCatalog(Schema const &schema)
int put(std::shared_ptr< Persistable const > obj, std::shared_ptr< Impl > const &self, bool permissive)
void writeFits(fits::Fits &fitsfile)
void saveEmpty(int id, std::string const &name, std::string const &module)
void saveCatalog(BaseCatalog const &catalog, int id, std::string const &name, std::string const &module, int catPersistable)
An object passed to Persistable::write to allow it to persist itself.
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
OutputArchiveHandle(const OutputArchiveHandle &)=delete
void saveEmpty()
Indicate that the object being persisted has no state, and hence will never call makeCatalog() or sav...
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
int put(Persistable const *obj, bool permissive=false)
Save an object to the archive and return a unique ID that can be used to retrieve it from an InputArc...
A multi-catalog archive object used to save table::io::Persistable objects.
Definition: OutputArchive.h:34
std::size_t countCatalogs() const
Return the total number of catalogs, including the index.
int put(std::shared_ptr< Persistable const > obj, bool permissive=false)
Save an object to the archive and return a unique ID that can be used to retrieve it from an InputArc...
void writeFits(fits::Fits &fitsfile) const
Write the archive to an already-open FITS object.
BaseCatalog const & getCatalog(int n) const
Return the nth catalog. Catalog 0 is always the index catalog.
OutputArchive & operator=(OutputArchive const &other)
Assign from another OutputArchive. Saved objects are not deep-copied.
BaseCatalog const & getIndexCatalog() const
Return the index catalog that specifies where objects are stored in the data catalogs.
OutputArchive()
Construct an empty OutputArchive containing no objects.
A base class for objects that can be persisted via afw::table::io Archive classes.
Definition: Persistable.h:74
Class for storing ordered metadata with comments.
Definition: PropertyList.h:68
Reports attempts to exceed implementation-defined length limits for some classes.
Definition: Runtime.h:76
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
T end(T... args)
T find(T... args)
T insert(T... args)
T move(T... args)
CatalogT< BaseRecord > BaseCatalog
Definition: fwd.h:72
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
A base class for image defects.
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.