lsst.afw g8f2ba02de7+e31e6a4341
Filter.cc
Go to the documentation of this file.
1// -*- lsst-c++ -*-
2
3/*
4 * LSST Data Management System
5 * Copyright 2008, 2009, 2010 LSST Corporation.
6 *
7 * This product includes software developed by the
8 * LSST Project (http://www.lsst.org/).
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the LSST License Statement and
21 * the GNU General Public License along with this program. If not,
22 * see <http://www.lsstcorp.org/LegalNotices/>.
23 */
24
25//
26//##====---------------- ----------------====##/
27//
28// Implements looking up a filter identifier by name.
29//
30//##====---------------- ----------------====##/
31#include <cmath>
32#include "boost/format.hpp"
33#include "boost/algorithm/string/trim.hpp"
34#include "lsst/pex/exceptions.h"
36
41
43
44namespace lsst {
45namespace afw {
46namespace image {
47
48FilterProperty::PropertyMap* FilterProperty::_propertyMap = nullptr;
49
51 : _name(name), _lambdaEff(NAN), _lambdaMin(NAN), _lambdaMax(NAN) {
52 if (prop.exists("lambdaEff")) {
53 _lambdaEff = prop.getAsDouble("lambdaEff");
54 }
55 if (prop.exists("lambdaMin")) {
56 _lambdaMin = prop.getAsDouble("lambdaMin");
57 }
58 if (prop.exists("lambdaMax")) {
59 _lambdaMax = prop.getAsDouble("lambdaMax");
60 }
61 _insert(force);
62}
63
64void FilterProperty::_insert(bool force) {
65 if (!_propertyMap) {
66 _initRegistry();
67 }
68
69 PropertyMap::iterator keyVal = _propertyMap->find(getName());
70
71 if (keyVal != _propertyMap->end()) {
72 if (keyVal->second == *this) {
73 return; // OK, a redefinition with identical values
74 }
75
76 if (!force) {
77 throw LSST_EXCEPT(pexEx::RuntimeError, "Filter " + getName() + " is already defined");
78 }
79 _propertyMap->erase(keyVal);
80 }
81
82 _propertyMap->insert(std::make_pair(getName(), *this));
83}
84
85bool FilterProperty::operator==(FilterProperty const& rhs) const noexcept {
86 return (_lambdaEff == rhs._lambdaEff);
87}
88
89std::size_t FilterProperty::hash_value() const noexcept { return std::hash<double>()(_lambdaEff); };
90
91void FilterProperty::_initRegistry() {
92 if (_propertyMap) {
93 delete _propertyMap;
94 }
95
96 _propertyMap = new PropertyMap;
97}
98
99FilterProperty const& FilterProperty::lookup(std::string const& name) {
100 if (!_propertyMap) {
101 _initRegistry();
102 }
103
104 PropertyMap::iterator keyVal = _propertyMap->find(name);
105
106 if (keyVal == _propertyMap->end()) {
107 throw LSST_EXCEPT(pexEx::NotFoundError, "Unable to find filter " + name);
108 }
109
110 return keyVal->second;
111}
112
113namespace {
114std::string const unknownFilter = "_unknown_";
115}
116
117int const Filter::AUTO = -1;
118int const Filter::UNKNOWN = -1;
119
120Filter::Filter(std::shared_ptr<lsst::daf::base::PropertySet const> metadata, bool const force) {
121 std::string const key = "FILTER";
122 if (metadata->exists(key)) {
123 std::string filterName = boost::algorithm::trim_right_copy(metadata->getAsString(key));
124 _id = _lookup(filterName, force);
125 _name = filterName;
126 }
127}
128
129namespace detail {
131 int nstripped = 0;
132
133 std::string key = "FILTER";
134 if (metadata->exists(key)) {
135 metadata->remove(key);
136 nstripped++;
137 }
138
139 return nstripped;
140}
141} // namespace detail
142
143// N.b. we cannot declare a std::vector<std::string const&> as there's no way to push the references
144std::vector<std::string> Filter::getAliases() const {
146
147 std::string const& canonicalName = getCanonicalName();
148 for (auto const &ptr : *_aliasMap) {
149 if (ptr.second == canonicalName) {
150 aliases.push_back(ptr.first);
151 }
152 }
153
154 return aliases;
155}
156
157std::vector<std::string> Filter::getNames() {
158 if (!_nameMap) {
159 _initRegistry();
160 }
161
163
164 for (auto const &ptr : *_nameMap) {
165 if (ptr.first != unknownFilter) {
166 names.push_back(ptr.first);
167 }
168 }
169 std::sort(names.begin(), names.end());
170
171 return names;
172}
173
174std::shared_ptr<typehandling::Storable> Filter::cloneStorable() const {
175 return std::make_unique<Filter>(*this);
176}
177
178bool Filter::equals(typehandling::Storable const& other) const noexcept {
179 return singleClassEquals(*this, other);
180}
181
182namespace {
183
184struct PersistenceHelper {
185 table::Schema schema;
186 table::Key<std::string> name;
187
188 static PersistenceHelper const& get() {
189 static PersistenceHelper const instance;
190 return instance;
191 }
192
193private:
194 PersistenceHelper() : schema(), name(schema.addField<std::string>("name", "name of the filter")) {}
195};
196
197class FilterFactory : public table::io::PersistableFactory {
198public:
199 std::shared_ptr<table::io::Persistable> read(InputArchive const& archive,
200 CatalogVector const& catalogs) const override {
201 PersistenceHelper const& keys = PersistenceHelper::get();
202 LSST_ARCHIVE_ASSERT(catalogs.size() == 1u);
203 LSST_ARCHIVE_ASSERT(catalogs.front().getSchema() == keys.schema);
204 return std::make_shared<Filter>(catalogs.front().begin()->get(keys.name), true);
205 }
206
207 FilterFactory(std::string const& name) : afw::table::io::PersistableFactory(name) {}
208};
209
210std::string _getPersistenceName() { return "Filter"; }
211
212FilterFactory registration(_getPersistenceName());
213
214} // namespace
215
216bool Filter::isPersistable() const noexcept { return true; }
217
218std::string Filter::getPersistenceName() const { return _getPersistenceName(); }
219
220std::string Filter::getPythonModule() const { return "lsst.afw.image"; };
221
222void Filter::write(OutputArchiveHandle& handle) const {
223 PersistenceHelper const& keys = PersistenceHelper::get();
224 table::BaseCatalog catalog = handle.makeCatalog(keys.schema);
225 std::shared_ptr<table::BaseRecord> record = catalog.addNew();
226 record->set(keys.name, getName());
227 handle.saveCatalog(catalog);
228}
229
230bool Filter::operator==(Filter const& rhs) const noexcept { return _id != UNKNOWN && _id == rhs._id; }
231
232std::size_t Filter::hash_value() const noexcept { return std::hash<int>()(_id); }
233
234void Filter::_initRegistry() {
235 _id0 = UNKNOWN;
236 delete _aliasMap;
237 delete _nameMap;
238 delete _idMap;
239
240 _aliasMap = new AliasMap;
241 _nameMap = new NameMap;
242 _idMap = new IdMap;
243
244 define(FilterProperty(unknownFilter, daf::base::PropertySet(), true));
245}
246
247int Filter::_id0 = Filter::UNKNOWN;
248
249// dynamically allocated as that avoids an intel bug with static variables in dynamic libraries
250Filter::AliasMap* Filter::_aliasMap = nullptr;
251Filter::NameMap* Filter::_nameMap = nullptr;
252Filter::IdMap* Filter::_idMap = nullptr;
253
254int Filter::define(FilterProperty const& fp, int id, bool force) {
255 if (!_nameMap) {
256 _initRegistry();
257 }
258
259 std::string const& name = fp.getName();
260 NameMap::iterator keyVal = _nameMap->find(name);
261
262 if (keyVal != _nameMap->end()) {
263 int oid = keyVal->second;
264
265 if (id == oid || id == AUTO) {
266 return oid; // OK, same value as before
267 }
268
269 if (!force) {
270 throw LSST_EXCEPT(pexEx::RuntimeError, "Filter " + name + " is already defined");
271 }
272 _nameMap->erase(keyVal);
273 _idMap->erase(oid);
274 }
275
276 if (id == AUTO) {
277 id = _id0;
278 ++_id0;
279 }
280
281 _nameMap->insert(std::make_pair(name, id));
282 _idMap->insert(std::make_pair(id, name));
283
284 return id;
285}
286
287int Filter::defineAlias(std::string const& oldName, std::string const& newName, bool force) {
288 if (!_nameMap) {
289 _initRegistry();
290 }
291
292 // Lookup oldName
293 NameMap::iterator keyVal = _nameMap->find(oldName);
294 if (keyVal == _nameMap->end()) {
295 throw LSST_EXCEPT(pexEx::NotFoundError, "Unable to find filter " + oldName);
296 }
297 int const id = keyVal->second;
298
299 // Lookup oldName in aliasMap
300 AliasMap::iterator aliasKeyVal = _aliasMap->find(newName);
301 if (aliasKeyVal != _aliasMap->end()) {
302 if (aliasKeyVal->second == oldName) {
303 return id; // OK, same value as before
304 }
305
306 if (!force) {
307 throw LSST_EXCEPT(pexEx::NotFoundError, "Filter " + newName + " is already defined");
308 }
309 _aliasMap->erase(aliasKeyVal);
310 }
311
312 _aliasMap->insert(std::make_pair(newName, oldName));
313
314 return id;
315}
316
317int Filter::_lookup(std::string const& name, bool const force) {
318 if (!_nameMap) {
319 _initRegistry();
320 }
321
322 NameMap::iterator keyVal = _nameMap->find(name);
323
324 if (keyVal == _nameMap->end()) {
325 AliasMap::iterator aliasKeyVal = _aliasMap->find(name);
326 if (aliasKeyVal != _aliasMap->end()) {
327 return _lookup(aliasKeyVal->second);
328 }
329
330 if (force) {
331 return UNKNOWN;
332 } else {
333 throw LSST_EXCEPT(pexEx::NotFoundError, "Unable to find filter " + name);
334 }
335 }
336
337 return keyVal->second;
338}
339
340std::string const& Filter::_lookup(int id) {
341 if (!_idMap) {
342 _initRegistry();
343 }
344
345 IdMap::iterator keyVal = _idMap->find(id);
346
347 if (keyVal == _idMap->end()) {
348 throw LSST_EXCEPT(pexEx::NotFoundError, (boost::format("Unable to find filter %d") % id).str());
349 }
350
351 return keyVal->second;
352}
353FilterProperty const& Filter::getFilterProperty() const {
354 //
355 // Map name to its ID and back to resolve aliases
356 //
357 int const id = _lookup(_name, true);
358 std::string const& name = (id == UNKNOWN) ? _name : _lookup(id);
359
360 return FilterProperty::lookup(name);
361}
362} // namespace image
363} // namespace afw
364} // namespace lsst
table::Key< int > id
Definition: Detector.cc:162
#define LSST_EXCEPT(type,...)
table::Key< std::string > name
Definition: Filter.cc:186
table::Schema schema
Definition: Filter.cc:185
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
Definition: Persistable.h:48
T begin(T... args)
bool exists(std::string const &name) const
double getAsDouble(std::string const &name) const
T end(T... args)
T make_pair(T... args)
def keys(self)
int stripFilterKeywords(std::shared_ptr< lsst::daf::base::PropertySet > metadata)
Remove Filter-related keywords from the metadata.
Definition: Filter.cc:130
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
bool operator==(FilterProperty const &rhs) const noexcept
Return true iff two FilterProperties are identical.
std::string getPythonModule() const override
std::string getPersistenceName() const override
@ UNKNOWN
Rotation angle is unknown.
void write(OutputArchiveHandle &handle) const override
std::size_t hash_value() const noexcept
Return a hash of this object.
std::string const & getName() const noexcept
Return a filter's name.
Definition: Filter.h:78
FilterProperty(FilterProperty const &)=default
CatalogT< BaseRecord > BaseCatalog
Definition: fwd.h:72
A base class for image defects.
STL namespace.
T push_back(T... args)
T sort(T... args)
std::shared_ptr< table::io::Persistable > read(table::io::InputArchive const &archive, table::io::CatalogVector const &catalogs) const override
Definition: warpExposure.cc:0