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
12#include "MantidDataObjects/DllConfig.h"
15
16namespace Mantid::DataObjects {
20using std::set;
21using std::size_t;
22
23// Register the workspace
24DECLARE_WORKSPACE(MaskWorkspace)
25
26namespace { // keep these constants only within this file.
28const double LIVE_VALUE = 0.;
29
34const double DEAD_VALUE = 1.;
35
37const double ERROR_VALUE = 0.;
38} // namespace
39
40//--------------------------------------------------------------------------
41
46MaskWorkspace::MaskWorkspace(std::size_t numvectors) {
47 this->init(numvectors, 1, 1);
48 this->clearMask();
49}
50
57MaskWorkspace::MaskWorkspace(const Mantid::Geometry::Instrument_const_sptr &instrument, const bool includeMonitors)
58 : SpecialWorkspace2D(instrument, includeMonitors) {
59 this->clearMask();
60}
61
70
71//--------------------------------------------------------------------------
72
74 std::size_t nHist = this->getNumberHistograms();
75 for (std::size_t i = 0; i < nHist; ++i) {
76 this->mutableY(i)[0] = LIVE_VALUE;
77 this->mutableE(i)[0] = ERROR_VALUE;
78 }
79
80 // Clear the mask flags
82}
83
88 size_t numMasked(0);
89 const size_t numWksp(this->getNumberHistograms());
90 for (size_t i = 0; i < numWksp; i++) {
91 if (this->isMaskedIndex(i)) { // quick check the value
92
93 numMasked++;
94 } else {
95 const set<detid_t> ids = this->getDetectorIDs(i);
96 if (this->isMasked(ids)) // slow and correct check with the real method
97 numMasked += ids.size();
98 }
99 }
100 return numMasked;
101}
102
108 set<detid_t> detIDs;
109 /*
110 * Note
111 * This test originally just checked if there was an instrument and ignored
112 * the number of detectors
113 */
114 size_t numHist(this->getNumberHistograms());
115 for (size_t i = 0; i < numHist; i++) {
116 if (this->isMaskedIndex(i)) {
117 set<detid_t> temp = this->getDetectorIDs(i);
118 detIDs.insert(temp.begin(), temp.end());
119 }
120 }
121
122 return detIDs;
123}
124
130 set<size_t> indices;
131
132 size_t numHist(this->getNumberHistograms());
133 for (size_t i = 0; i < numHist; i++) {
134 if (this->isMaskedIndex(i)) {
135 indices.insert(i);
136 }
137 }
138
139 return indices;
140}
141
142bool MaskWorkspace::containsDetID(const detid_t detectorID) const { return this->contains(detectorID); }
143
144bool MaskWorkspace::containsDetIDs(const std::set<detid_t> &detectorIDs) const {
145 if (detectorIDs.empty()) {
146 return false;
147 }
148
149 const auto it = std::find_if_not(detectorIDs.cbegin(), detectorIDs.cend(),
150 [this](const auto detectorID) { return this->containsDetID(detectorID); });
151 return it == detectorIDs.cend();
152}
153
154bool MaskWorkspace::containsDetIDs(const std::vector<detid_t> &detectorIDs) const {
155 if (detectorIDs.empty()) {
156 return false;
157 }
158
159 const auto it = std::find_if_not(detectorIDs.cbegin(), detectorIDs.cend(),
160 [this](const auto detectorID) { return this->containsDetID(detectorID); });
161 return it == detectorIDs.cend();
162}
163
164//--------------------------------------------------------------------------------------------
169bool MaskWorkspace::isMasked(const detid_t detectorID) const {
170 // return true if the value isn't zero
171 // TODO: remove this case
172 // and refactor code that depends on non-existence = masked
173 if (this->contains(detectorID) && this->getValue(detectorID) != LIVE_VALUE) {
174 return true;
175 }
176
177 // the mask bit on the workspace can be set
178 // Performance wise, it is not optimal to call detectorInfo() for every index,
179 // but this method seems to be used rarely enough to justify this until the
180 // Instrument-2.0 implementation has progressed far enough to make this cheap.
181 const auto &detectorInfo = this->detectorInfo();
182 try {
183 return detectorInfo.isMasked(detectorInfo.indexOf(detectorID));
184 } catch (std::out_of_range &) {
185 // The workspace can contain bad detector IDs. DetectorInfo::indexOf throws.
186 return false;
187 }
188}
189
193bool MaskWorkspace::isMasked(const std::set<detid_t> &detectorIDs) const {
194 if (detectorIDs.empty()) {
195 return false;
196 }
197
198 const auto it = std::find_if_not(detectorIDs.cbegin(), detectorIDs.cend(),
199 [this](const auto detectorID) { return this->isMasked(detectorID); });
200 return it == detectorIDs.cend();
201}
202
206bool MaskWorkspace::isMaskedIndex(const std::size_t wkspIndex) const {
207 return (this->y(wkspIndex)[0] != LIVE_VALUE); // if is not live it should masked
208}
209
216void MaskWorkspace::setMasked(const detid_t detectorID, const bool mask) {
217 double value(LIVE_VALUE);
218 if (mask)
219 value = DEAD_VALUE;
220
221 // TODO: Consider updating deterctorinfo with .setMask
222 // or deleting this comment
223 // whichever makes more sense.
224 this->setValue(detectorID, value, ERROR_VALUE);
225}
226
231void MaskWorkspace::setMasked(const std::set<detid_t> &detectorIDs, const bool mask) {
232 for (auto detectorID : detectorIDs) {
233 this->setMasked(detectorID, mask);
234 }
235}
236
237void MaskWorkspace::setMaskedIndex(const std::size_t wkspIndex, const bool mask) {
238 double value(LIVE_VALUE);
239 if (mask)
240 value = DEAD_VALUE;
241
242 this->mutableY(wkspIndex)[0] = value;
243}
244
249const std::string MaskWorkspace::id() const { return "MaskWorkspace"; }
250
251//--------------------------------------------------------------------------------------------
254void MaskWorkspace::copyFrom(std::shared_ptr<const SpecialWorkspace2D> sourcews) {
256}
257
260 if (!hasInstrument())
261 throw std::logic_error("MaskWorkspace has no instrument");
262
263 // detectors which are monitors are not included in the mask
264 const auto &detids = getInstrument()->getDetectorIDs(true);
265 const size_t N_spectra(getNumberHistograms());
266 const size_t N_monitors(detectorInfo().size() - detids.size());
267 const size_t N_detectors(detectors.size());
268 if (N_spectra == N_detectors - N_monitors) {
269 // One detector per spectrum
270 for (const auto &det : detids) {
271 if (isMasked(det))
272 detectors.setMasked(detectors.indexOf(det), true);
273 }
274 return;
275 }
276 // Multiple detectors per spectrum
278 "MaskWorkspace::combineToDetectorMasks: not implemented for the case of multiple detectors per spectrum.");
279#if 0 // Probably works: requires unit tests implementation.
280 const SpectrumInfo &info(spectrumInfo());
281 for (size_t ns = 0; ns < N_spectra; ++ns) {
282 const auto &spectrumDef = info.spectrumDefinition(ns);
283 if (isMaskedIndex(ns)) {
284 for (const auto &det_idx : spectrumDef)
285 detectors.setMasked(det_idx, true);
286 }
287 }
288#endif
289}
290
291} // namespace Mantid::DataObjects
292
293#if 0 // Probably works: requires unit tests implementation.
294namespace { // anonymous
295
296// Note: the following code replicates SpectrumInfo.cpp: lines 61-66, but as an anonymous utility method:
297bool isMaskedSpectrum(const Mantid::SpectrumDefinition &spectrumDef,
298 const Mantid::Geometry::DetectorInfo &detectorInfo) {
299 return std::all_of(
300 spectrumDef.cbegin(), spectrumDef.cend(),
301 [&detectorInfo](const std::pair<size_t, size_t> &detIndex) { return detectorInfo.isMasked(detIndex); });
302}
303
304} // namespace
305#endif
306
307namespace Mantid::DataObjects {
308
311 if (!hasInstrument())
312 throw std::logic_error("MaskWorkspace has no instrument");
313
314 // detectors which are monitors are not included in the mask
315 const auto &detids = getInstrument()->getDetectorIDs(true);
316 const size_t N_spectra(getNumberHistograms());
317 const size_t N_monitors(detectorInfo().size() - detids.size());
318 const size_t N_detectors(detectors.size());
319 if (N_spectra == N_detectors - N_monitors) {
320 // One detector per spectrum
321 for (const auto &det : detids) {
322 if (detectors.isMasked(detectors.indexOf(det)))
323 setMasked(det, true);
324 }
325 return;
326 }
327 // Multiple detectors per spectrum
329 "MaskWorkspace::combineFromDetectorMasks: not implemented for the case of multiple detectors per spectrum.");
330#if 0 // Probably works: requires unit tests implementation.
331 const SpectrumInfo &info(spectrumInfo());
332 for (size_t ns = 0; ns < N_spectra; ++ns) {
333 const auto &spectrumDef = info.spectrumDefinition(ns);
334 if (isMaskedSpectrum(spectrumDef, detectors)) {
335 setMaskedIndex(ns, true);
336 }
337 }
338#endif
339}
340
343 if (!hasInstrument())
344 throw std::logic_error("MaskWorkspace has no instrument");
345
346 // detectors which are monitors are not included in the mask
347 const auto &detids = getInstrument()->getDetectorIDs(true);
348 const size_t N_spectra(getNumberHistograms());
349 const size_t N_monitors(detectorInfo().size() - detids.size());
350 const size_t N_detectors(detectors.size());
351 if (N_spectra == N_detectors - N_monitors) {
352 // One detector per spectrum
353 auto maskConsistent = [&](const auto &det) { return isMasked(det) == detectors.isMasked(detectors.indexOf(det)); };
354
355 return std::all_of(detids.begin(), detids.end(), maskConsistent);
356 }
357
358 // Multiple detectors per spectrum
360 "MaskWorkspace::isConsistentWithDetectorMasks: not implemented for the case of multiple detectors per spectrum.");
361#if 0 // Probably works: requires unit tests implementation.
362 const SpectrumInfo &info(spectrumInfo());
363 for (size_t ns = 0; ns < N_spectra; ++ns) {
364 const auto &spectrumDef = info.spectrumDefinition(ns);
365 if (isMaskedIndex(ns) != isMaskedSpectrum(spectrumDef, detectors))
366 return false;
367 }
368 return true;
369#endif
370}
371
375const std::string MaskWorkspace::toString() const {
376 std::ostringstream os;
378 os << "Masked: " << getNumberMasked() << "\n";
379 return os.str();
380}
381
382//--------------------------------------------------------------------------------------------
388 bool hasinst;
390 if (inst) {
391 hasinst = inst->getNumberDetectors() > 0;
392 } else
393 hasinst = false;
394
395 return hasinst;
396}
397
398} // namespace Mantid::DataObjects
399
401
402namespace Mantid::Kernel {
403
404template <>
405MANTID_DATAOBJECTS_DLL Mantid::DataObjects::MaskWorkspace_sptr
406IPropertyManager::getValue<Mantid::DataObjects::MaskWorkspace_sptr>(const std::string &name) const {
407 auto *prop = dynamic_cast<PropertyWithValue<Mantid::DataObjects::MaskWorkspace_sptr> *>(getPointerToProperty(name));
408 if (prop) {
409 return *prop;
410 } else {
411 std::string message =
412 "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<MaskWorkspace>.";
413 throw std::runtime_error(message);
414 }
415}
416
417template <>
419IPropertyManager::getValue<Mantid::DataObjects::MaskWorkspace_const_sptr>(const std::string &name) const {
420 const auto *prop =
421 dynamic_cast<PropertyWithValue<Mantid::DataObjects::MaskWorkspace_sptr> *>(getPointerToProperty(name));
422 if (prop) {
423 return prop->operator()();
424 } else {
425 std::string message =
426 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<MaskWorkspace>.";
427 throw std::runtime_error(message);
428 }
429}
430
431} // namespace Mantid::Kernel
432
std::string name
Definition Run.cpp:60
double value
The value of the point.
Definition FitMW.cpp:51
#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.
HistogramData::HistogramE & mutableE(const size_t index) &
HistogramData::HistogramY & mutableY(const size_t index) &
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.