LSSTApplications  20.0.0
LSSTDataManagementBasePackage
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 
28 namespace lsst { namespace afw { namespace image { namespace detail {
29 
30 // A thread-safe singleton that manages MaskDict's global state.
31 class MaskDict::GlobalState final {
32 public:
33 
34  static GlobalState & get() {
35  static GlobalState instance;
36  return instance;
37  }
38 
41  if (!mpd.empty()) {
42  std::shared_ptr<MaskDict> dict(new MaskDict(mpd));
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 
79 private:
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 
112  return GlobalState::get().copyOrGetDefault(mpd);
113 }
114 
116  return GlobalState::get().getDefault();
117 }
118 
121 }
122 
124  return GlobalState::get().detachDefault();
125 }
126 
127 void MaskDict::addAllMasksPlane(std::string const & name, int bitId) {
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 
144 MaskDict::~MaskDict() noexcept = default;
145 
146 std::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 
181 void MaskDict::print() const {
182  for (auto const & item : *this) {
183  std::cout << "Plane " << item.second << " -> " << item.first << std::endl;
184  }
185 }
186 
187 bool MaskDict::operator==(MaskDict const& rhs) const {
188  return this == &rhs || (_hash == rhs._hash && _dict == rhs._dict);
189 }
190 
191 void 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 
206 void 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 
220 MaskDict::MaskDict() : _dict(), _hash(0x0) {}
221 
222 MaskDict::MaskDict(MaskPlaneDict const & dict) : _dict(dict), _hash(boost::hash<MaskPlaneDict>()(_dict)) {}
223 
224 }}}} // lsst::afw::image::detail
lsst::afw::image
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
Definition: imageAlgorithm.dox:1
std::max_element
T max_element(T... args)
lsst::afw::image::detail::MaskDict::GlobalState::copy
std::shared_ptr< MaskDict > copy(MaskDict const &dict)
Definition: MaskDict.cc:49
std::string
STL class.
std::shared_ptr
STL class.
lsst::afw::image::detail::MaskPlaneDict
std::map< std::string, int > MaskPlaneDict
Definition: Mask.h:58
lsst::afw::image::detail::MaskDict::empty
bool empty() const noexcept
Definition: MaskDict.h:141
std::move
T move(T... args)
lsst::afw::image::detail::MaskDict::GlobalState::getDefault
std::shared_ptr< MaskDict > getDefault() const noexcept
Definition: MaskDict.cc:56
lsst::afw::image::detail::MaskDict
Definition: MaskDict.h:61
lsst::afw::image::detail::MaskDict::GlobalState::forEachMaskDict
void forEachMaskDict(Functor functor)
Definition: MaskDict.cc:71
lsst::afw::image::detail::MaskDict::operator==
bool operator==(MaskDict const &rhs) const
Definition: MaskDict.cc:187
lsst::afw::image::detail::MaskDict::end
const_iterator end() const noexcept
Definition: MaskDict.h:132
std::find_if
T find_if(T... args)
lsst::afw::image::detail::MaskDict::getMaskPlane
int getMaskPlane(std::string const &name) const
Definition: MaskDict.cc:176
lsst::afw::image::detail::MaskDict::GlobalState::get
static GlobalState & get()
Definition: MaskDict.cc:34
lsst::afw
Definition: imageAlgorithm.dox:1
std::recursive_mutex
STL class.
std::owner_less
std::lock_guard
STL class.
boost
Definition: Polygon.cc:25
lsst::afw::image::detail::MaskDict::addAllMasksPlane
static void addAllMasksPlane(std::string const &name, int bitId)
Definition: MaskDict.cc:127
lsst::afw::geom.transform.transformContinued.name
string name
Definition: transformContinued.py:32
lsst::afw::image::detail::MaskDict::~MaskDict
~MaskDict() noexcept
std::map::clear
T clear(T... args)
lsst::afw::image::detail::MaskDict::getUnusedPlane
int getUnusedPlane() const
Definition: MaskDict.cc:150
lsst::afw::image::detail::MaskDict::setDefault
static void setDefault(std::shared_ptr< MaskDict > dict)
Definition: MaskDict.cc:119
std::cout
lsst::afw::image::detail::MaskDict::find
const_iterator find(std::string const &name) const
Definition: MaskDict.h:135
id
table::Key< int > id
Definition: Detector.cc:162
lsst::afw::image::detail::MaskDict::detachDefault
static std::shared_ptr< MaskDict > detachDefault()
Definition: MaskDict.cc:123
lsst::afw::image::detail::MaskDict::clear
void clear()
Definition: MaskDict.cc:201
std::map::erase
T erase(T... args)
ptr
uint64_t * ptr
Definition: RangeSet.cc:88
lsst::afw::image::detail::MaskDict::erase
void erase(std::string const &name)
Definition: MaskDict.cc:196
lsst::afw::image::detail::MaskDict::add
void add(std::string const &name, int bitId)
Definition: MaskDict.cc:191
std::map< std::string, int >
result
py::object result
Definition: _schema.cc:429
b
table::Key< int > b
Definition: TransmissionCurve.cc:467
lsst
A base class for image defects.
Definition: imageAlgorithm.dox:1
lsst::afw::image::detail::MaskDict::getDefault
static std::shared_ptr< MaskDict > getDefault()
Definition: MaskDict.cc:115
std::endl
T endl(T... args)
a
table::Key< int > a
Definition: TransmissionCurve.cc:466
std
STL namespace.
lsst::afw::image::detail::MaskDict::print
void print() const
Definition: MaskDict.cc:181
lsst::afw::image::detail::MaskDict::GlobalState::setDefault
void setDefault(std::shared_ptr< MaskDict > dict)
Definition: MaskDict.cc:60
MaskDict.h
std::map::empty
T empty(T... args)
lsst::afw::image::detail::MaskDict::begin
const_iterator begin() const noexcept
Definition: MaskDict.h:131
lsst::afw::image::detail::MaskDict::GlobalState
Definition: MaskDict.cc:31
lsst::afw::image.slicing.clone
clone
Definition: slicing.py:257
astshim.fitsChanContinued.iter
def iter(self)
Definition: fitsChanContinued.py:88
std::set
STL class.
lsst::afw::image::detail::MaskDict::copyOrGetDefault
static std::shared_ptr< MaskDict > copyOrGetDefault(MaskPlaneDict const &dict)
Definition: MaskDict.cc:111
lsst::afw::image::detail::MaskDict::GlobalState::detachDefault
std::shared_ptr< MaskDict > detachDefault()
Definition: MaskDict.cc:64
lsst::afw::image::detail::MaskDict::GlobalState::copyOrGetDefault
std::shared_ptr< MaskDict > copyOrGetDefault(MaskPlaneDict const &mpd)
Definition: MaskDict.cc:39