diff --git a/Framework/Algorithms/src/ExtractMask.cpp b/Framework/Algorithms/src/ExtractMask.cpp index f74ae3705128..bf8084cdfbfd 100644 --- a/Framework/Algorithms/src/ExtractMask.cpp +++ b/Framework/Algorithms/src/ExtractMask.cpp @@ -28,6 +28,7 @@ using namespace Kernel; void ExtractMask::init() { declareProperty(std::make_unique>("InputWorkspace", "", Direction::Input), "A workspace whose masking is to be extracted"); + declareProperty("UngroupDetectors", false, "If true, the spectra will be ungrouped and masked individually."); declareProperty(std::make_unique>("OutputWorkspace", "", Direction::Output), "A workspace containing the masked spectra as zeroes and ones."); @@ -62,26 +63,21 @@ void ExtractMask::exec() { // Create a new workspace for the results, copy from the input to ensure // that we copy over the instrument and current masking - auto maskWS = std::make_shared(inputWS); - maskWS->setTitle(inputWS->getTitle()); + std::shared_ptr maskWS; + if (getProperty("UngroupDetectors")) + maskWS = std::make_shared(inputWS->getInstrument()); + else + maskWS = std::make_shared(inputWS); - const auto &spectrumInfo = inputWS->spectrumInfo(); - const auto nHist = static_cast(inputWS->getNumberHistograms()); - Progress prog(this, 0.0, 1.0, nHist); + maskWS->setTitle(inputWS->getTitle()); - PARALLEL_FOR_IF(Kernel::threadSafe(*inputWS, *maskWS)) - for (int64_t i = 0; i < nHist; ++i) { - PARALLEL_START_INTERRUPT_REGION - bool inputIsMasked(false); - if (spectrumInfo.hasDetectors(i)) { - // special workspaces can mysteriously have the mask bit set - inputIsMasked = (inputWSIsSpecial && inputMaskWS->isMaskedIndex(i)) || spectrumInfo.isMasked(i); + // set mask from from detectorList + for (auto detectorID : detectorList) + try { + maskWS->setMasked(detectorID); + } catch (std::invalid_argument const &) { + g_log.warning() << "Detector ID = " << detectorID << " is masked but does not exist in any output spectra\n "; } - maskWS->setMaskedIndex(i, inputIsMasked); - prog.report(); - PARALLEL_END_INTERRUPT_REGION - } - PARALLEL_CHECK_INTERRUPT_REGION g_log.information() << maskWS->getNumberMasked() << " spectra are masked\n"; g_log.information() << detectorList.size() << " detectors are masked\n"; diff --git a/Framework/Algorithms/test/ExtractMaskTest.h b/Framework/Algorithms/test/ExtractMaskTest.h index 1e8aa7c7283d..2dffe4e72b76 100644 --- a/Framework/Algorithms/test/ExtractMaskTest.h +++ b/Framework/Algorithms/test/ExtractMaskTest.h @@ -6,6 +6,7 @@ // SPDX - License - Identifier: GPL - 3.0 + #pragma once +#include "MantidAPI/AlgorithmFactory.h" #include "MantidAPI/SpectrumInfo.h" #include "MantidAlgorithms/ExtractMask.h" #include "MantidDataObjects/MaskWorkspace.h" @@ -25,10 +26,11 @@ class ExtractMaskTest : public CxxTest::TestSuite { ExtractMask maskExtractor; maskExtractor.initialize(); std::vector properties = maskExtractor.getProperties(); - TS_ASSERT_EQUALS(properties.size(), 3); - if (properties.size() == 3) { + TS_ASSERT_EQUALS(properties.size(), 4); + if (properties.size() == 4) { TS_ASSERT_EQUALS(properties[0]->name(), "InputWorkspace"); - TS_ASSERT_EQUALS(properties[1]->name(), "OutputWorkspace"); + TS_ASSERT_EQUALS(properties[1]->name(), "UngroupDetectors"); + TS_ASSERT_EQUALS(properties[2]->name(), "OutputWorkspace"); } } @@ -117,12 +119,69 @@ class ExtractMaskTest : public CxxTest::TestSuite { AnalysisDataService::Instance().remove(inputName); } + void test_ungroup_detectors() { + // Create a simple test workspace with grouped detectors + const std::string inputName("inputWS"); + auto createWS = AlgorithmFactory::Instance().create("CreateSampleWorkspace", -1); + createWS->initialize(); + createWS->setProperty("NumBanks", 4); + createWS->setProperty("BankPixelWidth", 2); + createWS->setPropertyValue("OutputWorkspace", inputName); + createWS->execute(); + + const std::string groupName("groupWS"); + auto createGroupWS = AlgorithmFactory::Instance().create("CreateGroupingWorkspace", -1); + createGroupWS->initialize(); + createGroupWS->setPropertyValue("InputWorkspace", inputName); + createGroupWS->setPropertyValue("GroupDetectorsBy", "bank"); + createGroupWS->setPropertyValue("OutputWorkspace", groupName); + createGroupWS->execute(); + + auto groupWS = AlgorithmFactory::Instance().create("GroupDetectors", -1); + groupWS->initialize(); + groupWS->setPropertyValue("InputWorkspace", inputName); + groupWS->setPropertyValue("CopyGroupingFromWorkspace", groupName); + groupWS->setPropertyValue("OutputWorkspace", inputName); + groupWS->execute(); + + // mask spectra 0 and 2 which will be detectors 1-4 and 9-12 + auto mask = AlgorithmFactory::Instance().create("MaskDetectors", -1); + mask->initialize(); + mask->setPropertyValue("Workspace", inputName); + mask->setPropertyValue("WorkspaceIndexList", "0,2"); + mask->execute(); + + auto inputWS = AnalysisDataService::Instance().retrieveWS(inputName); + TS_ASSERT_EQUALS(inputWS->getNumberHistograms(), 4); + + MaskWorkspace_sptr outputWS; + TS_ASSERT_THROWS_NOTHING(outputWS = runExtractMask(inputName, true)); + TS_ASSERT(outputWS); + if (outputWS) { + TS_ASSERT_EQUALS(outputWS->getNumberHistograms(), 16); + TS_ASSERT_EQUALS(outputWS->getNumberMasked(), 8); + for (size_t i = 0; i < 4; ++i) + TS_ASSERT_EQUALS(outputWS->isMaskedIndex(i), true); + for (size_t i = 4; i < 8; ++i) + TS_ASSERT_EQUALS(outputWS->isMaskedIndex(i), false); + for (size_t i = 8; i < 12; ++i) + TS_ASSERT_EQUALS(outputWS->isMaskedIndex(i), true); + for (size_t i = 12; i < 16; ++i) + TS_ASSERT_EQUALS(outputWS->isMaskedIndex(i), false); + } + + AnalysisDataService::Instance().remove(inputName); + AnalysisDataService::Instance().remove(groupName); + AnalysisDataService::Instance().remove(outputWS->getName()); + } + private: // The input workspace should be in the analysis data service - MaskWorkspace_sptr runExtractMask(const std::string &inputName) { + MaskWorkspace_sptr runExtractMask(const std::string &inputName, const bool ungroupDetectors = false) { ExtractMask maskExtractor; maskExtractor.initialize(); maskExtractor.setPropertyValue("InputWorkspace", inputName); + maskExtractor.setProperty("UngroupDetectors", ungroupDetectors); const std::string outputName("masking"); maskExtractor.setPropertyValue("OutputWorkspace", outputName); maskExtractor.setRethrows(true); diff --git a/docs/source/algorithms/ExtractMask-v1.rst b/docs/source/algorithms/ExtractMask-v1.rst index fe2ec8f9976f..5f39f6653099 100644 --- a/docs/source/algorithms/ExtractMask-v1.rst +++ b/docs/source/algorithms/ExtractMask-v1.rst @@ -21,6 +21,11 @@ link is preserved so that the instrument view functions correctly. A list of masked detector IDs is also output. Note this contains the detector IDs which are masked rather than the index or spectrum number. +Ungroup Detectors +----------------- + +If ``UngroupDetectors`` is set to True, the detector IDs are ungrouped. This means that if the input workspace has a grouped detector, the output workspace will have a single spectra for each detector. + Usage ----- diff --git a/docs/source/release/v6.12.0/Framework/Algorithms/New_features/38198.rst b/docs/source/release/v6.12.0/Framework/Algorithms/New_features/38198.rst new file mode 100644 index 000000000000..89939a4fcff1 --- /dev/null +++ b/docs/source/release/v6.12.0/Framework/Algorithms/New_features/38198.rst @@ -0,0 +1 @@ +- A new property ``UngroupDetectors`` was added to :ref:`ExtractMask ` allowing the output ``MaskWorkspace`` to expand the spectra to individal detectors. \ No newline at end of file