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
147//--------------------------------------------------------------------------------------------
152bool MaskWorkspace::isMasked(const detid_t detectorID) const {
153 if (!this->hasInstrument()) {
154 std::stringstream msg;
155 if (!this->getInstrument())
156 msg << "There is no instrument associated with workspace \'" << this->getName() << "\'";
157 else
158 msg << "There is no proper instrument associated with workspace \'" << this->getName()
159 << "\'. Number of detectors = " << this->getInstrument()->getNumberDetectors();
160 throw std::runtime_error(msg.str());
161 }
162
163 // return true if the value isn't zero
164 if (this->getValue(detectorID, LIVE_VALUE) != LIVE_VALUE) {
165 return true;
166 }
167
168 // the mask bit on the workspace can be set
169 // Performance wise, it is not optimal to call detectorInfo() for every index,
170 // but this method seems to be used rarely enough to justify this until the
171 // Instrument-2.0 implementation has progressed far enough to make this cheap.
172 const auto &detectorInfo = this->detectorInfo();
173 try {
174 return detectorInfo.isMasked(detectorInfo.indexOf(detectorID));
175 } catch (std::out_of_range &) {
176 // The workspace can contain bad detector IDs. DetectorInfo::indexOf throws.
177 return false;
178 }
179}
180
184bool MaskWorkspace::isMasked(const std::set<detid_t> &detectorIDs) const {
185 if (detectorIDs.empty()) {
186 return false;
187 }
188
189 const auto it = std::find_if_not(detectorIDs.cbegin(), detectorIDs.cend(),
190 [this](const auto detectorID) { return this->isMasked(detectorID); });
191 return it == detectorIDs.cend();
192}
193
197bool MaskWorkspace::isMaskedIndex(const std::size_t wkspIndex) const {
198 return (this->dataY(wkspIndex)[0] != LIVE_VALUE); // if is not live it should masked
199}
200
207void MaskWorkspace::setMasked(const detid_t detectorID, const bool mask) {
208 double value(LIVE_VALUE);
209 if (mask)
210 value = DEAD_VALUE;
211
212 this->setValue(detectorID, value, ERROR_VALUE);
213}
214
219void MaskWorkspace::setMasked(const std::set<detid_t> &detectorIDs, const bool mask) {
220 for (auto detectorID : detectorIDs) {
221 this->setMasked(detectorID, mask);
222 }
223}
224
225void MaskWorkspace::setMaskedIndex(const std::size_t wkspIndex, const bool mask) {
226 double value(LIVE_VALUE);
227 if (mask)
228 value = DEAD_VALUE;
229
230 this->dataY(wkspIndex)[0] = value;
231}
232
237const std::string MaskWorkspace::id() const { return "MaskWorkspace"; }
238
239//--------------------------------------------------------------------------------------------
242void MaskWorkspace::copyFrom(std::shared_ptr<const SpecialWorkspace2D> sourcews) {
244}
245
248 if (!hasInstrument())
249 throw std::logic_error("MaskWorkspace has no instrument");
250
251 // detectors which are monitors are not included in the mask
252 const auto &detids = getInstrument()->getDetectorIDs(true);
253 const size_t N_spectra(getNumberHistograms());
254 const size_t N_monitors(detectorInfo().size() - detids.size());
255 const size_t N_detectors(detectors.size());
256 if (N_spectra == N_detectors - N_monitors) {
257 // One detector per spectrum
258 for (const auto &det : detids) {
259 if (isMasked(det))
260 detectors.setMasked(detectors.indexOf(det), true);
261 }
262 return;
263 }
264 // Multiple detectors per spectrum
266 "MaskWorkspace::combineToDetectorMasks: not implemented for the case of multiple detectors per spectrum.");
267#if 0 // Probably works: requires unit tests implementation.
268 const SpectrumInfo &info(spectrumInfo());
269 for (size_t ns = 0; ns < N_spectra; ++ns) {
270 const auto &spectrumDef = info.spectrumDefinition(ns);
271 if (isMaskedIndex(ns)) {
272 for (const auto &det_idx : spectrumDef)
273 detectors.setMasked(det_idx, true);
274 }
275 }
276#endif
277}
278
279} // namespace Mantid::DataObjects
280
281#if 0 // Probably works: requires unit tests implementation.
282namespace { // anonymous
283
284// Note: the following code replicates SpectrumInfo.cpp: lines 61-66, but as an anonymous utility method:
285bool isMaskedSpectrum(const Mantid::SpectrumDefinition &spectrumDef,
286 const Mantid::Geometry::DetectorInfo &detectorInfo) {
287 return std::all_of(
288 spectrumDef.cbegin(), spectrumDef.cend(),
289 [&detectorInfo](const std::pair<size_t, size_t> &detIndex) { return detectorInfo.isMasked(detIndex); });
290}
291
292} // namespace
293#endif
294
295namespace Mantid::DataObjects {
296
299 if (!hasInstrument())
300 throw std::logic_error("MaskWorkspace has no instrument");
301
302 // detectors which are monitors are not included in the mask
303 const auto &detids = getInstrument()->getDetectorIDs(true);
304 const size_t N_spectra(getNumberHistograms());
305 const size_t N_monitors(detectorInfo().size() - detids.size());
306 const size_t N_detectors(detectors.size());
307 if (N_spectra == N_detectors - N_monitors) {
308 // One detector per spectrum
309 for (const auto &det : detids) {
310 if (detectors.isMasked(detectors.indexOf(det)))
311 setMasked(det, true);
312 }
313 return;
314 }
315 // Multiple detectors per spectrum
317 "MaskWorkspace::combineFromDetectorMasks: not implemented for the case of multiple detectors per spectrum.");
318#if 0 // Probably works: requires unit tests implementation.
319 const SpectrumInfo &info(spectrumInfo());
320 for (size_t ns = 0; ns < N_spectra; ++ns) {
321 const auto &spectrumDef = info.spectrumDefinition(ns);
322 if (isMaskedSpectrum(spectrumDef, detectors)) {
323 setMaskedIndex(ns, true);
324 }
325 }
326#endif
327}
328
331 if (!hasInstrument())
332 throw std::logic_error("MaskWorkspace has no instrument");
333
334 // detectors which are monitors are not included in the mask
335 const auto &detids = getInstrument()->getDetectorIDs(true);
336 const size_t N_spectra(getNumberHistograms());
337 const size_t N_monitors(detectorInfo().size() - detids.size());
338 const size_t N_detectors(detectors.size());
339 if (N_spectra == N_detectors - N_monitors) {
340 // One detector per spectrum
341 for (const auto &det : detids) {
342 if (isMasked(det) != detectors.isMasked(detectors.indexOf(det)))
343 return false;
344 }
345 return true;
346 }
347 // Multiple detectors per spectrum
349 "MaskWorkspace::isConsistentWithDetectorMasks: not implemented for the case of multiple detectors per spectrum.");
350#if 0 // Probably works: requires unit tests implementation.
351 const SpectrumInfo &info(spectrumInfo());
352 for (size_t ns = 0; ns < N_spectra; ++ns) {
353 const auto &spectrumDef = info.spectrumDefinition(ns);
354 if (isMaskedIndex(ns) != isMaskedSpectrum(spectrumDef, detectors))
355 return false;
356 }
357 return true;
358#endif
359}
360
364const std::string MaskWorkspace::toString() const {
365 std::ostringstream os;
367 os << "Masked: " << getNumberMasked() << "\n";
368 return os.str();
369}
370
371//--------------------------------------------------------------------------------------------
377 bool hasinst;
379 if (inst) {
380 hasinst = inst->getNumberDetectors() > 0;
381 } else
382 hasinst = false;
383
384 return hasinst;
385}
386
387} // namespace Mantid::DataObjects
388
390
391namespace Mantid::Kernel {
392
393template <>
395IPropertyManager::getValue<Mantid::DataObjects::MaskWorkspace_sptr>(const std::string &name) const {
396 auto *prop = dynamic_cast<PropertyWithValue<Mantid::DataObjects::MaskWorkspace_sptr> *>(getPointerToProperty(name));
397 if (prop) {
398 return *prop;
399 } else {
400 std::string message =
401 "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<MaskWorkspace>.";
402 throw std::runtime_error(message);
403 }
404}
405
406template <>
408IPropertyManager::getValue<Mantid::DataObjects::MaskWorkspace_const_sptr>(const std::string &name) const {
409 const auto *prop =
410 dynamic_cast<PropertyWithValue<Mantid::DataObjects::MaskWorkspace_sptr> *>(getPointerToProperty(name));
411 if (prop) {
412 return prop->operator()();
413 } else {
414 std::string message =
415 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<MaskWorkspace>.";
416 throw std::runtime_error(message);
417 }
418}
419
420} // namespace Mantid::Kernel
421
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.
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 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.
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.