lsst.afw  20.0.0-4-gde602ef96+5
ProductBoundedField.cc
Go to the documentation of this file.
1 // -*- LSST-C++ -*-
2 /*
3  * LSST Data Management System
4  * Copyright 2008-2014 LSST Corporation.
5  *
6  * This product includes software developed by the
7  * LSST Project (http://www.lsst.org/).
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the LSST License Statement and
20  * the GNU General Public License along with this program. If not,
21  * see <http://www.lsstcorp.org/LegalNotices/>.
22  */
23 
24 #include <algorithm>
25 
26 #include "ndarray/eigen.h"
27 
28 #include "lsst/pex/exceptions.h"
35 
36 namespace lsst {
37 namespace afw {
38 
39 template std::shared_ptr<math::ProductBoundedField> table::io::PersistableFacade<
40  math::ProductBoundedField>::dynamicCast(std::shared_ptr<table::io::Persistable> const&);
41 
42 namespace math {
43 
44 namespace {
45 
46 lsst::geom::Box2I checkAndExtractBBox(std::vector<std::shared_ptr<BoundedField const>> const & factors) {
47  if (factors.size() < 1u) {
48  throw LSST_EXCEPT(
49  pex::exceptions::LengthError,
50  "ProductBoundedField requires at least one BoundedField factor."
51  );
52  }
53  auto iter = factors.begin();
54  auto bbox = (**iter).getBBox();
55  ++iter;
56  for (; iter != factors.end(); ++iter) {
57  if ((**iter).getBBox() != bbox) {
58  throw LSST_EXCEPT(
59  pex::exceptions::InvalidParameterError,
60  (boost::format("Inconsistency in ProductBoundedField bboxes: %s != %s") %
61  bbox % (**iter).getBBox()).str()
62  );
63  }
64  }
65  return bbox;
66 }
67 
68 } // anonymous
69 
71  BoundedField(checkAndExtractBBox(factors)), _factors(factors)
72 {}
73 
77 
78 double ProductBoundedField::evaluate(lsst::geom::Point2D const& position) const {
79  double product = 1.0;
80  for (auto const & field : _factors) {
81  product *= field->evaluate(position);
82  }
83  return product;
84 }
85 
86 ndarray::Array<double, 1, 1> ProductBoundedField::evaluate(
87  ndarray::Array<double const, 1> const& x,
88  ndarray::Array<double const, 1> const& y
89 ) const {
90  if (x.getShape() != y.getShape()) {
91  throw LSST_EXCEPT(
93  (boost::format("Inconsistent shapes: %s != %s") % x.getShape() % y.getShape()).str()
94  );
95  }
96  ndarray::Array<double, 1, 1> z = ndarray::allocate(x.getShape());
97  std::fill(z.begin(), z.end(), 1.0);
98  for (auto const & field : _factors) {
99  ndarray::asEigenArray(z) *= ndarray::asEigenArray(field->evaluate(x, y));
100  }
101  return z;
102 }
103 
104 // ------------------ persistence ---------------------------------------------------------------------------
105 
106 namespace {
107 
108 struct PersistenceHelper {
109  table::Schema schema;
110  table::Key<int> id;
111 
112  static PersistenceHelper const & get() {
113  static PersistenceHelper const instance;
114  return instance;
115  }
116 
117 private:
118 
119  PersistenceHelper() :
120  schema(),
121  id(schema.addField<int>("id", "Archive ID of a BoundedField factor."))
122  {}
123 
124  PersistenceHelper(PersistenceHelper const &) = delete;
125  PersistenceHelper(PersistenceHelper &&) = delete;
126  PersistenceHelper & operator=(PersistenceHelper const &) = delete;
127  PersistenceHelper & operator=(PersistenceHelper &&) = delete;
128 
129  ~PersistenceHelper() noexcept = default;
130 
131 };
132 
133 class ProductBoundedFieldFactory : public table::io::PersistableFactory {
134 public:
135  explicit ProductBoundedFieldFactory(std::string const& name)
136  : afw::table::io::PersistableFactory(name) {}
137 
138  std::shared_ptr<table::io::Persistable> read(InputArchive const& archive,
139  CatalogVector const& catalogs) const override {
140  LSST_ARCHIVE_ASSERT(catalogs.size() == 1u);
141  auto const & keys = PersistenceHelper::get();
142  auto const & cat = catalogs.front();
144  factors.reserve(cat.size());
145  for (auto const & record : cat) {
146  factors.push_back(archive.get<BoundedField>(record.get(keys.id)));
147  }
148  return std::make_shared<ProductBoundedField>(factors);
149  }
150 };
151 
152 std::string getProductBoundedFieldPersistenceName() { return "ProductBoundedField"; }
153 
154 ProductBoundedFieldFactory registration(getProductBoundedFieldPersistenceName());
155 
156 } // namespace
157 
158 bool ProductBoundedField::isPersistable() const noexcept {
159  return std::all_of(_factors.begin(), _factors.end(),
160  [](auto const & field) { return field->isPersistable(); });
161 }
162 
164  return getProductBoundedFieldPersistenceName();
165 }
166 
167 std::string ProductBoundedField::getPythonModule() const { return "lsst.afw.math"; }
168 
170  auto const & keys = PersistenceHelper::get();
171  table::BaseCatalog catalog = handle.makeCatalog(keys.schema);
172  catalog.reserve(_factors.size());
173  for (auto const & field : _factors) {
174  catalog.addNew()->set(keys.id, handle.put(field));
175  }
176  handle.saveCatalog(catalog);
177 }
178 
179 // ------------------ operators -----------------------------------------------------------------------------
180 
183  bool multiplied = false;
184  for (auto & field : factors) {
185  try {
186  field = (*field) * scale;
187  multiplied = true;
188  break;
189  } catch (pex::exceptions::LogicError &) {}
190  }
191  if (!multiplied) {
192  ndarray::Array<double, 2, 2> coefficients = ndarray::allocate(1, 1);
193  coefficients[0][0] = scale;
194  factors.push_back(std::make_shared<ChebyshevBoundedField>(getBBox(), coefficients));
195  }
196  return std::make_shared<ProductBoundedField>(factors);
197 }
198 
200  auto rhsCasted = dynamic_cast<ProductBoundedField const*>(&rhs);
201  if (!rhsCasted) return false;
202 
203  return (getBBox() == rhsCasted->getBBox()) &&
204  std::equal(_factors.begin(), _factors.end(),
205  rhsCasted->_factors.begin(), rhsCasted->_factors.end(),
206  [](auto const & a, auto const & b) { return *a == *b; });
207 }
208 
209 std::string ProductBoundedField::toString() const {
211  os << "ProductBoundedField([";
212  for (auto const & field : _factors) {
213  os << (*field) << ", ";
214  }
215  os << "])";
216  return os.str();
217 }
218 
219 } // namespace math
220 } // namespace afw
221 } // namespace lsst
y
int y
Definition: SpanSet.cc:49
lsst::afw::math::ProductBoundedField::ProductBoundedField
ProductBoundedField(std::vector< std::shared_ptr< BoundedField const >> const &factors)
Construct from a sequence of BoundedField factors.
Definition: ProductBoundedField.cc:70
LSST_ARCHIVE_ASSERT
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
Definition: Persistable.h:48
std::string
STL class.
std::equal
T equal(T... args)
std::shared_ptr
STL class.
lsst::afw::math::BoundedField
An abstract base class for 2-d functions defined on an integer bounding boxes.
Definition: BoundedField.h:55
coefficients
ndarray::Array< double const, 2, 2 > coefficients
Definition: ChebyshevBoundedField.cc:276
lsst::afw::math::ProductBoundedField
A BoundedField that lazily multiplies a sequence of other BoundedFields.
Definition: ProductBoundedField.h:37
std::vector::reserve
T reserve(T... args)
lsst::afw::table::io::OutputArchiveHandle
An object passed to Persistable::write to allow it to persist itself.
Definition: OutputArchive.h:118
lsst::afw::math::ProductBoundedField::evaluate
double evaluate(lsst::geom::Point2D const &position) const override
Evaluate the field at the given point.
Definition: ProductBoundedField.cc:78
std::vector
STL class.
lsst::afw::table::io::OutputArchiveHandle::saveCatalog
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
Definition: OutputArchive.cc:211
keys
def keys(self)
CatalogVector.h
std::all_of
T all_of(T... args)
lsst::afw::geom.transform.transformContinued.name
string name
Definition: transformContinued.py:32
lsst::afw::math::ProductBoundedField::getPersistenceName
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
Definition: ProductBoundedField.cc:163
lsst::afw::table::CatalogT::reserve
void reserve(size_type n)
Increase the capacity of the catalog to the given size.
Definition: Catalog.h:428
std::fill
T fill(T... args)
schema
table::Schema schema
Definition: ProductBoundedField.cc:109
std::vector::push_back
T push_back(T... args)
lsst::afw::table::io::OutputArchiveHandle::makeCatalog
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
Definition: OutputArchive.cc:207
z
double z
Definition: Match.cc:44
x
double x
Definition: ChebyshevBoundedField.cc:277
field
table::Key< int > field
Definition: ApCorrMap.cc:77
lsst::pex::exceptions::LogicError
Persistable.cc
b
table::Key< int > b
Definition: TransmissionCurve.cc:467
lsst
A base class for image defects.
LSST_EXCEPT
#define LSST_EXCEPT(type,...)
exceptions.h
lsst::afw::math::BoundedField::getBBox
lsst::geom::Box2I getBBox() const
Return the bounding box that defines the region where the field is valid.
Definition: BoundedField.h:112
std::ostringstream
STL class.
lsst::afw::math::ProductBoundedField::isPersistable
bool isPersistable() const noexcept override
ProductBoundedField is persistable if and only if all of its factors are.
Definition: ProductBoundedField.cc:158
os
std::ostream * os
Definition: Schema.cc:746
lsst::pex::exceptions::InvalidParameterError
a
table::Key< int > a
Definition: TransmissionCurve.cc:466
Point< double, 2 >
ChebyshevBoundedField.h
lsst::geom::Box2I
lsst::afw.display.ds9.scale
def scale(algorithm, min, max=None, frame=None)
Definition: ds9.py:109
lsst::afw::math::ProductBoundedField::operator*
std::shared_ptr< BoundedField > operator*(double const scale) const override
Return a scaled BoundedField.
Definition: ProductBoundedField.cc:181
InputArchive.h
lsst::afw::table::io::OutputArchiveHandle::put
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...
Definition: OutputArchive.cc:216
lsst::afw::table::CatalogT::addNew
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
lsst::afw::math::ProductBoundedField::~ProductBoundedField
~ProductBoundedField() override
lsst::afw::math::ProductBoundedField::getPythonModule
std::string getPythonModule() const override
Return the fully-qualified Python module that should be imported to guarantee that its factory is reg...
Definition: ProductBoundedField.cc:167
id
table::Key< int > id
Definition: ProductBoundedField.cc:110
lsst::afw::math::ProductBoundedField::write
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
Definition: ProductBoundedField.cc:169
lsst::afw::table::CatalogT< BaseRecord >
iter
def iter(self)
ProductBoundedField.h
OutputArchive.h
lsst::afw::math::ProductBoundedField::operator==
bool operator==(BoundedField const &rhs) const override
BoundedFields (of the same sublcass) are equal if their bounding boxes and parameters are equal.
Definition: ProductBoundedField.cc:199
bbox
AmpInfoBoxKey bbox
Definition: Amplifier.cc:117