Mantid
Loading...
Searching...
No Matches
MaskWorkspace.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7#include <algorithm>
8#include <utility>
9
14
15namespace Mantid::DataObjects {
19using std::set;
20using std::size_t;
21
22// Register the workspace
23DECLARE_WORKSPACE(MaskWorkspace)
24
25namespace { // keep these constants only within this file.
27const double LIVE_VALUE = 0.;
28
33const double DEAD_VALUE = 1.;
34
36const double ERROR_VALUE = 0.;
37} // namespace
38
39//--------------------------------------------------------------------------
40
45MaskWorkspace::MaskWorkspace(std::size_t numvectors) {
46 this->init(numvectors, 1, 1);
47 this->clearMask();
48}
49
56MaskWorkspace::MaskWorkspace(const Mantid::Geometry::Instrument_const_sptr &instrument, const bool includeMonitors)
57 : SpecialWorkspace2D(instrument, includeMonitors) {
58 this->clearMask();
59}
60
69
70//--------------------------------------------------------------------------
71
73 std::size_t nHist = this->getNumberHistograms();
74 for (std::size_t i = 0; i < nHist; ++i) {
75 this->dataY(i)[0] = LIVE_VALUE;
76 this->dataE(i)[0] = ERROR_VALUE;
77 }
78
79 // Clear the mask flags
81}
82
87 size_t numMasked(0);
88 const size_t numWksp(this->getNumberHistograms());
89 for (size_t i = 0; i < numWksp; i++) {
90 if (this->isMaskedIndex(i)) { // quick check the value
91
92 numMasked++;
93 } else {
94 const set<detid_t> ids = this->getDetectorIDs(i);
95 if (this->isMasked(ids)) // slow and correct check with the real method
96 numMasked += ids.size();
97 }
98 }
99 return numMasked;
100}
101
107 set<detid_t> detIDs;
108 /*
109 * Note
110 * This test originally just checked if there was an instrument and ignored
111 * the number of detectors
112 */
113 size_t numHist(this->getNumberHistograms());
114 for (size_t i = 0; i < numHist; i++) {
115 if (this->isMaskedIndex(i)) {
116 set<detid_t> temp = this->getDetectorIDs(i);
117 detIDs.insert(temp.begin(), temp.end());
118 }
119 }
120
121 return detIDs;
122}
123
129 set<size_t> indices;
130
131 size_t numHist(this->getNumberHistograms());
132 for (size_t i = 0; i < numHist; i++) {
133 if (this->isMaskedIndex(i)) {
134 indices.insert(i);
135 }
136 }
137
138 return indices;
139}
140
141bool MaskWorkspace::containsDetID(const detid_t detectorID) const { return this->contains(detectorID); }
142
143bool MaskWorkspace::containsDetIDs(const std::set<detid_t> &detectorIDs) const {
144 if (detectorIDs.empty()) {
145 return false;
146 }
147
148 const auto it = std::find_if_not(detectorIDs.cbegin(), detectorIDs.cend(),
149 [this](const auto detectorID) { return this->containsDetID(detectorID); });
150 return it == detectorIDs.cend();
151}
152
153bool MaskWorkspace::containsDetIDs(const std::vector<detid_t> &detectorIDs) const {
154 if (detectorIDs.empty()) {
155 return false;
156 }
157
158 const auto it = std::find_if_not(detectorIDs.cbegin(), detectorIDs.cend(),
159 [this](const auto detectorID) { return this->containsDetID(detectorID); });
160 return it == detectorIDs.cend();
161}
162
163//--------------------------------------------------------------------------------------------
168bool MaskWorkspace::isMasked(const detid_t detectorID) const {
169 // return true if the value isn't zero
170 // TODO: remove this case
171 // and refactor code that depends on non-existence = masked
172 if (this->contains(detectorID) && this->getValue(detectorID) != LIVE_VALUE) {
173 return true;
174 }
175
176 // the mask bit on the workspace can be set
177 // Performance wise, it is not optimal to call detectorInfo() for every index,
178 // but this method seems to be used rarely enough to justify this until the
179 // Instrument-2.0 implementation has progressed far enough to make this cheap.
180 const auto &detectorInfo = this->detectorInfo();
181 try {
182 return detectorInfo.isMasked(detectorInfo.indexOf(detectorID));
183 } catch (std::out_of_range &) {
184 // The workspace can contain bad detector IDs. DetectorInfo::indexOf throws.
185 return false;
186 }
187}
188
192bool MaskWorkspace::isMasked(const std::set<detid_t> &detectorIDs) const {
193 if (detectorIDs.empty()) {
194 return false;
195 }
196
197 const auto it = std::find_if_not(detectorIDs.cbegin(), detectorIDs.cend(),
198 [this](const auto detectorID) { return this->isMasked(detectorID); });
199 return it == detectorIDs.cend();
200}
201
205bool MaskWorkspace::isMaskedIndex(const std::size_t wkspIndex) const {
206 return (this->dataY(wkspIndex)[0] != LIVE_VALUE); // if is not live it should masked
207}
208
215void MaskWorkspace::setMasked(const detid_t detectorID, const bool mask) {
216 double value(LIVE_VALUE);
217 if (mask)
218 value = DEAD_VALUE;
219
220 // TODO: Consider updating deterctorinfo with .setMask
221 // or deleting this comment
222 // whichever makes more sense.
223 this->setValue(detectorID, value, ERROR_VALUE);
224}
225
230void MaskWorkspace::setMasked(const std::set<detid_t> &detectorIDs, const bool mask) {
231 for (auto detectorID : detectorIDs) {
232 this->setMasked(detectorID, mask);
233 }
234}
235
236void MaskWorkspace::setMaskedIndex(const std::size_t wkspIndex, const bool mask) {
237 double value(LIVE_VALUE);
238 if (mask)
239 value = DEAD_VALUE;
240
241 this->dataY(wkspIndex)[0] = value;
242}
243
248const std::string MaskWorkspace::id() const { return "MaskWorkspace"; }
249
250//--------------------------------------------------------------------------------------------
253void MaskWorkspace::copyFrom(std::shared_ptr<const SpecialWorkspace2D> sourcews) {
255}
256
259 if (!hasInstrument())
260 throw std::logic_error("MaskWorkspace has no instrument");
261
262 // detectors which are monitors are not included in the mask
263 const auto &detids = getInstrument()->getDetectorIDs(true);
264 const size_t N_spectra(getNumberHistograms());
265 const size_t N_monitors(detectorInfo().size() - detids.size());
266 const size_t N_detectors(detectors.size());
267 if (N_spectra == N_detectors - N_monitors) {
268 // One detector per spectrum
269 for (const auto &det : detids) {
270 if (isMasked(det))
271 detectors.setMasked(detectors.indexOf(det), true);
272 }
273 return;
274 }
275 // Multiple detectors per spectrum
277 "MaskWorkspace::combineToDetectorMasks: not implemented for the case of multiple detectors per spectrum.");
278#if 0 // Probably works: requires unit tests implementation.
279 const SpectrumInfo &info(spectrumInfo());
280 for (size_t ns = 0; ns < N_spectra; ++ns) {
281 const auto &spectrumDef = info.spectrumDefinition(ns);
282 if (isMaskedIndex(ns)) {
283 for (const auto &det_idx : spectrumDef)
284 detectors.setMasked(det_idx, true);
285 }
286 }
287#endif
288}
289
290} // namespace Mantid::DataObjects
291
292#if 0 // Probably works: requires unit tests implementation.
293namespace { // anonymous
294
295// Note: the following code replicates SpectrumInfo.cpp: lines 61-66, but as an anonymous utility method:
296bool isMaskedSpectrum(const Mantid::SpectrumDefinition &spectrumDef,
297 const Mantid::Geometry::DetectorInfo &detectorInfo) {
298 return std::all_of(
299 spectrumDef.cbegin(), spectrumDef.cend(),
300 [&detectorInfo](const std::pair<size_t, size_t> &detIndex) { return detectorInfo.isMasked(detIndex); });
301}
302
303} // namespace
304#endif
305
306namespace Mantid::DataObjects {
307
310 if (!hasInstrument())
311 throw std::logic_error("MaskWorkspace has no instrument");
312
313 // detectors which are monitors are not included in the mask
314 const auto &detids = getInstrument()->getDetectorIDs(true);
315 const size_t N_spectra(getNumberHistograms());
316 const size_t N_monitors(detectorInfo().size() - detids.size());
317 const size_t N_detectors(detectors.size());
318 if (N_spectra == N_detectors - N_monitors) {
319 // One detector per spectrum
320 for (const auto &det : detids) {
321 if (detectors.isMasked(detectors.indexOf(det)))
322 setMasked(det, true);
323 }
324 return;
325 }
326 // Multiple detectors per spectrum
328 "MaskWorkspace::combineFromDetectorMasks: not implemented for the case of multiple detectors per spectrum.");
329#if 0 // Probably works: requires unit tests implementation.
330 const SpectrumInfo &info(spectrumInfo());
331 for (size_t ns = 0; ns < N_spectra; ++ns) {
332 const auto &spectrumDef = info.spectrumDefinition(ns);
333 if (isMaskedSpectrum(spectrumDef, detectors)) {
334 setMaskedIndex(ns, true);
335 }
336 }
337#endif
338}
339
342 if (!hasInstrument())
343 throw std::logic_error("MaskWorkspace has no instrument");
344
345 // detectors which are monitors are not included in the mask
346 const auto &detids = getInstrument()->getDetectorIDs(true);
347 const size_t N_spectra(getNumberHistograms());
348 const size_t N_monitors(detectorInfo().size() - detids.size());
349 const size_t N_detectors(detectors.size());
350 if (N_spectra == N_detectors - N_monitors) {
351 // One detector per spectrum
352 auto maskConsistent = [&](const auto &det) { return isMasked(det) == detectors.isMasked(detectors.indexOf(det)); };
353
354 return std::all_of(detids.begin(), detids.end(), maskConsistent);
355 }
356
357 // Multiple detectors per spectrum
359 "MaskWorkspace::isConsistentWithDetectorMasks: not implemented for the case of multiple detectors per spectrum.");
360#if 0 // Probably works: requires unit tests implementation.
361 const SpectrumInfo &info(spectrumInfo());
362 for (size_t ns = 0; ns < N_spectra; ++ns) {
363 const auto &spectrumDef = info.spectrumDefinition(ns);
364 if (isMaskedIndex(ns) != isMaskedSpectrum(spectrumDef, detectors))
365 return false;
366 }
367 return true;
368#endif
369}
370
374const std::string MaskWorkspace::toString() const {
375 std::ostringstream os;
377 os << "Masked: " << getNumberMasked() << "\n";
378 return os.str();
379}
380
381//--------------------------------------------------------------------------------------------
387 bool hasinst;
389 if (inst) {
390 hasinst = inst->getNumberDetectors() > 0;
391 } else
392 hasinst = false;
393
394 return hasinst;
395}
396
397} // namespace Mantid::DataObjects
398
400
401namespace Mantid::Kernel {
402
403template <>
405IPropertyManager::getValue<Mantid::DataObjects::MaskWorkspace_sptr>(const std::string &name) const {
406 auto *prop = dynamic_cast<PropertyWithValue<Mantid::DataObjects::MaskWorkspace_sptr> *>(getPointerToProperty(name));
407 if (prop) {
408 return *prop;
409 } else {
410 std::string message =
411 "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<MaskWorkspace>.";
412 throw std::runtime_error(message);
413 }
414}
415
416template <>
418IPropertyManager::getValue<Mantid::DataObjects::MaskWorkspace_const_sptr>(const std::string &name) const {
419 const auto *prop =
420 dynamic_cast<PropertyWithValue<Mantid::DataObjects::MaskWorkspace_sptr> *>(getPointerToProperty(name));
421 if (prop) {
422 return prop->operator()();
423 } else {
424 std::string message =
425 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<MaskWorkspace>.";
426 throw std::runtime_error(message);
427 }
428}
429
430} // namespace Mantid::Kernel
431
std::string name
Definition Run.cpp:60
double value
The value of the point.
Definition FitMW.cpp:51
#define DLLExport
Definitions of the DLLImport compiler directives for MSVC.
Definition System.h:33
#define DECLARE_WORKSPACE(classname)
Geometry::DetectorInfo & mutableDetectorInfo()
Return a non-const reference to the DetectorInfo object.
const SpectrumInfo & spectrumInfo() const
Return a reference to the SpectrumInfo object.
const Geometry::DetectorInfo & detectorInfo() const
Return a const reference to the DetectorInfo object.
Geometry::Instrument_const_sptr getInstrument() const
Returns the parameterized instrument.
virtual MantidVec & dataE(const std::size_t index)
Deprecated, use mutableE() instead. Returns the error data.
virtual MantidVec & dataY(const std::size_t index)
Deprecated, use mutableY() instead. Returns the y data.
API::SpectrumInfo is an intermediate step towards a SpectrumInfo that is part of Instrument-2....
const SpectrumDefinition & spectrumDefinition(const size_t index) const
Returns a const reference to the SpectrumDefinition of the spectrum.
const std::string toString() const override
Return human-readable string.
bool containsDetID(const detid_t detectorID) const override
void clearMask()
Clear original incorrect mask.
void setMaskedIndex(const std::size_t wkspIndex, const bool mask=true)
const std::string id() const override
Gets the name of the workspace type.
bool isMaskedIndex(const std::size_t wkspIndex) const
Use this method with MaskWorkspace that doesn't have an instrument.
void copyFrom(std::shared_ptr< const SpecialWorkspace2D > sourcews) override
Copy the set up from another workspace.
bool hasInstrument() const
Check whether any instrument associated.
bool isConsistentWithDetectorMasks() const
Test consistency between the values from this workspace and its own detectors' mask flags.
void setMasked(const detid_t detectorID, const bool mask=true) override
Mask an individual pixel.
void combineFromDetectorMasks()
Ensure that this workspace's values include the values from its own detectors' mask flags.
bool containsDetIDs(const std::set< detid_t > &detectorIDs) const override
bool isMasked(const detid_t detectorID) const override
void combineToDetectorMasks()
Ensure that this mask workspace's detectors mask flags include the workspace values.
std::set< detid_t > getMaskedDetectors() const
MaskWorkspace::getMaskedDetectors.
std::set< std::size_t > getMaskedWkspIndices() const
MaskWorkspace::getMaskedWkspIndices.
std::size_t getNumberMasked() const override
double getValue(const detid_t detectorID) const
Return the special value (Y) in the workspace at the given detector ID.
const std::string toString() const override
Return human-readable string.
bool contains(const detid_t detectorID) const
void init(const size_t &NVectors, const size_t &XLength, const size_t &YLength) override
Sets the size of the workspace and initializes arrays to zero.
std::set< detid_t > getDetectorIDs(const std::size_t workspaceIndex) const
Return the detector ID at the given workspace index (i.e., spectrum/histogram index)
virtual void copyFrom(std::shared_ptr< const SpecialWorkspace2D > sourcews)
Duplicate SpecialWorkspace2D.
void setValue(const detid_t detectorID, const double value, const double error=0.)
Set the special value (Y) in the workspace at the given detector ID.
std::size_t getNumberHistograms() const override
Returns the histogram number.
std::size_t size() const override
get pseudo size
Geometry::DetectorInfo is an intermediate step towards a DetectorInfo that is part of Instrument-2....
bool isMasked(const size_t index) const
Returns true if the detector is masked.
void setMasked(const size_t index, bool masked)
Set the mask flag of the detector with given index. Not thread safe.
void clearMaskFlags()
Sets all mask flags to false (unmasked).
size_t indexOf(const detid_t id) const
Returns the index of the detector with the given detector ID.
size_t size() const
Returns the size of the DetectorInfo, i.e., the number of detectors in the instrument.
Marks code as not implemented yet.
Definition Exception.h:138
The concrete, templated class for properties.
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< const MaskWorkspace > MaskWorkspace_const_sptr
shared pointer to a const MaskWorkspace
std::shared_ptr< MaskWorkspace > MaskWorkspace_sptr
shared pointer to the MaskWorkspace class
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.