Skip to content

Commit

Permalink
Merge pull request #38198 from rosswhitfield/ExtractMaskDonor
Browse files Browse the repository at this point in the history
Add UngroupDetectors to ExtractMask
  • Loading branch information
KedoKudo authored Oct 21, 2024
2 parents beabba3 + 76f1984 commit 7fa6b03
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 21 deletions.
30 changes: 13 additions & 17 deletions Framework/Algorithms/src/ExtractMask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ using namespace Kernel;
void ExtractMask::init() {
declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("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<WorkspaceProperty<MatrixWorkspace>>("OutputWorkspace", "", Direction::Output),
"A workspace containing the masked spectra as zeroes and ones.");

Expand Down Expand Up @@ -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<DataObjects::MaskWorkspace>(inputWS);
maskWS->setTitle(inputWS->getTitle());
std::shared_ptr<DataObjects::MaskWorkspace> maskWS;
if (getProperty("UngroupDetectors"))
maskWS = std::make_shared<DataObjects::MaskWorkspace>(inputWS->getInstrument());
else
maskWS = std::make_shared<DataObjects::MaskWorkspace>(inputWS);

const auto &spectrumInfo = inputWS->spectrumInfo();
const auto nHist = static_cast<int64_t>(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";
Expand Down
67 changes: 63 additions & 4 deletions Framework/Algorithms/test/ExtractMaskTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -25,10 +26,11 @@ class ExtractMaskTest : public CxxTest::TestSuite {
ExtractMask maskExtractor;
maskExtractor.initialize();
std::vector<Property *> 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");
}
}

Expand Down Expand Up @@ -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<MatrixWorkspace>(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);
Expand Down
5 changes: 5 additions & 0 deletions docs/source/algorithms/ExtractMask-v1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
-----

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- A new property ``UngroupDetectors`` was added to :ref:`ExtractMask <algm-ExtractMask>` allowing the output ``MaskWorkspace`` to expand the spectra to individal detectors.

0 comments on commit 7fa6b03

Please sign in to comment.