LSST Applications  21.0.0+04719a4bac,21.0.0-1-ga51b5d4+f5e6047307,21.0.0-11-g2b59f77+a9c1acf22d,21.0.0-11-ga42c5b2+86977b0b17,21.0.0-12-gf4ce030+76814010d2,21.0.0-13-g1721dae+760e7a6536,21.0.0-13-g3a573fe+768d78a30a,21.0.0-15-g5a7caf0+f21cbc5713,21.0.0-16-g0fb55c1+b60e2d390c,21.0.0-19-g4cded4ca+71a93a33c0,21.0.0-2-g103fe59+bb20972958,21.0.0-2-g45278ab+04719a4bac,21.0.0-2-g5242d73+3ad5d60fb1,21.0.0-2-g7f82c8f+8babb168e8,21.0.0-2-g8f08a60+06509c8b61,21.0.0-2-g8faa9b5+616205b9df,21.0.0-2-ga326454+8babb168e8,21.0.0-2-gde069b7+5e4aea9c2f,21.0.0-2-gecfae73+1d3a86e577,21.0.0-2-gfc62afb+3ad5d60fb1,21.0.0-25-g1d57be3cd+e73869a214,21.0.0-3-g357aad2+ed88757d29,21.0.0-3-g4a4ce7f+3ad5d60fb1,21.0.0-3-g4be5c26+3ad5d60fb1,21.0.0-3-g65f322c+e0b24896a3,21.0.0-3-g7d9da8d+616205b9df,21.0.0-3-ge02ed75+a9c1acf22d,21.0.0-4-g591bb35+a9c1acf22d,21.0.0-4-g65b4814+b60e2d390c,21.0.0-4-gccdca77+0de219a2bc,21.0.0-4-ge8a399c+6c55c39e83,21.0.0-5-gd00fb1e+05fce91b99,21.0.0-6-gc675373+3ad5d60fb1,21.0.0-64-g1122c245+4fb2b8f86e,21.0.0-7-g04766d7+cd19d05db2,21.0.0-7-gdf92d54+04719a4bac,21.0.0-8-g5674e7b+d1bd76f71f,master-gac4afde19b+a9c1acf22d,w.2021.13
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 
17 namespace lsst {
18 namespace afw {
19 namespace table {
20 namespace io {
21 
22 namespace {
23 
24 ArchiveIndexSchema 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 
31 typedef Map::value_type MapItem;
32 
33 } // namespace
34 
35 // ----- OutputArchive::Impl --------------------------------------------------------------------------------
36 
38 public:
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  }
99  } catch (pex::exceptions::NotFoundError &) {
100  iter->getTable()->getMetadata()->add("AR_NAME", name, "Class name for objects stored here");
101  }
102  indexRecord->set(indexKeys.row0, iter->size());
103  indexRecord->set(indexKeys.catArchive, catArchive);
104  iter->insert(iter->end(), catalog.begin(), catalog.end(), false);
105  }
106 
107  int put(Persistable const *obj, std::shared_ptr<Impl> const &self, bool permissive) {
108  if (!obj) return 0;
109  if (permissive && !obj->isPersistable()) return 0;
110  int const currentId = _nextId;
111  ++_nextId;
112  OutputArchiveHandle handle(currentId, obj->getPersistenceName(), obj->getPythonModule(), self);
113  obj->write(handle);
114  return currentId;
115  }
116 
117  int put(std::shared_ptr<Persistable const> obj, std::shared_ptr<Impl> const &self, bool permissive) {
118  if (!obj) return 0;
119  if (permissive && !obj->isPersistable()) return 0;
120  MapItem item(obj, _nextId);
121  std::pair<Map::iterator, bool> r = _map.insert(item);
122  if (r.second) {
123  // We've never seen this object before. Save it.
124  return put(obj.get(), self, permissive);
125  } else {
126  // We had already saved this object, and insert returned an iterator
127  // to the ID we used before; return that.
128  return r.first->second;
129  }
130  }
131 
132  void writeFits(fits::Fits &fitsfile) {
133  _index.getTable()->getMetadata()->set("AR_NCAT", int(_catalogs.size() + 1),
134  "# of catalogs in this archive, including the index");
135  _index.writeFits(fitsfile);
136  int n = 1;
137  for (CatalogVector::const_iterator iter = _catalogs.begin(); iter != _catalogs.end(); ++iter, ++n) {
138  iter->writeFits(fitsfile);
139  }
140  }
141 
144  metadata->set("EXTTYPE", "ARCHIVE_INDEX");
145  metadata->set("AR_CATN", 0, "# of this catalog relative to the start of this archive");
146  _index.getTable()->setMetadata(metadata);
147  }
148 
149  int _nextId;
150  Map _map;
153 };
154 
155 // ----- OutputArchive --------------------------------------------------------------------------------------
156 
158 
160 // Delegate to copy constructor for backward compatibility
162 
164  _impl = other._impl;
165  return *this;
166 }
167 // Delegate to copy assignment for backward compatibility
169 
171 
172 int 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 
188 BaseCatalog 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 
201 int OutputArchive::countCatalogs() const { return _impl->_catalogs.size() + 1; }
202 
203 void OutputArchive::writeFits(fits::Fits &fitsfile) const { _impl->writeFits(fitsfile); }
204 
205 // ----- OutputArchiveHandle ------------------------------------------------------------------------------
206 
207 BaseCatalog OutputArchiveHandle::makeCatalog(Schema const &schema) { return _impl->makeCatalog(schema); }
208 
209 void OutputArchiveHandle::saveEmpty() { _impl->saveEmpty(_id, _name, _module); }
210 
212  _impl->saveCatalog(catalog, _id, _name, _module, _catPersistable);
213  ++_catPersistable;
214 }
215 
216 int 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
ItemVariant const * other
Definition: Schema.cc:56
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
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:485
size_type size() const
Return the number of elements in the catalog.
Definition: Catalog.h:408
iterator begin()
Iterator access.
Definition: Catalog.h:396
std::shared_ptr< Table > getTable() const
Return the table associated with the catalog.
Definition: Catalog.h:114
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:306
Defines the fields and offsets for a table.
Definition: Schema.h:50
@ EQUAL_NAMES
Fields have the same names (ordered).
Definition: Schema.h:66
@ EQUAL_KEYS
Keys have the same types offsets, and sizes.
Definition: Schema.h:65
A vector of catalogs used by Persistable.
Definition: CatalogVector.h:29
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)
std::shared_ptr< BaseRecord > addIndexRecord(int id, std::string const &name, std::string const &module)
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
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.
int countCatalogs() const
Return the total number of catalogs, including the index.
A base class for objects that can be persisted via afw::table::io Archive classes.
Definition: Persistable.h:74
virtual bool isPersistable() const noexcept
Return true if this particular object can be persisted using afw::table::io.
Definition: Persistable.h:102
virtual std::string getPythonModule() const
Return the fully-qualified Python module that should be imported to guarantee that its factory is reg...
Definition: Persistable.cc:36
virtual std::string getPersistenceName() const
Return the unique name used to persist this object and look up its factory.
Definition: Persistable.cc:34
virtual void write(OutputArchiveHandle &handle) const
Write the object to one or more catalogs.
Definition: Persistable.cc:38
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 get(T... args)
T insert(T... args)
T move(T... args)
CatalogT< BaseRecord > BaseCatalog
Definition: fwd.h:71
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.