LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
LSST Data Management Base Package
MaskDict.cc
Go to the documentation of this file.
1/*
2 * Developed for the LSST Data Management System.
3 * This product includes software developed by the LSST Project
4 * (https://www.lsst.org).
5 * See the COPYRIGHT file at the top-level directory of this distribution
6 * for details of code ownership.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <mutex>
23#include <set>
24
25#include "boost/functional/hash.hpp"
27
28namespace lsst { namespace afw { namespace image { namespace detail {
29
30// A thread-safe singleton that manages MaskDict's global state.
32public:
33
34 static GlobalState & get() {
35 static GlobalState instance;
36 return instance;
37 }
38
41 if (!mpd.empty()) {
43 _allMaskDicts.insert(dict);
44 return dict;
45 }
46 return _defaultMaskDict;
47 }
48
52 _allMaskDicts.insert(result);
53 return result;
54 }
55
57 return _defaultMaskDict;
58 }
59
61 _defaultMaskDict = std::move(dict);
62 }
63
66 _defaultMaskDict = copy(*_defaultMaskDict);
67 return _defaultMaskDict;
68 }
69
70 template <typename Functor>
71 void forEachMaskDict(Functor functor) {
73 _prune(); // guarantees dereference below is safe
74 for (auto const & ptr : _allMaskDicts) {
75 functor(*ptr.lock());
76 }
77 }
78
79private:
80
81 GlobalState() : _defaultMaskDict(new MaskDict()) {
82 _allMaskDicts.insert(_defaultMaskDict);
83 _defaultMaskDict->_addInitialMaskPlanes();
84 }
85
86 GlobalState(GlobalState const &) = delete;
87 GlobalState(GlobalState &&) = delete;
88
89 GlobalState & operator=(GlobalState const &) = delete;
90 GlobalState & operator=(GlobalState &&) = delete;
91
92 ~GlobalState() = default;
93
94 // Prune expired weak_ptrs from _allMaskDicts. Not thread safe; should
95 // only be called by routines that have already locked the mutex.
96 void _prune() {
97 for (auto iter = _allMaskDicts.begin(); iter != _allMaskDicts.end(); ) {
98 if (iter->expired()) {
99 iter = _allMaskDicts.erase(iter);
100 } else {
101 ++iter;
102 }
103 }
104 }
105
106 std::recursive_mutex _mutex; // guards _allMaskDicts and synchronizes updates to it and _defaultMaskDict
108 std::shared_ptr<MaskDict> _defaultMaskDict;
109};
110
113}
114
116 return GlobalState::get().getDefault();
117}
118
121}
122
125}
126
129 [&name, bitId](MaskDict & dict) {
130 auto const found = std::find_if(
131 dict.begin(), dict.end(),
132 [bitId](auto const & item) { return item.second == bitId; }
133 );
134 if (found == dict.end()) {
135 // is name already in use?
136 if (dict.find(name) == dict.end()) {
137 dict.add(name, bitId);
138 }
139 }
140 }
141 );
142}
143
144MaskDict::~MaskDict() noexcept = default;
145
146std::shared_ptr<MaskDict> MaskDict::clone() const {
147 return GlobalState::get().copy(*this);
148}
149
151 if (empty()) {
152 return 0;
153 }
154
155 auto const maxIter = std::max_element(
156 begin(), end(),
157 [](auto const & a, auto const & b) { return a.second < b.second; }
158 );
159 assert(maxIter != end());
160 int id = maxIter->second + 1; // The maskPlane to use if there are no gaps
161
162 for (int i = 0; i < id; ++i) {
163 // is i already used in this Mask?
164 auto const sameIter = std::find_if(
165 begin(), end(),
166 [i](auto const & item) { return item.second == i; }
167 );
168 if (sameIter == end()) { // Not used; so we'll use it
169 return i;
170 }
171 }
172
173 return id;
174}
175
177 auto iter = find(name);
178 return (iter == end()) ? -1 : iter->second;
179}
180
181void MaskDict::print() const {
182 for (auto const & item : *this) {
183 std::cout << "Plane " << item.second << " -> " << item.first << std::endl;
184 }
185}
186
187bool MaskDict::operator==(MaskDict const& rhs) const {
188 return this == &rhs || (_hash == rhs._hash && _dict == rhs._dict);
189}
190
191void MaskDict::add(std::string const & name, int bitId) {
192 _dict[name] = bitId;
193 _hash = boost::hash<MaskPlaneDict>()(_dict);
194}
195
197 _dict.erase(name);
198 _hash = boost::hash<MaskPlaneDict>()(_dict);
199}
200
202 _dict.clear();
203 _hash = 0x0;
204}
205
206void MaskDict::_addInitialMaskPlanes() {
207 int i = -1;
208 _dict["BAD"] = ++i;
209 _dict["SAT"] = ++i;
210 _dict["INTRP"] = ++i;
211 _dict["CR"] = ++i;
212 _dict["EDGE"] = ++i;
213 _dict["DETECTED"] = ++i;
214 _dict["DETECTED_NEGATIVE"] = ++i;
215 _dict["SUSPECT"] = ++i;
216 _dict["NO_DATA"] = ++i;
217 _hash = boost::hash<MaskPlaneDict>()(_dict);
218}
219
220MaskDict::MaskDict() : _dict(), _hash(0x0) {}
221
222MaskDict::MaskDict(MaskPlaneDict const & dict) : _dict(dict), _hash(boost::hash<MaskPlaneDict>()(_dict)) {}
223
224}}}} // lsst::afw::image::detail
py::object result
Definition: _schema.cc:429
table::Key< std::string > name
Definition: Amplifier.cc:116
table::Key< int > id
Definition: Detector.cc:162
uint64_t * ptr
Definition: RangeSet.cc:88
table::Key< int > b
table::Key< int > a
std::shared_ptr< MaskDict > getDefault() const noexcept
Definition: MaskDict.cc:56
std::shared_ptr< MaskDict > copyOrGetDefault(MaskPlaneDict const &mpd)
Definition: MaskDict.cc:39
std::shared_ptr< MaskDict > copy(MaskDict const &dict)
Definition: MaskDict.cc:49
void setDefault(std::shared_ptr< MaskDict > dict)
Definition: MaskDict.cc:60
std::shared_ptr< MaskDict > detachDefault()
Definition: MaskDict.cc:64
int getMaskPlane(std::string const &name) const
Definition: MaskDict.cc:176
const_iterator begin() const noexcept
Definition: MaskDict.h:131
static void addAllMasksPlane(std::string const &name, int bitId)
Definition: MaskDict.cc:127
static std::shared_ptr< MaskDict > detachDefault()
Definition: MaskDict.cc:123
const_iterator end() const noexcept
Definition: MaskDict.h:132
static std::shared_ptr< MaskDict > getDefault()
Definition: MaskDict.cc:115
static void setDefault(std::shared_ptr< MaskDict > dict)
Definition: MaskDict.cc:119
bool operator==(MaskDict const &rhs) const
Definition: MaskDict.cc:187
const_iterator find(std::string const &name) const
Definition: MaskDict.h:135
void add(std::string const &name, int bitId)
Definition: MaskDict.cc:191
static std::shared_ptr< MaskDict > copyOrGetDefault(MaskPlaneDict const &dict)
Definition: MaskDict.cc:111
bool empty() const noexcept
Definition: MaskDict.h:141
void erase(std::string const &name)
Definition: MaskDict.cc:196
T clear(T... args)
T empty(T... args)
T endl(T... args)
T erase(T... args)
T find_if(T... args)
T max_element(T... args)
T move(T... args)
Definition: Polygon.cc:24
std::map< std::string, int > MaskPlaneDict
Definition: Mask.h:58
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
A base class for image defects.
STL namespace.