Mantid
Loading...
Searching...
No Matches
MaskDetectorsIf.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 +
15
16#include <fstream>
17#include <iomanip>
18#include <numeric>
19
20namespace Mantid::Algorithms {
21
22// Register the class into the algorithm factory
23DECLARE_ALGORITHM(MaskDetectorsIf)
24
25using namespace Kernel;
26
27// anonymous namespace
28namespace {
32template <class T> struct not_finite {
35
36 constexpr bool operator()(const T &value, const T &ignored) const {
37 UNUSED_ARG(ignored);
38 return !std::isfinite(value);
39 };
40};
41} // namespace
42
46 using namespace Mantid::Kernel;
47 declareProperty(std::make_unique<API::WorkspaceProperty<>>("InputWorkspace", "", Direction::Input),
48 "A 1D Workspace that contains values to select against");
49 const std::vector<std::string> select_mode{"SelectIf", "DeselectIf"};
50 declareProperty("Mode", "SelectIf", std::make_shared<StringListValidator>(select_mode),
51 "Mode to select or deselect detectors based on comparison with values.");
52 const std::vector<std::string> select_operator{"Equal", "NotEqual", "Greater", "GreaterEqual",
53 "Less", "LessEqual", "NotFinite"};
54 declareProperty("Operator", "Equal", std::make_shared<StringListValidator>(select_operator),
55 "Operator to compare to given values.");
56 declareProperty("Value", 0.0);
57 auto positiveIntValidator = std::make_shared<BoundedValidator<int>>();
58 positiveIntValidator->setLower(0);
60 std::make_unique<PropertyWithValue<int>>("StartWorkspaceIndex", 0, positiveIntValidator, Direction::Input),
61 "The start of the spectrum range on which to apply the mask");
62 declareProperty(std::make_unique<PropertyWithValue<int>>("EndWorkspaceIndex", EMPTY_INT(), positiveIntValidator,
64 "The end of the spectrum range on which to apply the mask.");
65 declareProperty(std::make_unique<API::FileProperty>("InputCalFile", "", API::FileProperty::OptionalLoad, ".cal"),
66 "The name of the CalFile with grouping data.");
67 declareProperty(std::make_unique<API::FileProperty>("OutputCalFile", "", API::FileProperty::OptionalSave, ".cal"),
68 "The name of the CalFile with grouping data.");
70 std::make_unique<API::WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output, API::PropertyMode::Optional),
71 "The masked workspace.");
72}
73
78std::map<std::string, std::string> MaskDetectorsIf::validateInputs() {
79 std::map<std::string, std::string> issues;
80 const auto noInputFile = isDefault("InputCalFile");
81 const auto noOutputFile = isDefault("OutputCalFile");
82 if (!noInputFile && noOutputFile) {
83 issues["OutputCalFile"] = "Output file name is missing.";
84 } else if (noInputFile && !noOutputFile) {
85 issues["InputCalFile"] = "Input file name is missing.";
86 }
87 if (!isDefault("EndWorkspaceIndex")) {
88 const int nspec_start = getProperty("StartWorkspaceIndex");
89 const int nspec_end = getProperty("EndWorkspaceIndex");
90 if (nspec_end < nspec_start) {
91 issues["EndWorkspaceIndex"] =
92 "EndWorkspaceIndex should be more than StartWorkspaceIndex. Specify a value greater than " +
93 std::to_string(nspec_start) + ".\n";
94 }
95 }
96 return issues;
97}
98
103
104 if (isDefault("InputCalFile") && isDefault("OutputWorkspace")) {
105 g_log.error() << "No InputCalFle or OutputWorkspace specified; " << this->name() << " will do nothing.\n";
106 return;
107 }
108 for (int i = m_start_ix; i <= m_end_ix; ++i) {
109 // Get the list of udets contributing to this spectra
110 const auto &dets = m_inputW->getSpectrum(i).getDetectorIDs();
111
112 if (dets.empty())
113 continue;
114 else {
115 const size_t num_bins = m_inputW->y(i).size();
116 for (size_t j = 0; j < num_bins; ++j) {
117 const double val = m_inputW->y(i)[j];
118 if (m_compar_f(val, m_value)) {
119 for (const auto det : dets) {
120 m_umap.emplace(det, m_select_on);
121 }
122 // stop after the first bin matches the criteria
123 break;
124 }
125 }
126 }
127 const double p = static_cast<double>(i) / static_cast<double>(m_end_ix - m_start_ix);
128 progress(p, "Generating detector map");
129 }
130
131 if (!isDefault("InputCalFile")) {
133 }
134 if (!isDefault("OutputWorkspace")) {
136 }
137}
138
143 API::MatrixWorkspace_sptr outputW = getProperty("OutputWorkspace");
144 if (outputW != m_inputW)
145 outputW = m_inputW->clone();
146 auto &detectorInfo = outputW->mutableDetectorInfo();
147 for (const auto &selection : m_umap) {
148 detectorInfo.setMasked(detectorInfo.indexOf(selection.first), selection.second);
149 }
150
151 const auto &spectrumInfo = outputW->spectrumInfo();
152 for (size_t i = 0; i < spectrumInfo.size(); ++i) {
153 if (spectrumInfo.hasDetectors(i) && spectrumInfo.isMasked(i))
154 outputW->getSpectrum(i).clearData();
155 }
156
157 if (const auto *event = dynamic_cast<DataObjects::EventWorkspace *>(outputW.get()))
158 event->clearMRU();
159
160 setProperty("OutputWorkspace", outputW);
161}
166 m_inputW = getProperty("InputWorkspace");
167 m_value = getProperty("Value");
168
169 // Get the selction mode (select if or deselect if)
170 std::string select_mode = getProperty("Mode");
171 if (select_mode == "SelectIf")
172 m_select_on = true;
173 else
174 m_select_on = false;
175
176 // Select function object based on the type of comparison operator
177 std::string select_operator = getProperty("Operator");
178
179 if (select_operator == "LessEqual")
180 m_compar_f = std::less_equal<double>();
181 else if (select_operator == "Less")
182 m_compar_f = std::less<double>();
183 else if (select_operator == "GreaterEqual")
184 m_compar_f = std::greater_equal<double>();
185 else if (select_operator == "Greater")
186 m_compar_f = std::greater<double>();
187 else if (select_operator == "Equal")
188 m_compar_f = std::equal_to<double>();
189 else if (select_operator == "NotEqual")
190 m_compar_f = std::not_equal_to<double>();
191 else if (select_operator == "NotFinite")
192 m_compar_f = not_finite<double>();
193
195}
196
202 int nspec = static_cast<int>(m_inputW->getNumberHistograms());
203 m_start_ix = getProperty("StartWorkspaceIndex");
204 if (m_start_ix > nspec - 2) {
205 throw std::invalid_argument("StartWorkspaceIndex should be greater than or equal to 0 and less than " +
206 std::to_string(nspec - 1) + ". Value provided is invalid.");
207 }
208 if (isDefault("EndWorkspaceIndex")) {
209 m_end_ix = nspec - 1;
210 } else {
211 int end_ix = getProperty("EndWorkspaceIndex");
212 if (end_ix > nspec - 1) {
213 throw std::invalid_argument("EndWorkspaceIndex should be greater than 0 and less than " + std::to_string(nspec) +
214 ". Value provided is invalid.");
215 } else {
216 m_end_ix = end_ix;
217 }
218 }
219}
220
227 const std::string oldfile = getProperty("InputCalFile");
228 const std::string newfile = getProperty("OutputCalFile");
229 progress(0.99, "Creating new cal file");
230 std::ifstream oldf(oldfile.c_str());
231 if (!oldf.is_open()) {
232 g_log.error() << "Unable to open grouping file " << oldfile << '\n';
233 throw Exception::FileError("Error reading .cal file", oldfile);
234 }
235 std::ofstream newf(newfile.c_str());
236 if (!newf.is_open()) {
237 g_log.error() << "Unable to open grouping file " << newfile << '\n';
238 throw Exception::FileError("Error reading .cal file", newfile);
239 }
240 std::string str;
241 while (getline(oldf, str)) {
242 // Comment or empty lines get copied into the new cal file
243 if (str.empty() || str[0] == '#') {
244 newf << str << '\n';
245 continue;
246 }
247 std::istringstream istr(str);
248 int n, udet, sel, group;
249 double offset;
250 istr >> n >> udet >> offset >> sel >> group;
251 const auto it = m_umap.find(udet);
252 bool selection;
253
254 if (it == m_umap.end())
255 selection = sel != 0;
256 else
257 selection = (*it).second;
258
259 newf << std::fixed << std::setw(9) << n << std::fixed << std::setw(15) << udet << std::fixed << std::setprecision(7)
260 << std::setw(15) << offset << std::fixed << std::setw(8) << selection << std::fixed << std::setw(8) << group
261 << '\n';
262 }
263 oldf.close();
264 newf.close();
265}
266} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
double value
The value of the point.
Definition FitMW.cpp:51
T first_argument_type
T second_argument_type
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:48
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.
Kernel::Logger & g_log
Definition Algorithm.h:422
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
bool isDefault(const std::string &name) const
@ OptionalSave
to specify a file to write to but an empty string is
@ OptionalLoad
to specify a file to read but the file doesn't have to exist
A property class for workspaces.
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
std::map< std::string, std::string > validateInputs() override
Validates the algorithm's input properties.
boost::function< bool(double, double)> m_compar_f
A comparator function.
void init() override
Initialisation method.
API::MatrixWorkspace_const_sptr m_inputW
The input workspace.
int m_end_ix
The end index parameter.
void retrieveProperties()
Get the input properties and store them in the object variables.
void validateAndSetIxProperties()
Execution code.
void createNewCalFile()
Create a new cal file based on the old file.
int m_start_ix
The start index parameter.
bool m_select_on
Whether select is on or off.
void outputToWorkspace()
Create an output workspace masking/unmasking the selected/deselected spectra.
udet2valuem m_umap
A map from detid to selection.
void exec() override
Executes the algorithm.
double m_value
The Value parameter.
This class is intended to fulfill the design specified in <https://github.com/mantidproject/documents...
Records the filename and the description of failure.
Definition Exception.h:98
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
The concrete, templated class for properties.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition EmptyValues.h:24
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54