lsst.meas.algorithms  15.0-12-g7952b551+1
CoaddBoundedField.cc
Go to the documentation of this file.
1 // -*- LSST-C++ -*-
2 /*
3  * LSST Data Management System
4  * Copyright 2008-2014, 2010 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 
25 #include "lsst/geom/Box.h"
31 
32 namespace lsst {
33 namespace meas {
34 namespace algorithms {
35 
37  ElementVector const& elements)
38  : afw::math::BoundedField(bbox),
39  _throwOnMissing(true),
40  _default(0.0), // unused
41  _coaddWcs(coaddWcs),
42  _elements(elements) {}
43 
45  ElementVector const& elements, double default_)
46  : afw::math::BoundedField(bbox),
47  _throwOnMissing(false),
48  _default(default_),
49  _coaddWcs(coaddWcs),
50  _elements(elements) {}
51 
52 double CoaddBoundedField::evaluate(geom::Point2D const& position) const {
53  auto coord = _coaddWcs->pixelToSky(position);
54  double sum = 0.0;
55  double wSum = 0.0;
56  for (ElementVector::const_iterator i = _elements.begin(); i != _elements.end(); ++i) {
57  geom::Point2D transformedPosition = i->wcs->skyToPixel(coord);
58  bool inValidArea = i->validPolygon ? i->validPolygon->contains(transformedPosition) : true;
59  if (geom::Box2D(i->field->getBBox()).contains(transformedPosition) && inValidArea) {
60  sum += i->weight * i->field->evaluate(transformedPosition);
61  wSum += i->weight;
62  }
63  }
64  if (wSum == 0.0) {
65  if (_throwOnMissing) {
67  (boost::format("No constituent fields to evaluate at point %f, %f") %
68  position.getX() % position.getY())
69  .str());
70  } else {
71  return _default;
72  }
73  }
74  return sum / wSum;
75 }
76 
77 // ---------- Persistence -----------------------------------------------------------------------------------
78 
79 // For persistence of CoaddBoundedField, we have two catalogs: the first has just one record, and contains
80 // the archive ID of the coadd WCS and the parameters that control missing data. The other catalog
81 // has one record for each element, with fields corresponding to the data members of the Element struct.
82 
83 namespace {
84 
85 // Singleton class that manages the first persistence catalog's schema and keys
86 class CoaddBoundedFieldPersistenceKeys1 {
87 public:
88  afw::table::Schema schema;
89  afw::table::PointKey<int> bboxMin;
90  afw::table::PointKey<int> bboxMax;
91  afw::table::Key<int> coaddWcs;
92  afw::table::Key<afw::table::Flag> throwOnMissing;
93  afw::table::Key<double> default_;
94 
95  static CoaddBoundedFieldPersistenceKeys1 const& get() {
96  static CoaddBoundedFieldPersistenceKeys1 const instance;
97  return instance;
98  }
99 
100  // No copying
101  CoaddBoundedFieldPersistenceKeys1(const CoaddBoundedFieldPersistenceKeys1&) = delete;
102  CoaddBoundedFieldPersistenceKeys1& operator=(const CoaddBoundedFieldPersistenceKeys1&) = delete;
103 
104  // No moving
105  CoaddBoundedFieldPersistenceKeys1(CoaddBoundedFieldPersistenceKeys1&&) = delete;
106  CoaddBoundedFieldPersistenceKeys1& operator=(CoaddBoundedFieldPersistenceKeys1&&) = delete;
107 
108 private:
109  CoaddBoundedFieldPersistenceKeys1()
110  : schema(),
112  "lower-left corner of bounding box", "pixel")),
114  "upper-right corner of bounding box", "pixel")),
115  coaddWcs(schema.addField<int>("coaddWcs", "archive ID of the coadd's WCS")),
116  throwOnMissing(schema.addField<afw::table::Flag>(
117  "throwOnMissing", "whether to throw an exception on missing data")),
118  default_(schema.addField<double>("default",
119  "default value to use when throwOnMissing is False")) {
120  schema.getCitizen().markPersistent();
121  }
122 };
123 
124 // Singleton class that manages the second persistence catalog's schema and keys
125 class CoaddBoundedFieldPersistenceKeys2 {
126 public:
127  afw::table::Schema schema;
128  afw::table::Key<int> field;
129  afw::table::Key<int> wcs;
130  afw::table::Key<int> validPolygon;
131  afw::table::Key<double> weight;
132 
133  static CoaddBoundedFieldPersistenceKeys2 const& get() {
134  static CoaddBoundedFieldPersistenceKeys2 const instance;
135  return instance;
136  }
137 
138  // No copying
139  CoaddBoundedFieldPersistenceKeys2(const CoaddBoundedFieldPersistenceKeys2&) = delete;
140  CoaddBoundedFieldPersistenceKeys2& operator=(const CoaddBoundedFieldPersistenceKeys2&) = delete;
141 
142  // No moving
143  CoaddBoundedFieldPersistenceKeys2(CoaddBoundedFieldPersistenceKeys2&&) = delete;
144  CoaddBoundedFieldPersistenceKeys2& operator=(CoaddBoundedFieldPersistenceKeys2&&) = delete;
145 
146 private:
147  CoaddBoundedFieldPersistenceKeys2()
148  : schema(),
149  field(schema.addField<int>("field", "archive ID of the BoundedField to be coadded")),
150  wcs(schema.addField<int>("wcs", "archive ID of the Wcs associated with this element")),
151  validPolygon(schema.addField<int>("validPolygon",
152  "archive ID of the Polygon associated with this element")),
153  weight(schema.addField<double>("weight", "weight value for this element")) {
154  schema.getCitizen().markPersistent();
155  }
156 };
157 
158 } // namespace
159 
161 public:
163  read(InputArchive const& archive, CatalogVector const& catalogs) const {
164  CoaddBoundedFieldPersistenceKeys1 const& keys1 = CoaddBoundedFieldPersistenceKeys1::get();
165  CoaddBoundedFieldPersistenceKeys2 const& keys2 = CoaddBoundedFieldPersistenceKeys2::get();
166  LSST_ARCHIVE_ASSERT(catalogs.size() == 2u);
167  LSST_ARCHIVE_ASSERT(catalogs.front().getSchema() == keys1.schema);
168  LSST_ARCHIVE_ASSERT(catalogs.back().getSchema() == keys2.schema);
169  afw::table::BaseRecord const& record1 = catalogs.front().front();
170  ElementVector elements;
171  elements.reserve(catalogs.back().size());
172  for (afw::table::BaseCatalog::const_iterator i = catalogs.back().begin(); i != catalogs.back().end();
173  ++i) {
174  elements.push_back(Element(archive.get<afw::math::BoundedField>(i->get(keys2.field)),
175  archive.get<afw::geom::SkyWcs>(i->get(keys2.wcs)),
176  archive.get<afw::geom::polygon::Polygon>(i->get(keys2.validPolygon)),
177  i->get(keys2.weight)));
178  }
179  return std::make_shared<CoaddBoundedField>(
180  geom::Box2I(record1.get(keys1.bboxMin), record1.get(keys1.bboxMax)),
181  archive.get<afw::geom::SkyWcs>(record1.get(keys1.coaddWcs)), elements,
182  record1.get(keys1.default_));
183  }
184 
185  Factory(std::string const& name) : afw::table::io::PersistableFactory(name) {}
186 };
187 
188 namespace {
189 
190 std::string getCoaddBoundedFieldPersistenceName() { return "CoaddBoundedField"; }
191 
192 CoaddBoundedField::Factory registration(getCoaddBoundedFieldPersistenceName());
193 
194 } // namespace
195 
196 std::string CoaddBoundedField::getPersistenceName() const { return getCoaddBoundedFieldPersistenceName(); }
197 
198 std::string CoaddBoundedField::getPythonModule() const { return "lsst.meas.algorithms"; }
199 
201  CoaddBoundedFieldPersistenceKeys1 const& keys1 = CoaddBoundedFieldPersistenceKeys1::get();
202  CoaddBoundedFieldPersistenceKeys2 const& keys2 = CoaddBoundedFieldPersistenceKeys2::get();
203  afw::table::BaseCatalog cat1 = handle.makeCatalog(keys1.schema);
204  PTR(afw::table::BaseRecord) record1 = cat1.addNew();
205  record1->set(keys1.bboxMin, getBBox().getMin());
206  record1->set(keys1.bboxMax, getBBox().getMax());
207  record1->set(keys1.coaddWcs, handle.put(_coaddWcs));
208  record1->set(keys1.default_, _default);
209  handle.saveCatalog(cat1);
210  afw::table::BaseCatalog cat2 = handle.makeCatalog(keys2.schema);
211  for (ElementVector::const_iterator i = _elements.begin(); i != _elements.end(); ++i) {
212  PTR(afw::table::BaseRecord) record2 = cat2.addNew();
213  record2->set(keys2.field, handle.put(i->field));
214  record2->set(keys2.wcs, handle.put(i->wcs));
215  record2->set(keys2.validPolygon, handle.put(i->validPolygon));
216  record2->set(keys2.weight, i->weight);
217  }
218  handle.saveCatalog(cat2);
219 }
220 
222  throw LSST_EXCEPT(pex::exceptions::NotFoundError, "Scaling of CoaddBoundedField is not implemented");
223 }
224 
226  auto rhsCasted = dynamic_cast<CoaddBoundedField const*>(&rhs);
227  if (!rhsCasted) return false;
228 
229  return (getBBox() == rhsCasted->getBBox()) && (_default == rhsCasted->_default) &&
230  ((*_coaddWcs) == (*rhsCasted->_coaddWcs)) && (_elements == rhsCasted->_elements);
231 }
232 
233 } // namespace algorithms
234 } // namespace meas
235 } // namespace lsst
virtual std::string getPersistenceName() const
virtual std::string getPythonModule() const
geom::Box2D bbox
#define LSST_ARCHIVE_ASSERT(EXPR)
afw::table::Key< int > wcs
static PointKey addFields(Schema &schema, std::string const &name, std::string const &doc, std::string const &unit)
afw::table::PointKey< int > bboxMax
afw::table::Key< int > validPolygon
#define PTR(...)
T end(T... args)
afw::table::PointKey< int > bboxMin
afw::table::Key< double > default_
virtual void write(OutputArchiveHandle &handle) const
STL class.
BoundedField & operator=(BoundedField const &)=delete
T push_back(T... args)
BoundedField(BoundedField const &)=default
afw::table::Key< afw::table::Flag > throwOnMissing
afw::table::Key< int > field
virtual bool operator==(BoundedField const &rhs) const
BoundedFields (of the same sublcass) are equal if their bounding boxes and parameters are equal...
afw::table::Schema schema
lsst::geom::Box2I getBBox() const
afw::table::Key< int > coaddWcs
virtual double evaluate(geom::Point2D const &position) const
CatalogIterator< typename Internal::const_iterator > const_iterator
#define LSST_EXCEPT(type,...)
T begin(T... args)
virtual boost::shared_ptr< afw::math::BoundedField > operator*(double const scale) const
io::OutputArchiveHandle OutputArchiveHandle
afw::table::Key< double > weight
CoaddBoundedField(geom::Box2I const &bbox, boost::shared_ptr< afw::geom::SkyWcs const > coaddWcs, ElementVector const &elements)
T reserve(T... args)
std::shared_ptr< BaseRecord > addNew()