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 if (this->hasInstrument()) {
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 } else {
98 std::stringstream errss;
99 errss << "No instrument is associated with mask workspace " << this->getName();
100 throw std::runtime_error(errss.str());
101 }
102 }
103 return numMasked;
104}
105
111 set<detid_t> detIDs;
112 /*
113 * Note
114 * This test originally just checked if there was an instrument and ignored
115 * the number of detectors
116 */
117 if (this->hasInstrument()) {
118 size_t numHist(this->getNumberHistograms());
119 for (size_t i = 0; i < numHist; i++) {
120 if (this->isMaskedIndex(i)) {
121 set<detid_t> temp = this->getDetectorIDs(i);
122 detIDs.insert(temp.begin(), temp.end());
123 }
124 }
125 }
126
127 return detIDs;
128}
129
135 set<size_t> indices;
136
137 size_t numHist(this->getNumberHistograms());
138 for (size_t i = 0; i < numHist; i++) {
139 if (this->isMaskedIndex(i)) {
140 indices.insert(i);
141 }
142 }
143
144 return indices;
145}
146
147bool MaskWorkspace::containsDetID(const detid_t detectorID) const { return this->contains(detectorID); }
148
149bool MaskWorkspace::containsDetIDs(const std::set<detid_t> &detectorIDs) const {
150 if (detectorIDs.empty()) {
151 return false;
152 }
153
154 const auto it = std::find_if_not(detectorIDs.cbegin(), detectorIDs.cend(),
155 [this](const auto detectorID) { return this->containsDetID(detectorID); });
156 return it == detectorIDs.cend();
157}
158
159bool MaskWorkspace::containsDetIDs(const std::vector<detid_t> &detectorIDs) const {
160 if (detectorIDs.empty()) {
161 return false;
162 }
163
164 const auto it = std::find_if_not(detectorIDs.cbegin(), detectorIDs.cend(),
165 [this](const auto detectorID) { return this->containsDetID(detectorID); });
166 return it == detectorIDs.cend();
167}
168
169//--------------------------------------------------------------------------------------------
174bool MaskWorkspace::isMasked(const detid_t detectorID) const {
175 if (!this->hasInstrument()) {
176 std::stringstream msg;
177 if (!this->getInstrument())
178 msg << "There is no instrument associated with workspace \'" << this->getName() << "\'";
179 else
180 msg << "There is no proper instrument associated with workspace \'" << this->getName()
181 << "\'. Number of detectors = " << this->getInstrument()->getNumberDetectors();
182 throw std::runtime_error(msg.str());
183 }
184
185 // return true if the value isn't zero
186 // TODO: remove this case
187 // and refactor code that depends on non-existence = masked
188 if (this->contains(detectorID) && this->getValue(detectorID) != LIVE_VALUE) {
189 return true;
190 }
191
192 // the mask bit on the workspace can be set
193 // Performance wise, it is not optimal to call detectorInfo() for every index,
194 // but this method seems to be used rarely enough to justify this until the
195 // Instrument-2.0 implementation has progressed far enough to make this cheap.
196 const auto &detectorInfo = this->detectorInfo();
197 try {
198 return detectorInfo.isMasked(detectorInfo.indexOf(detectorID));
199 } catch (std::out_of_range &) {
200 // The workspace can contain bad detector IDs. DetectorInfo::indexOf throws.
201 return false;
202 }
203}
204
208bool MaskWorkspace::isMasked(const std::set<detid_t> &detectorIDs) const {
209 if (detectorIDs.empty()) {
210 return false;
211 }
212
213 const auto it = std::find_if_not(detectorIDs.cbegin(), detectorIDs.cend(),
214 [this](const auto detectorID) { return this->isMasked(detectorID); });
215 return it == detectorIDs.cend();
216}
217
221bool MaskWorkspace::isMaskedIndex(const std::size_t wkspIndex) const {
222 return (this->dataY(wkspIndex)[0] != LIVE_VALUE); // if is not live it should masked
223}
224
231void MaskWorkspace::setMasked(const detid_t detectorID, const bool mask) {
232 double value(LIVE_VALUE);
233 if (mask)
234 value = DEAD_VALUE;
235
236 // TODO: Consider updating deterctorinfo with .setMask
237 // or deleting this comment
238 // whichever makes more sense.
239 this->setValue(detectorID, value, ERROR_VALUE);
240}
241
246void MaskWorkspace::setMasked(const std::set<detid_t> &detectorIDs, const bool mask) {
247 for (auto detectorID : detectorIDs) {
248 this->setMasked(detectorID, mask);
249 }
250}
251
252void MaskWorkspace::setMaskedIndex(const std::size_t wkspIndex, const bool mask) {
253 double value(LIVE_VALUE);
254 if (mask)
255 value = DEAD_VALUE;
256
257 this->dataY(wkspIndex)[0] = value;
258}
259
264const std::string MaskWorkspace::id() const { return "MaskWorkspace"; }
265
266//--------------------------------------------------------------------------------------------
269void MaskWorkspace::copyFrom(std::shared_ptr<const SpecialWorkspace2D> sourcews) {
271}
272
275 if (!hasInstrument())
276 throw std::logic_error("MaskWorkspace has no instrument");
277
278 // detectors which are monitors are not included in the mask
279 const auto &detids = getInstrument()->getDetectorIDs(true);
280 const size_t N_spectra(getNumberHistograms());
281 const size_t N_monitors(detectorInfo().size() - detids.size());
282 const size_t N_detectors(detectors.size());
283 if (N_spectra == N_detectors - N_monitors) {
284 // One detector per spectrum
285 for (const auto &det : detids) {
286 if (isMasked(det))
287 detectors.setMasked(detectors.indexOf(det), true);
288 }
289 return;
290 }
291 // Multiple detectors per spectrum
293 "MaskWorkspace::combineToDetectorMasks: not implemented for the case of multiple detectors per spectrum.");
294#if 0 // Probably works: requires unit tests implementation.
295 const SpectrumInfo &info(spectrumInfo());
296 for (size_t ns = 0; ns < N_spectra; ++ns) {
297 const auto &spectrumDef = info.spectrumDefinition(ns);
298 if (isMaskedIndex(ns)) {
299 for (const auto &det_idx : spectrumDef)
300 detectors.setMasked(det_idx, true);
301 }
302 }
303#endif
304}
305
306} // namespace Mantid::DataObjects
307
308#if 0 // Probably works: requires unit tests implementation.
309namespace { // anonymous
310
311// Note: the following code replicates SpectrumInfo.cpp: lines 61-66, but as an anonymous utility method:
312bool isMaskedSpectrum(const Mantid::SpectrumDefinition &spectrumDef,
313 const Mantid::Geometry::DetectorInfo &detectorInfo) {
314 return std::all_of(
315 spectrumDef.cbegin(), spectrumDef.cend(),
316 [&detectorInfo](const std::pair<size_t, size_t> &detIndex) { return detectorInfo.isMasked(detIndex); });
317}
318
319} // namespace
320#endif
321
322namespace Mantid::DataObjects {
323
326 if (!hasInstrument())
327 throw std::logic_error("MaskWorkspace has no instrument");
328
329 // detectors which are monitors are not included in the mask
330 const auto &detids = getInstrument()->getDetectorIDs(true);
331 const size_t N_spectra(getNumberHistograms());
332 const size_t N_monitors(detectorInfo().size() - detids.size());
333 const size_t N_detectors(detectors.size());
334 if (N_spectra == N_detectors - N_monitors) {
335 // One detector per spectrum
336 for (const auto &det : detids) {
337 if (detectors.isMasked(detectors.indexOf(det)))
338 setMasked(det, true);
339 }
340 return;
341 }
342 // Multiple detectors per spectrum
344 "MaskWorkspace::combineFromDetectorMasks: not implemented for the case of multiple detectors per spectrum.");
345#if 0 // Probably works: requires unit tests implementation.
346 const SpectrumInfo &info(spectrumInfo());
347 for (size_t ns = 0; ns < N_spectra; ++ns) {
348 const auto &spectrumDef = info.spectrumDefinition(ns);
349 if (isMaskedSpectrum(spectrumDef, detectors)) {
350 setMaskedIndex(ns, true);
351 }
352 }
353#endif
354}
355
358 if (!hasInstrument())
359 throw std::logic_error("MaskWorkspace has no instrument");
360
361 // detectors which are monitors are not included in the mask
362 const auto &detids = getInstrument()->getDetectorIDs(true);
363 const size_t N_spectra(getNumberHistograms());
364 const size_t N_monitors(detectorInfo().size() - detids.size());
365 const size_t N_detectors(detectors.size());
366 if (N_spectra == N_detectors - N_monitors) {
367 // One detector per spectrum
368 auto maskConsistent = [&](const auto &det) { return isMasked(det) == detectors.isMasked(detectors.indexOf(det)); };
369
370 return std::all_of(detids.begin(), detids.end(), maskConsistent);
371 }
372
373 // Multiple detectors per spectrum
375 "MaskWorkspace::isConsistentWithDetectorMasks: not implemented for the case of multiple detectors per spectrum.");
376#if 0 // Probably works: requires unit tests implementation.
377 const SpectrumInfo &info(spectrumInfo());
378 for (size_t ns = 0; ns < N_spectra; ++ns) {
379 const auto &spectrumDef = info.spectrumDefinition(ns);
380 if (isMaskedIndex(ns) != isMaskedSpectrum(spectrumDef, detectors))
381 return false;
382 }
383 return true;
384#endif
385}
386
390const std::string MaskWorkspace::toString() const {
391 std::ostringstream os;
393 os << "Masked: " << getNumberMasked() << "\n";
394 return os.str();
395}
396
397//--------------------------------------------------------------------------------------------
403 bool hasinst;
405 if (inst) {
406 hasinst = inst->getNumberDetectors() > 0;
407 } else
408 hasinst = false;
409
410 return hasinst;
411}
412
413} // namespace Mantid::DataObjects
414
416
417namespace Mantid::Kernel {
418
419template <>
421IPropertyManager::getValue<Mantid::DataObjects::MaskWorkspace_sptr>(const std::string &name) const {
422 auto *prop = dynamic_cast<PropertyWithValue<Mantid::DataObjects::MaskWorkspace_sptr> *>(getPointerToProperty(name));
423 if (prop) {
424 return *prop;
425 } else {
426 std::string message =
427 "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<MaskWorkspace>.";
428 throw std::runtime_error(message);
429 }
430}
431
432template <>
434IPropertyManager::getValue<Mantid::DataObjects::MaskWorkspace_const_sptr>(const std::string &name) const {
435 const auto *prop =
436 dynamic_cast<PropertyWithValue<Mantid::DataObjects::MaskWorkspace_sptr> *>(getPointerToProperty(name));
437 if (prop) {
438 return prop->operator()();
439 } else {
440 std::string message =
441 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<MaskWorkspace>.";
442 throw std::runtime_error(message);
443 }
444}
445
446} // namespace Mantid::Kernel
447
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:37
#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 & getName() const override
Get the workspace name.
Definition Workspace.cpp:59
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.