14#include "MantidIndexing/IndexInfo.h"
15#include "MantidIndexing/LegacyConversion.h"
16#include "MantidIndexing/SpectrumIndexSet.h"
32void constrainIndexInRange(std::vector<size_t> &sourceList, std::vector<size_t> &targetList,
size_t minIndex,
34 targetList.reserve(sourceList.size());
35 std::sort(sourceList.begin(), sourceList.end());
36 std::copy_if(sourceList.cbegin(), sourceList.cend(), std::back_inserter(targetList),
37 [minIndex, maxIndex](
auto sourceValue) { return sourceValue >= minIndex && sourceValue <= maxIndex; });
47using namespace Kernel;
48using namespace DataObjects;
49using namespace Geometry;
56 "The name of the input and output workspace on which to perform the "
61 "A list of the workspace indices to mask");
64 "If given but not as a SpecialWorkspace2D, the masking from "
65 "this workspace will be copied. If given as a "
66 "SpecialWorkspace2D, the masking is read from its Y values.");
68 "Works when 'MaskedWorkspace' is provided and forces "
69 "to use spectra-detector mapping even in case when number of "
70 "spectra in 'Workspace' and 'MaskedWorkspace' are equal",
73 std::make_unique<EnabledWhenProperty>(
"MaskedWorkspace", ePropertyCriterion::IS_NOT_DEFAULT));
75 auto mustBePosInt = std::make_shared<BoundedValidator<int>>();
76 mustBePosInt->setLower(0);
78 "If other masks fields are provided, it's the first index of the "
79 "target workspace to be allowed to be masked from by these masks, "
80 "if not, its the first index of the target workspace to mask.\n"
81 "Default value is 0 if other masking is present or ignored if not.");
83 "If other masks are provided, it's the last index of the "
84 "target workspace allowed to be masked to by these masks, "
85 "if not, its the last index of the target workspace to mask.\n"
86 "Default is number of histograms in target workspace if other masks are"
88 "or ignored if not.");
110 const auto isMaskWS =
static_cast<bool>(inputAsMaskWS);
112 std::vector<size_t> indexList =
getProperty(
"WorkspaceIndexList");
113 auto spectraList = Indexing::makeSpectrumNumberVector(
getProperty(
"SpectraList"));
115 std::vector<std::string> componentList =
getProperty(
"ComponentList");
116 if (!componentList.empty()) {
122 bool range_constrained = std::get<2>(ranges_info);
124 bool mask_defined(
false);
125 if (!indexList.empty() || !spectraList.empty() || !
detectorList.empty() || prevMasking) {
131 if (!mask_defined && !range_constrained) {
133 "detector lists and masked workspace properties are all empty");
138 if (!mask_defined && range_constrained) {
139 size_t list_size = std::get<1>(ranges_info) - std::get<0>(ranges_info) + 1;
140 indexList.resize(list_size);
141 std::iota(indexList.begin(), indexList.end(), std::get<0>(ranges_info));
144 auto maskWS = std::dynamic_pointer_cast<DataObjects::MaskWorkspace>(prevMasking);
145 if (maskWS && prevMasking) {
147 }
else if (prevMasking) {
155 if (!spectraList.empty()) {
160 if (indexList.empty()) {
161 indexList = WS->getIndicesFromDetectorIDs(
detectorList);
163 auto tmpList = WS->getIndicesFromDetectorIDs(
detectorList);
164 indexList.insert(indexList.end(), std::begin(tmpList), std::end(tmpList));
169 if (range_constrained) {
174 if (indexList.empty()) {
180 auto &spectrumInfo = WS->mutableSpectrumInfo();
182 for (
const auto i : indexList) {
183 WS->getSpectrum(i).clearData();
184 if (spectrumInfo.hasDetectors(i))
185 spectrumInfo.setMasked(i,
true);
188 prog += (1.0 /
static_cast<int>(indexList.size()));
199 auto &maskWsSpectrumInfo = inputAsMaskWS->mutableSpectrumInfo();
200 for (
size_t i = 0; i < inputAsMaskWS->getNumberHistograms(); ++i) {
201 const bool mask = inputAsMaskWS->isMaskedIndex(i) || maskWsSpectrumInfo.isMasked(i);
202 inputAsMaskWS->setMaskedIndex(i, mask);
204 maskWsSpectrumInfo.setMasked(i,
false);
222 std::vector<detid_t> &
detectorList, std::vector<size_t> &indexList,
225 if (maskWs->getInstrument()->getDetectorIDs().size() != WS->getInstrument()->getDetectorIDs().size()) {
226 throw std::runtime_error(
"Instrument's detector numbers mismatch "
227 "between input Workspace and MaskWorkspace");
230 g_log.
debug() <<
"Extracting mask from MaskWorkspace (" << maskWs->getName() <<
")\n";
231 bool forceDetIDs =
getProperty(
"ForceInstrumentMasking");
232 if (maskWs->getNumberHistograms() != WS->getNumberHistograms() || forceDetIDs) {
254 std::vector<detid_t> &
detectorList, std::vector<size_t> &indexList,
257 const auto nHist = maskWs->getNumberHistograms();
258 auto instrument = WS->getInstrument();
259 auto maskInstrument = maskWs->getInstrument();
263 if (nHist == WS->getNumberHistograms()) {
267 }
else if (instrument && maskInstrument) {
268 const auto inputDetCount = instrument->getNumberDetectors();
269 const auto maskDetCount = maskInstrument->getNumberDetectors();
273 if (inputDetCount != maskDetCount)
274 g_log.
warning() <<
"Number of detectors does not match between "
275 "mask workspace and input workspace";
277 if (instrument->getName() != maskInstrument->getName())
278 g_log.
warning() <<
"Mask is from a different instrument to the input "
284 throw std::runtime_error(
"Input or mask workspace does not have an instrument.");
298 int startIndex =
getProperty(
"StartWorkspaceIndex");
299 size_t max_ind = targWS->getNumberHistograms() - 1;
301 if (endIndex ==
EMPTY_INT() && startIndex == 0) {
302 return std::tuple<size_t, size_t, bool>(0, max_ind,
false);
304 if (startIndex < 0) {
307 auto startIndex_l =
static_cast<size_t>(startIndex);
308 auto endIndex_l =
static_cast<size_t>(endIndex);
311 endIndex_l = max_ind;
313 if (endIndex_l > max_ind) {
314 endIndex_l = max_ind;
316 if (startIndex_l > endIndex_l) {
317 startIndex_l = endIndex_l;
320 return std::tuple<size_t, size_t, bool>(startIndex_l, endIndex_l,
true);
332 const std::tuple<size_t, size_t, bool> &range_info) {
334 std::vector<size_t>
tmp;
335 constrainIndexInRange(indexList,
tmp, std::get<0>(range_info), std::get<1>(range_info));
349 size_t nHist = maskWS->getNumberHistograms();
350 for (
size_t i = 0; i < nHist; ++i) {
351 if (maskWS->y(i).front() > 0.5) {
352 const auto &dets = maskWS->getSpectrum(i).getDetectorIDs();
353 std::copy(dets.cbegin(), dets.cend(), std::back_inserter(
detectorList));
370 "detector lists and masked workspace properties are all empty");
374 auto &detInfo = WS->mutableDetectorInfo();
375 std::vector<size_t> indicesToMask;
378 indicesToMask.emplace_back(detInfo.indexOf(detID));
379 }
catch (std::out_of_range &) {
380 g_log.
warning() <<
"Invalid detector ID " << detID <<
". Found while running MaskDetectors\n";
388 const auto &maskDetInfo = maskWS->detectorInfo();
389 if (detInfo.size() != maskDetInfo.size()) {
390 throw std::runtime_error(
"Size mismatch between input Workspace and MaskWorkspace");
393 g_log.
debug() <<
"Extracting mask from MaskWorkspace (" << maskWS->getName() <<
")\n";
395 for (
size_t i = 0; i < maskDetInfo.size(); ++i)
396 if (maskDetInfo.isMasked(i))
397 indicesToMask.emplace_back(i);
401 for (
const auto index : indicesToMask)
402 detInfo.setMasked(
index,
true);
414 std::vector<Indexing::SpectrumNumber> spectraList,
416 const std::tuple<size_t, size_t, bool> &range_info) {
418 std::vector<size_t> tmp_index;
419 size_t startIndex = std::get<0>(range_info);
420 size_t endIndex = std::get<1>(range_info);
421 bool range_constrained = std::get<2>(range_info);
423 if (range_constrained) {
424 constrainIndexInRange(indexList, tmp_index, startIndex, endIndex);
426 tmp_index.swap(indexList);
430 std::sort(spectraList.begin(), spectraList.end());
431 auto last = std::unique(spectraList.begin(), spectraList.end());
432 if (last != spectraList.end())
434 spectraList.erase(last, spectraList.end());
435 for (
auto ws_index : WS->indexInfo().makeIndexSet(spectraList)) {
436 if (range_constrained && (ws_index < startIndex || ws_index > endIndex)) {
439 tmp_index.emplace_back(ws_index);
442 tmp_index.swap(indexList);
454 const std::tuple<size_t, size_t, bool> &range_info) {
456 std::vector<size_t> tmp_index;
457 size_t startIndex = std::get<0>(range_info);
458 size_t endIndex = std::get<1>(range_info);
459 bool range_constrained = std::get<2>(range_info);
461 const auto &spectrumInfo = sourceWS->spectrumInfo();
462 if (range_constrained) {
463 constrainIndexInRange(indexList, tmp_index, startIndex, endIndex);
465 for (
size_t i = startIndex; i <= endIndex; ++i) {
466 if (spectrumInfo.hasDetectors(i) && spectrumInfo.isMasked(i)) {
467 tmp_index.emplace_back(i);
471 tmp_index.swap(indexList);
473 endIndex = sourceWS->getNumberHistograms();
474 for (
size_t i = 0; i < endIndex; ++i) {
475 if (spectrumInfo.hasDetectors(i) && spectrumInfo.isMasked(i)) {
476 tmp_index.emplace_back(i);
480 tmp_index.swap(indexList);
497 const std::tuple<size_t, size_t, bool> &range_info) {
498 const auto startIndex = std::get<0>(range_info);
499 const auto endIndex = std::get<1>(range_info);
500 const auto &detMap = inputWs->getDetectorIDToWorkspaceIndexMap();
503 for (
size_t i = 0; i < maskWs->getNumberHistograms(); ++i) {
504 if (maskWs->y(i)[0] == 0) {
505 const auto &spec = maskWs->getSpectrum(i);
506 for (
const auto &
id : spec.getDetectorIDs()) {
507 if (detMap.at(
id) >= startIndex && detMap.at(
id) <= endIndex)
525 const std::tuple<size_t, size_t, bool> &range_info) {
527 std::vector<size_t> tmp_index;
529 size_t startIndex = std::get<0>(range_info);
530 size_t endIndex = std::get<1>(range_info);
531 bool range_constrained = std::get<2>(range_info);
533 if (range_constrained) {
534 constrainIndexInRange(indexList, tmp_index, startIndex, endIndex);
536 for (
size_t i = startIndex; i <= endIndex; ++i) {
537 if (maskedWorkspace->y(i)[0] > 0.5) {
538 g_log.
debug() <<
"Adding WorkspaceIndex " << i <<
" to mask.\n";
539 tmp_index.emplace_back(i);
543 tmp_index.swap(indexList);
544 endIndex = maskedWorkspace->getNumberHistograms();
545 for (
size_t i = 0; i < endIndex; ++i) {
547 if (maskedWorkspace->y(i)[0] > 0.5) {
548 g_log.
debug() <<
"Adding WorkspaceIndex " << i <<
" to mask.\n";
549 tmp_index.emplace_back(i);
553 tmp_index.swap(indexList);
565 const std::vector<std::string> &componentList,
567 const auto instrument = WS->getInstrument();
569 g_log.
error() <<
"No instrument in input workspace. Ignoring ComponentList\n";
572 std::set<detid_t> detectorIDs;
573 for (
const auto &compName : componentList) {
574 std::vector<IDetector_const_sptr> dets;
575 instrument->getDetectorsInBank(dets, compName);
577 const auto component = instrument->getComponentByName(compName);
578 const auto det = std::dynamic_pointer_cast<const IDetector>(component);
580 g_log.
warning() <<
"No detectors found in component '" << compName <<
"'\n";
583 dets.emplace_back(det);
585 for (
const auto &det : dets) {
586 detectorIDs.emplace(det->getID());
592 std::copy(detectorIDs.cbegin(), detectorIDs.cend(), appendBegin);
#define DECLARE_ALGORITHM(classname)
std::map< DeltaEMode::Type, std::string > index
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
A property class for workspaces.
void handleMaskByMatrixWorkspace(const API::MatrixWorkspace_const_sptr &maskWs, const API::MatrixWorkspace_const_sptr &WS, std::vector< detid_t > &detectorList, std::vector< size_t > &indexList, const RangeInfo &rangeInfo)
Choose how to mask given that we have a matrix workspace.
void fillIndexListFromSpectra(std::vector< size_t > &indexList, std::vector< Indexing::SpectrumNumber > spectraList, const API::MatrixWorkspace_sptr &WS, const RangeInfo &range_info)
RangeInfo getRanges(const API::MatrixWorkspace_sptr &targWS)
std::tuple< size_t, size_t, bool > RangeInfo
void constrainMaskedIndexes(std::vector< size_t > &indexList, const RangeInfo &range_info)
void init() override
Virtual method - must be overridden by concrete algorithm.
void appendToDetectorListFromWS(std::vector< detid_t > &detectorList, const API::MatrixWorkspace_const_sptr &inputWs, const API::MatrixWorkspace_const_sptr &maskWs, const std::tuple< size_t, size_t, bool > &range_info)
Append the indices of a workspace corresponding to detector IDs to the given list.
void appendToIndexListFromMaskWS(std::vector< size_t > &indexList, const DataObjects::MaskWorkspace_const_sptr &maskedWorkspace, const std::tuple< size_t, size_t, bool > &range_info)
Append the indices of the masked spectra from the given workspace list to the given list.
void exec() override
Virtual method - must be overridden by concrete algorithm.
void appendToDetectorListFromComponentList(std::vector< detid_t > &detectorList, const std::vector< std::string > &componentList, const API::MatrixWorkspace_const_sptr &WS)
Append the detector IDs of detectors found recursively in the list of components.
void appendToIndexListFromWS(std::vector< size_t > &indexList, const API::MatrixWorkspace_const_sptr &maskedWorkspace, const RangeInfo &range_info)
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
void execPeaks(const DataObjects::PeaksWorkspace_sptr &WS)
void extractMaskedWSDetIDs(std::vector< detid_t > &detectorList, const DataObjects::MaskWorkspace_const_sptr &maskWS)
void handleMaskByMaskWorkspace(const DataObjects::MaskWorkspace_const_sptr &maskWs, const API::MatrixWorkspace_const_sptr &WS, std::vector< detid_t > &detectorList, std::vector< size_t > &indexList, const RangeInfo &rangeInfo)
Choose how to mask given that we have a mask workspace.
Support for a property that holds an array of values.
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
void debug(const std::string &msg)
Logs at debug level.
void notice(const std::string &msg)
Logs at notice level.
void error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
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< PeaksWorkspace > PeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
@ InOut
Both an input & output workspace.
@ Input
An input workspace.