LSST Applications g0f08755f38+9c285cab97,g1635faa6d4+13f3999e92,g1653933729+a8ce1bb630,g1a0ca8cf93+bf6eb00ceb,g28da252d5a+0829b12dee,g29321ee8c0+5700dc9eac,g2bbee38e9b+9634bc57db,g2bc492864f+9634bc57db,g2cdde0e794+c2c89b37c4,g3156d2b45e+41e33cbcdc,g347aa1857d+9634bc57db,g35bb328faa+a8ce1bb630,g3a166c0a6a+9634bc57db,g3e281a1b8c+9f2c4e2fc3,g414038480c+077ccc18e7,g41af890bb2+fde0dd39b6,g5fbc88fb19+17cd334064,g781aacb6e4+a8ce1bb630,g80478fca09+55a9465950,g82479be7b0+d730eedb7d,g858d7b2824+9c285cab97,g9125e01d80+a8ce1bb630,g9726552aa6+10f999ec6a,ga5288a1d22+2a84bb7594,gacf8899fa4+c69c5206e8,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc28159a63d+9634bc57db,gcf0d15dbbd+4b7d09cae4,gda3e153d99+9c285cab97,gda6a2b7d83+4b7d09cae4,gdaeeff99f8+1711a396fd,ge2409df99d+5e831397f4,ge79ae78c31+9634bc57db,gf0baf85859+147a0692ba,gf3967379c6+41c94011de,gf3fb38a9a8+8f07a9901b,gfb92a5be7c+9c285cab97,w.2024.46
LSST Data Management Base Package
Loading...
Searching...
No Matches
Classes | Typedefs | Functions
lsst::afw::table::python Namespace Reference

Classes

class  PyCatalogIndexIterator
 

Typedefs

template<typename Record >
using PyCatalog = pybind11::class_<CatalogT<Record>, std::shared_ptr<CatalogT<Record>>>
 
template<typename Record >
using PyColumnView
 
template<typename Record >
using PySortedCatalog
 

Functions

template<typename T , typename Record >
ndarray::Array< typename Field< T >::Value const, 1, 1 > _getArrayFromCatalog (CatalogT< Record > const &catalog, Key< T > const &key)
 Extract a column from a potentially non-contiguous Catalog.
 
template<typename Record >
ndarray::Array< double const, 1, 1 > _getArrayFromCatalog (CatalogT< Record > const &catalog, Key< Angle > const &key)
 Extract a column from a potentially non-contiguous Catalog (angle specialization)
 
template<typename T , typename Record >
ndarray::Array< typename Field< T >::Value const, 2, 2 > _getArrayFromCatalog (CatalogT< Record > const &catalog, Key< Array< T > > const &key)
 Extract an array-valued column from a potentially non-contiguous Catalog into a 2-d array.
 
template<typename Record >
void _setFlagColumnToArray (CatalogT< Record > &catalog, Key< Flag > const &key, ndarray::Array< bool const, 1 > const &array)
 
template<typename Record >
void _setFlagColumnToScalar (CatalogT< Record > &catalog, Key< Flag > const &key, bool value)
 
template<typename T , typename Record >
void declareCatalogOverloads (PyCatalog< Record > &cls)
 Declare field-type-specific overloaded catalog member functions for one field type.
 
template<typename T , typename Record >
void declareCatalogArrayOverloads (PyCatalog< Record > &cls)
 Declare field-type-specific overloaded catalog member functions for one array-valued field type.
 
template<typename Record >
PyCatalog< Record > declareCatalog (cpputils::python::WrapperCollection &wrappers, std::string const &name, bool isBase=false)
 Wrap an instantiation of lsst::afw::table::CatalogT<Record>.
 
template<typename Record >
PyColumnView< Record > declareColumnView (cpputils::python::WrapperCollection &wrappers, std::string const &name, bool isBase=false)
 Declare member and static functions for a given instantiation of lsst::afw::table::ColumnViewT<RecordT>.
 
template<typename Record >
PySortedCatalog< Record > declareSortedCatalog (cpputils::python::WrapperCollection &wrappers, std::string const &name, bool isBase=false)
 Wrap an instantiation of lsst::afw::table::SortedCatalogT<Record>.
 

Typedef Documentation

◆ PyCatalog

template<typename Record >
using lsst::afw::table::python::PyCatalog = pybind11::class_<CatalogT<Record>, std::shared_ptr<CatalogT<Record>>>

Definition at line 39 of file catalog.h.

◆ PyColumnView

template<typename Record >
using lsst::afw::table::python::PyColumnView
Initial value:
pybind11::class_<ColumnViewT<Record>, std::shared_ptr<ColumnViewT<Record>>, BaseColumnView>

Definition at line 39 of file columnView.h.

◆ PySortedCatalog

Initial value:
pybind11::class_<SortedCatalogT<Record>, std::shared_ptr<SortedCatalogT<Record>>, CatalogT<Record>>

Definition at line 39 of file sortedCatalog.h.

Function Documentation

◆ _getArrayFromCatalog() [1/3]

template<typename Record >
ndarray::Array< double const, 1, 1 > lsst::afw::table::python::_getArrayFromCatalog ( CatalogT< Record > const & catalog,
Key< Angle > const & key )

Extract a column from a potentially non-contiguous Catalog (angle specialization)

Parameters
catalogCatalog
keyKey to column to extract

Definition at line 59 of file catalog.h.

62 {
63 ndarray::Array<double, 1, 1> out = ndarray::allocate(catalog.size());
64 auto outIter = out.begin();
65 auto inIter = catalog.begin();
66 for (; inIter != catalog.end(); ++inIter, ++outIter) {
67 *outIter = inIter->get(key).asRadians();
68 }
69 return out;
70}
Tag types used to declare specialized field types.
Definition misc.h:31

◆ _getArrayFromCatalog() [2/3]

template<typename T , typename Record >
ndarray::Array< typename Field< T >::Value const, 2, 2 > lsst::afw::table::python::_getArrayFromCatalog ( CatalogT< Record > const & catalog,
Key< Array< T > > const & key )

Extract an array-valued column from a potentially non-contiguous Catalog into a 2-d array.

Parameters
catalogCatalog
keyKey to column to extract

Definition at line 75 of file catalog.h.

78 {
79 ndarray::Array<typename Field<T>::Value, 2, 2> out = ndarray::allocate(catalog.size(), key.getSize());
80 auto outIter = out.begin();
81 auto inIter = catalog.begin();
82 for (; inIter != catalog.end(); ++inIter, ++outIter) {
83 *outIter = inIter->get(key);
84 }
85 return out;
86}

◆ _getArrayFromCatalog() [3/3]

template<typename T , typename Record >
ndarray::Array< typename Field< T >::Value const, 1, 1 > lsst::afw::table::python::_getArrayFromCatalog ( CatalogT< Record > const & catalog,
Key< T > const & key )

Extract a column from a potentially non-contiguous Catalog.

Parameters
catalogCatalog
keyKey to column to extract

Definition at line 43 of file catalog.h.

46 {
47 ndarray::Array<typename Field<T>::Value, 1, 1> out = ndarray::allocate(catalog.size());
48 auto outIter = out.begin();
49 auto inIter = catalog.begin();
50 for (; inIter != catalog.end(); ++inIter, ++outIter) {
51 *outIter = inIter->get(key);
52 }
53 return out;
54}

◆ _setFlagColumnToArray()

template<typename Record >
void lsst::afw::table::python::_setFlagColumnToArray ( CatalogT< Record > & catalog,
Key< Flag > const & key,
ndarray::Array< bool const, 1 > const & array )

Definition at line 89 of file catalog.h.

93 {
94 if (array.size() != catalog.size()) {
95 throw LSST_EXCEPT(
97 (boost::format("Catalog has %d rows, while array has %d elements.")
98 % catalog.size() % array.size()).str()
99 );
100 }
101 auto catIter = catalog.begin();
102 auto arrayIter = array.begin();
103 for (; catIter != catalog.end(); ++catIter, ++arrayIter) {
104 catIter->set(key, *arrayIter);
105 }
106}
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
Reports attempts to exceed implementation-defined length limits for some classes.
Definition Runtime.h:76

◆ _setFlagColumnToScalar()

template<typename Record >
void lsst::afw::table::python::_setFlagColumnToScalar ( CatalogT< Record > & catalog,
Key< Flag > const & key,
bool value )

Definition at line 109 of file catalog.h.

113 {
114 for (auto catIter = catalog.begin(); catIter != catalog.end(); ++catIter) {
115 catIter->set(key, value);
116 }
117}

◆ declareCatalog()

template<typename Record >
PyCatalog< Record > lsst::afw::table::python::declareCatalog ( cpputils::python::WrapperCollection & wrappers,
std::string const & name,
bool isBase = false )

Wrap an instantiation of lsst::afw::table::CatalogT<Record>.

In addition to calling this method you must call addCatalogMethods on the class object in Python.

Template Parameters
RecordRecord type, e.g. BaseRecord or SimpleRecord.
Parameters
[in]wrappersPackage manager class will be added to.
[in]nameName prefix of the record type, e.g. "Base" or "Simple".
[in]isBaseWhether this instantiation is only being used as a base class (used to set the class name).

Definition at line 276 of file catalog.h.

277 {
278 namespace py = pybind11;
279 using namespace pybind11::literals;
280
282 using Table = typename Record::Table;
283 using ColumnView = typename Record::ColumnView;
284
286 if (isBase) {
287 fullName = "_" + name + "CatalogBase";
288 } else {
289 fullName = name + "Catalog";
290 }
291
292 // We need py::dynamic_attr() in the class definition to support our Python-side caching
293 // of the associated ColumnView.
294 return wrappers.wrapType(
295 PyCatalog<Record>(wrappers.module, fullName.c_str(), py::dynamic_attr()),
296 [](auto &mod, auto &cls) {
297 /* Constructors */
298 cls.def(py::init<Schema const &>(), "schema"_a);
299 cls.def(py::init<std::shared_ptr<Table> const &>(), "table"_a);
300 cls.def(py::init<Catalog const &>(), "other"_a);
301
302 /* Static Methods */
303 cls.def_static("readFits", (Catalog(*)(std::string const &, int, int)) & Catalog::readFits,
304 "filename"_a, "hdu"_a = fits::DEFAULT_HDU, "flags"_a = 0);
305 cls.def_static("readFits", (Catalog(*)(fits::MemFileManager &, int, int)) & Catalog::readFits,
306 "manager"_a, "hdu"_a = fits::DEFAULT_HDU, "flags"_a = 0);
307 // readFits taking Fits objects not wrapped, because Fits objects are not wrapped.
308
309 /* Methods */
310 cls.def("getTable", &Catalog::getTable);
311 cls.def_property_readonly("table", &Catalog::getTable);
312 cls.def("getSchema", &Catalog::getSchema);
313 cls.def_property_readonly("schema", &Catalog::getSchema);
314 cls.def("capacity", &Catalog::capacity);
315 cls.def("__len__", &Catalog::size);
316 cls.def("resize", &Catalog::resize);
317
318 // Use private names for the following so the public Python method
319 // can manage the _column cache
320 cls.def("_getColumnView", &Catalog::getColumnView);
321 cls.def("_addNew", &Catalog::addNew);
322 cls.def("_extend", [](Catalog &self, Catalog const &other, bool deep) {
323 self.insert(self.end(), other.begin(), other.end(), deep);
324 });
325 cls.def("_extend", [](Catalog &self, Catalog const &other, SchemaMapper const &mapper) {
326 self.insert(mapper, self.end(), other.begin(), other.end());
327 });
328 cls.def("_append",
329 [](Catalog &self, std::shared_ptr<Record> const &rec) { self.push_back(rec); });
330 cls.def("_delitem_", [](Catalog &self, std::ptrdiff_t i) {
331 self.erase(self.begin() + cpputils::python::cppIndex(self.size(), i));
332 });
333 cls.def("_delslice_", [](Catalog &self, py::slice const &s) {
334 Py_ssize_t start = 0, stop = 0, step = 0, length = 0;
335 if (PySlice_GetIndicesEx(s.ptr(), self.size(), &start, &stop, &step, &length) != 0) {
336 throw py::error_already_set();
337 }
338 if (step != 1) {
339 throw py::index_error("Slice step must not exactly 1");
340 }
341 self.erase(self.begin() + start, self.begin() + stop);
342 });
343 cls.def("_clear", &Catalog::clear);
344
345 cls.def("set", &Catalog::set);
346 cls.def("_getitem_", [](Catalog &self, int i) {
347 return self.get(cpputils::python::cppIndex(self.size(), i));
348 });
349 cls.def("__iter__", [](Catalog & self) {
350 // We wrap a custom iterator class here for two reasons:
351 //
352 // - letting Python define an automatic iterator that
353 // delegates to __getitem__(int) is super slow, because
354 // __getitem__ is overloaded;
355 //
356 // - using pybind11::make_iterator on either Catalog's own
357 // iterator type or Catalog.getInternal()'s iterator (a
358 // std::vector iterator) opens us up to undefined
359 // behavior if a modification to the container those
360 // iterators during iteration.
361 //
362 // Our custom iterator holds a Catalog and an integer
363 // index, allowing it to do a bounds check at ever access,
364 // but unlike its Python equivalent there's no overloading
365 // in play (and even if it was, C++ overloading is resolved
366 // at compile-time).
367 //
368 // This custom iterator also yields `shared_ptr<Record>`.
369 // That should make the return value policy passed to
370 // `py::make_iterator` irrelevant; we don't need to keep
371 // the catalog alive in order to keep a record alive,
372 // because the `shared_ptr` manages the record's lifetime.
373 // But we still need keep_alive on the `__iter__` method
374 // itself to keep the raw catalog pointer alive as long as
375 // the iterator is alive.
376 return py::make_iterator(
377 PyCatalogIndexIterator<Record>(&self, 0),
378 PyCatalogIndexIterator<Record>(&self, self.size())
379 );
380 }, py::keep_alive<0, 1>());
381 cls.def("isContiguous", &Catalog::isContiguous);
382 cls.def("writeFits",
383 (void (Catalog::*)(std::string const &, std::string const &, int) const) &
384 Catalog::writeFits,
385 "filename"_a, "mode"_a = "w", "flags"_a = 0);
386 cls.def("writeFits",
387 (void (Catalog::*)(fits::MemFileManager &, std::string const &, int) const) &
388 Catalog::writeFits,
389 "manager"_a, "mode"_a = "w", "flags"_a = 0);
390 cls.def("reserve", &Catalog::reserve);
391 cls.def("subset",
392 (Catalog(Catalog::*)(ndarray::Array<bool const, 1> const &) const) & Catalog::subset);
393 cls.def("subset",
394 (Catalog(Catalog::*)(std::ptrdiff_t, std::ptrdiff_t, std::ptrdiff_t) const) &
395 Catalog::subset);
396
397 declareCatalogOverloads<std::int32_t>(cls);
398 declareCatalogOverloads<std::int64_t>(cls);
399 declareCatalogOverloads<float>(cls);
400 declareCatalogOverloads<double>(cls);
401 declareCatalogOverloads<lsst::geom::Angle>(cls);
402 declareCatalogArrayOverloads<std::uint8_t>(cls);
403 declareCatalogArrayOverloads<std::uint16_t>(cls);
404 declareCatalogArrayOverloads<int>(cls);
405 declareCatalogArrayOverloads<float>(cls);
406 declareCatalogArrayOverloads<double>(cls);
407
408 cls.def("_get_column_from_key",
409 [](Catalog const &self, Key<Flag> const &key, pybind11::object py_column_view) {
410 // Extra ColumnView arg and return value here are
411 // for consistency with the non-flag overload (up
412 // in declareCatalogOverloads). Casting the array
413 // (from ndarray::Array to numpy.ndarray) before
414 // return is also for consistency with that, though
415 // it's not strictly necessary.
416 return pybind11::make_tuple(
417 _getArrayFromCatalog(self, key),
418 py_column_view
419 );
420 });
421 cls.def(
422 "_set_flag",
423 [](Catalog &self, Key<Flag> const & key, ndarray::Array<bool const, 1> const & array) {
424 _setFlagColumnToArray(self, key, array);
425 }
426 );
427 cls.def(
428 "_set_flag",
429 [](Catalog &self, Key<Flag> const & key, bool value) {
430 _setFlagColumnToScalar(self, key, value);
431 }
432 );
433
434 });
435}
int const step
SchemaMapper * mapper
T c_str(T... args)
PyType wrapType(PyType cls, ClassWrapperCallback function, bool setModuleName=true)
Add a type (class or enum) wrapper, deferring method and other attribute definitions until finish() i...
Definition python.h:391
void _setFlagColumnToArray(CatalogT< Record > &catalog, Key< Flag > const &key, ndarray::Array< bool const, 1 > const &array)
Definition catalog.h:89
ndarray::Array< typename Field< T >::Value const, 1, 1 > _getArrayFromCatalog(CatalogT< Record > const &catalog, Key< T > const &key)
Extract a column from a potentially non-contiguous Catalog.
Definition catalog.h:43
void _setFlagColumnToScalar(CatalogT< Record > &catalog, Key< Flag > const &key, bool value)
Definition catalog.h:109
writeFits(filename, stamps, metadata, type_name, write_mask, write_variance, write_archive=False)
Definition stamps.py:40
STL namespace.

◆ declareCatalogArrayOverloads()

template<typename T , typename Record >
void lsst::afw::table::python::declareCatalogArrayOverloads ( PyCatalog< Record > & cls)

Declare field-type-specific overloaded catalog member functions for one array-valued field type.

Template Parameters
TArray element type.
RecordRecord type, e.g. BaseRecord or SimpleRecord.
Parameters
[in]clsCatalog pybind11 class.

Definition at line 235 of file catalog.h.

235 {
236 namespace py = pybind11;
237 using namespace pybind11::literals;
238
240 using Value = typename Field<T>::Value;
241 using ColumnView = typename Record::ColumnView;
242
243 cls.def("_get_column_from_key",
244 [](Catalog const &self, Key<Array<T>> const &key, pybind11::object py_column_view) {
246 if (!column_view && self.isContiguous()) {
247 // If there's no column view cached, but there could be,
248 // make one (and we'll return it so it can be cached by
249 // the calling Python code).
250 column_view = std::make_shared<ColumnView>(self.getColumnView());
251 py_column_view = pybind11::cast(column_view);
252 }
253 if (column_view) {
254 // If there is a column view, use it to return view.
255 return pybind11::make_tuple((*column_view)[key].shallow(), column_view);
256 }
257 // If we can't make a column view, extract a copy.
258 return pybind11::make_tuple(_getArrayFromCatalog(self, key), column_view);
259 });
260}
A class used as a handle to a particular field in a table.
Definition Key.h:53
T Value
the type returned by BaseRecord::get
Definition FieldBase.h:42

◆ declareCatalogOverloads()

template<typename T , typename Record >
void lsst::afw::table::python::declareCatalogOverloads ( PyCatalog< Record > & cls)

Declare field-type-specific overloaded catalog member functions for one field type.

Template Parameters
TField type.
RecordRecord type, e.g. BaseRecord or SimpleRecord.
Parameters
[in]clsCatalog pybind11 class.

Definition at line 168 of file catalog.h.

168 {
169 namespace py = pybind11;
170 using namespace pybind11::literals;
171
173 using Value = typename Field<T>::Value;
174 using ColumnView = typename Record::ColumnView;
175
176 cls.def("isSorted", (bool (Catalog::*)(Key<T> const &) const) & Catalog::isSorted);
177 cls.def("sort", (void (Catalog::*)(Key<T> const &)) & Catalog::sort);
178 cls.def("find", [](Catalog &self, Value const &value, Key<T> const &key) -> std::shared_ptr<Record> {
179 auto iter = self.find(value, key);
180 if (iter == self.end()) {
181 return nullptr;
182 };
183 return iter;
184 });
185 cls.def("upper_bound", [](Catalog &self, Value const &value, Key<T> const &key) -> std::ptrdiff_t {
186 return self.upper_bound(value, key) - self.begin();
187 });
188 cls.def("lower_bound", [](Catalog &self, Value const &value, Key<T> const &key) -> std::ptrdiff_t {
189 return self.lower_bound(value, key) - self.begin();
190 });
191 cls.def("equal_range", [](Catalog &self, Value const &value, Key<T> const &key) {
192 auto p = self.equal_range(value, key);
193 return py::slice(p.first - self.begin(), p.second - self.begin(), 1);
194 });
195 cls.def("between", [](Catalog &self, Value const &lower, Value const &upper, Key<T> const &key) {
196 std::ptrdiff_t a = self.lower_bound(lower, key) - self.begin();
197 std::ptrdiff_t b = self.upper_bound(upper, key) - self.begin();
198 return py::slice(a, b, 1);
199 });
200
201 cls.def("_get_column_from_key",
202 [](Catalog const &self, Key<T> const &key, pybind11::object py_column_view) {
203 std::shared_ptr<ColumnView> column_view = py_column_view.cast<std::shared_ptr<ColumnView>>();
204 if (!column_view && self.isContiguous()) {
205 // If there's no column view cached, but there could be,
206 // make one (and we'll return it so it can be cached by
207 // the calling Python code).
208 column_view = std::make_shared<ColumnView>(self.getColumnView());
209 py_column_view = pybind11::cast(column_view);
210 }
211 if (column_view) {
212 // If there is a column view, use it to return a view.
213 if constexpr (std::is_same_v<T, Angle>) {
214 // numpy doesn't recognize our Angle type, so we return
215 // double radians.
216 return pybind11::make_tuple(column_view->get_radians_array(key), column_view);
217 } else {
218 return pybind11::make_tuple((*column_view)[key].shallow(), column_view);
219 }
220 }
221 // If we can't make a column view, extract a copy.
222 return pybind11::make_tuple(_getArrayFromCatalog(self, key), column_view);
223 });
224}
table::Key< int > b

◆ declareColumnView()

template<typename Record >
PyColumnView< Record > lsst::afw::table::python::declareColumnView ( cpputils::python::WrapperCollection & wrappers,
std::string const & name,
bool isBase = false )

Declare member and static functions for a given instantiation of lsst::afw::table::ColumnViewT<RecordT>.

Template Parameters
RecordRecord type, e.g. BaseRecord or SimpleRecord.
Parameters
[in]wrappersPackage manager class will be added to.
[in]nameName prefix of the record type, e.g. "Base" or "Simple".
[in]isBaseWhether this instantiation is only being used as a base class (used to set the class name).

Definition at line 53 of file columnView.h.

54 {
56 if (isBase) {
57 fullName = "_" + name + "ColumnViewBase";
58 } else {
59 fullName = name + "ColumnView";
60 }
61 return wrappers.wrapType(PyColumnView<Record>(wrappers.module, fullName.c_str()),
62 [](auto& mod, auto& cls) {
63 cls.def("getTable", &ColumnViewT<Record>::getTable);
64 cls.def_property_readonly("table", &ColumnViewT<Record>::getTable);
65 });
66};

◆ declareSortedCatalog()

template<typename Record >
PySortedCatalog< Record > lsst::afw::table::python::declareSortedCatalog ( cpputils::python::WrapperCollection & wrappers,
std::string const & name,
bool isBase = false )

Wrap an instantiation of lsst::afw::table::SortedCatalogT<Record>.

In addition to calling this method (which also instantiates and wraps the CatalogT base class), you must call addCatalogMethods on the class object in Python.

Template Parameters
RecordRecord type, e.g. BaseRecord or SimpleRecord.
Parameters
[in]wrappersPackage manager class will be added to.
[in]nameName prefix of the record type, e.g. "Base" or "Simple".
[in]isBaseWhether this instantiation is only being used as a base class (used to set the class name).

Definition at line 57 of file sortedCatalog.h.

58 {
59 namespace py = pybind11;
60 using namespace pybind11::literals;
61
63 using Table = typename Record::Table;
64
65 auto clsBase = declareCatalog<Record>(wrappers, name, true);
66
68 if (isBase) {
69 fullName = "_" + name + "SortedCatalogBase";
70 } else {
71 fullName = name + "Catalog";
72 }
73
74 // We need py::dynamic_attr() in the class definition to support our Python-side caching
75 // of the associated ColumnView.
76 return wrappers.wrapType(
77 PySortedCatalog<Record>(wrappers.module, fullName.c_str(), py::dynamic_attr()),
78 [clsBase](auto &mod, auto &cls) {
79 /* Constructors */
80 cls.def(pybind11::init<Schema const &>());
81 cls.def(pybind11::init<std::shared_ptr<Table> const &>(),
82 "table"_a = std::shared_ptr<Table>());
83 cls.def(pybind11::init<Catalog const &>());
84
85 /* Overridden and Variant Methods */
86 cls.def_static("readFits", (Catalog(*)(std::string const &, int, int)) & Catalog::readFits,
87 "filename"_a, "hdu"_a = fits::DEFAULT_HDU, "flags"_a = 0);
88 cls.def_static("readFits", (Catalog(*)(fits::MemFileManager &, int, int)) & Catalog::readFits,
89 "manager"_a, "hdu"_a = fits::DEFAULT_HDU, "flags"_a = 0);
90 // readFits taking Fits objects not wrapped, because Fits objects are not wrapped.
91
92 cls.def("subset",
93 (Catalog(Catalog::*)(ndarray::Array<bool const, 1> const &) const) & Catalog::subset);
94 cls.def("subset",
95 (Catalog(Catalog::*)(std::ptrdiff_t, std::ptrdiff_t, std::ptrdiff_t) const) &
96 Catalog::subset);
97
98 // The following three methods shadow those in the base class in C++ (unlike the base class
99 // versions, they do not require a key argument because we assume it's the ID key). In
100 // Python, we make that appear as though the key argument is available but has a default
101 // value. If that key is not None, we delegate to the base class.
102 cls.def("isSorted",
103 [clsBase](py::object const &self, py::object key) -> py::object {
104 if (key.is(py::none())) {
105 key = self.attr("table").attr("getIdKey")();
106 }
107 return clsBase.attr("isSorted")(self, key);
108 },
109 "key"_a = py::none());
110 cls.def("sort",
111 [clsBase](py::object const &self, py::object key) -> py::object {
112 if (key.is(py::none())) {
113 key = self.attr("table").attr("getIdKey")();
114 }
115 return clsBase.attr("sort")(self, key);
116 },
117 "key"_a = py::none());
118 cls.def("find",
119 [clsBase](py::object const &self, py::object const &value,
120 py::object key) -> py::object {
121 if (key.is(py::none())) {
122 key = self.attr("table").attr("getIdKey")();
123 }
124 return clsBase.attr("find")(self, value, key);
125 },
126 "value"_a, "key"_a = py::none());
127
128 });
129}