Mantid
Loading...
Searching...
No Matches
PDDetermineCharacterizations.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 +
10#include "MantidAPI/Run.h"
17
18namespace Mantid::Algorithms {
19
27
28namespace { // anonymous namespace
29const std::string CHAR_PROP_NAME("Characterizations");
30const std::string FREQ_PROP_NAME("FrequencyLogNames");
31const std::string WL_PROP_NAME("WaveLengthLogNames");
32} // namespace
33
34// Register the algorithm into the AlgorithmFactory
35DECLARE_ALGORITHM(PDDetermineCharacterizations)
36
37
38const std::string PDDetermineCharacterizations::name() const { return "PDDetermineCharacterizations"; }
39
42
44const std::string PDDetermineCharacterizations::category() const {
45 return "Workflow\\Diffraction\\UsesPropertyManager";
46}
47
49const std::string PDDetermineCharacterizations::summary() const {
50 return "Determines the characterizations of a workspace.";
51}
52
70std::vector<std::string> getColumnNames() {
71 return {"frequency", "wavelength", "bank", "container", "vanadium", "vanadium_background",
72 "empty_environment", "empty_instrument", "d_min", "d_max", "tof_min", "tof_max",
73 "wavelength_min", "wavelength_max"};
74}
75
77std::map<std::string, std::string> PDDetermineCharacterizations::validateInputs() {
78 std::map<std::string, std::string> result;
79
80 ITableWorkspace_const_sptr characterizations = getProperty(CHAR_PROP_NAME);
81
82 if (!bool(characterizations))
83 return result;
84
85 std::vector<std::string> expectedNames = getColumnNames();
86 std::vector<std::string> names = characterizations->getColumnNames();
87 if (names.size() < expectedNames.size()) { // allow for extra columns
88 std::stringstream msg;
89 msg << "Encountered invalid number of columns in "
90 << "TableWorkspace. Found " << names.size() << " expected " << expectedNames.size();
91 result[CHAR_PROP_NAME] = msg.str();
92 } else {
93 for (auto &expectedName : expectedNames) {
94 if (std::find(names.begin(), names.end(), expectedName) == names.end()) {
95 std::stringstream msg;
96 msg << "Failed to find column named " << expectedName;
97 result[CHAR_PROP_NAME] = msg.str();
98 }
99 }
100 }
101 return result;
102}
103
107 std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input, API::PropertyMode::Optional),
108 "Workspace with logs to help identify frequency and wavelength");
109
112 "Table of characterization information");
113
114 declareProperty("ReductionProperties", "__pd_reduction_properties", "Property manager name for the reduction");
115
116 const std::string defaultMsg = " run to use. 0 to use value in table, -1 to not use.";
117
118 declareProperty(std::make_unique<Kernel::ArrayProperty<int32_t>>("BackRun", "0"), "Empty container" + defaultMsg);
119 declareProperty(std::make_unique<Kernel::ArrayProperty<int32_t>>("NormRun", "0"), "Normalization" + defaultMsg);
120 declareProperty(std::make_unique<Kernel::ArrayProperty<int32_t>>("NormBackRun", "0"),
121 "Normalization background" + defaultMsg);
122 declareProperty(std::make_unique<Kernel::ArrayProperty<int32_t>>("EmptyEnv", "0"),
123 "Empty sample environment" + defaultMsg);
124 declareProperty(std::make_unique<Kernel::ArrayProperty<int32_t>>("EmptyInstr", "0"), "Empty instrument" + defaultMsg);
125
126 std::vector<std::string> defaultFrequencyNames{"SpeedRequest1", "Speed1", "frequency", "skf1.speed"};
128 std::make_unique<Kernel::ArrayProperty<std::string>>(FREQ_PROP_NAME, std::move(defaultFrequencyNames)),
129 "Candidate log names for frequency");
130 // NOTE: beamline specific log names goes to the end of the list
131 std::vector<std::string> defaultWavelengthNames{"LambdaRequest", "lambda", "skf12.lambda", "BL1B:Det:TH:BL:Lambda",
132 "freq"};
133 declareProperty(std::make_unique<Kernel::ArrayProperty<std::string>>(WL_PROP_NAME, std::move(defaultWavelengthNames)),
134 "Candidate log names for wave length");
135}
136
143bool closeEnough(const double left, const double right) {
144 // the same value
145 const double diff = fabs(left - right);
146 if (diff == 0.)
147 return true;
148
149 // same within 5%
150 const double relativeDiff = diff * 2 / (left + right);
151 return relativeDiff < .05;
152}
153
155void PDDetermineCharacterizations::getInformationFromTable(const double frequency, const double wavelength,
156 const std::string &canName) {
157 size_t numRows = m_characterizations->rowCount();
158
159 for (size_t i = 0; i < numRows; ++i) {
160 const double rowFrequency = m_characterizations->getRef<double>("frequency", i);
161 const double rowWavelength = m_characterizations->getRef<double>("wavelength", i);
162
163 if (closeEnough(frequency, rowFrequency) && closeEnough(wavelength, rowWavelength)) {
164
165 // declare how the row was chosen
166 g_log.information() << "Using information from row " << i << " with frequency = " << rowFrequency
167 << " and wavelength = " << rowWavelength << "\n";
168 m_propertyManager->setProperty("frequency", frequency);
169 m_propertyManager->setProperty("wavelength", wavelength);
170
171 // what bank number this should be called - only used at POWGEN
172 m_propertyManager->setProperty("bank", m_characterizations->getRef<int>("bank", i));
173
174 // data ranges
175 m_propertyManager->setPropertyValue("d_min", m_characterizations->getRef<std::string>("d_min", i));
176 m_propertyManager->setPropertyValue("d_max", m_characterizations->getRef<std::string>("d_max", i));
177 m_propertyManager->setProperty("tof_min", m_characterizations->getRef<double>("tof_min", i));
178 m_propertyManager->setProperty("tof_max", m_characterizations->getRef<double>("tof_max", i));
179 m_propertyManager->setProperty("wavelength_min", m_characterizations->getRef<double>("wavelength_min", i));
180 m_propertyManager->setProperty("wavelength_max", m_characterizations->getRef<double>("wavelength_max", i));
181
182 // characterization run numbers
183 m_propertyManager->setProperty("vanadium", m_characterizations->getRef<std::string>("vanadium", i));
184 m_propertyManager->setProperty("vanadium_background",
185 m_characterizations->getRef<std::string>("vanadium_background", i));
186 m_propertyManager->setProperty("container", m_characterizations->getRef<std::string>("container", i));
187 m_propertyManager->setProperty("empty_environment",
188 m_characterizations->getRef<std::string>("empty_environment", i));
189 m_propertyManager->setProperty("empty_instrument",
190 m_characterizations->getRef<std::string>("empty_instrument", i));
191
192 // something special if the container was specified
193 if (!canName.empty()) {
194 const auto columnNames = m_characterizations->getColumnNames();
195 if (std::find(columnNames.begin(), columnNames.end(), canName) == columnNames.end()) {
196 g_log.warning() << "Failed to find container name \"" << canName << "\" in characterizations table \""
197 << m_characterizations->getName() << " - using default container value\n";
198 } else {
199 const auto canRuns = m_characterizations->getRef<std::string>(canName, i);
200 g_log.information() << "Updating container identifier to \"" << canRuns << "\"\n";
201 m_propertyManager->setProperty("container", canRuns);
202 }
203 }
204
205 return;
206 }
207 }
208 g_log.warning("Failed to find compatible row in characterizations table");
209}
210
217double PDDetermineCharacterizations::getLogValue(const API::Run &run, const std::string &propName) {
218 std::vector<std::string> names = getProperty(propName);
219
220 std::string label = "frequency";
221 if (propName == WL_PROP_NAME)
222 label = "wavelength";
223
224 std::unordered_set<std::string> validUnits;
225 if (propName == WL_PROP_NAME) {
226 validUnits.insert("Angstrom");
227 validUnits.insert("A");
228 } else {
229 validUnits.insert("Hz");
230 }
231
232 for (auto &name : names) {
233 if (run.hasProperty(name)) {
234 const std::string units = run.getProperty(name)->units();
235
236 if (validUnits.find(units) != validUnits.end()) {
238 if (value == 0.) {
239 std::stringstream msg;
240 msg << "'" << name << "' has a mean value of zero " << units;
241 g_log.information(msg.str());
242 } else {
243 std::stringstream msg;
244 msg << "Found " << label << " in log '" << name << "' with mean value " << value << " " << units;
245 g_log.information(msg.str());
246 return value;
247 }
248 } else {
249 std::stringstream msg;
250 msg << "When looking at " << name << " log encountered unknown units '" << units << "' for " << label << ":"
251 << units;
252 g_log.warning(msg.str());
253 }
254 }
255 }
256
257 // generate an exception if it gets here because the log wasn't found
258 std::stringstream msg;
259 msg << "Failed to determine " << label << " because none of the logs ";
260 for (auto &name : names) {
261 msg << "\"" << name << "\" ";
262 }
263 msg << "exist";
264 throw std::runtime_error(msg.str());
265}
266
269 if (!m_propertyManager->existsProperty("frequency")) {
270 m_propertyManager->declareProperty(std::make_unique<PropertyWithValue<double>>("frequency", 0.));
271 }
272 if (!m_propertyManager->existsProperty("wavelength")) {
273 m_propertyManager->declareProperty(std::make_unique<PropertyWithValue<double>>("wavelength", 0.));
274 }
275
276 if (!m_propertyManager->existsProperty("bank")) {
277 m_propertyManager->declareProperty(std::make_unique<PropertyWithValue<int>>("bank", 1));
278 }
279
280 if (!m_propertyManager->existsProperty("d_min")) {
281 m_propertyManager->declareProperty(std::make_unique<ArrayProperty<double>>("d_min"));
282 }
283 if (!m_propertyManager->existsProperty("d_max")) {
284 m_propertyManager->declareProperty(std::make_unique<ArrayProperty<double>>("d_max"));
285 }
286 if (!m_propertyManager->existsProperty("tof_min")) {
287 m_propertyManager->declareProperty(std::make_unique<PropertyWithValue<double>>("tof_min", 0.));
288 }
289 if (!m_propertyManager->existsProperty("tof_max")) {
290 m_propertyManager->declareProperty(std::make_unique<PropertyWithValue<double>>("tof_max", 0.));
291 }
292 if (!m_propertyManager->existsProperty("wavelength_min")) {
293 m_propertyManager->declareProperty(std::make_unique<PropertyWithValue<double>>("wavelength_min", 0.));
294 }
295 if (!m_propertyManager->existsProperty("wavelength_max")) {
296 m_propertyManager->declareProperty(std::make_unique<PropertyWithValue<double>>("wavelength_max", 0.));
297 }
298
299 if (!m_propertyManager->existsProperty("vanadium")) {
300 m_propertyManager->declareProperty(std::make_unique<ArrayProperty<int32_t>>("vanadium", "0"));
301 }
302 if (!m_propertyManager->existsProperty("vanadium_background")) {
303 m_propertyManager->declareProperty(std::make_unique<ArrayProperty<int32_t>>("vanadium_background", "0"));
304 }
305 if (!m_propertyManager->existsProperty("container")) {
306 m_propertyManager->declareProperty(std::make_unique<ArrayProperty<int32_t>>("container", "0"));
307 }
308 if (!m_propertyManager->existsProperty("empty_environment")) {
309 m_propertyManager->declareProperty(std::make_unique<ArrayProperty<int32_t>>("empty_environment", "0"));
310 }
311 if (!m_propertyManager->existsProperty("empty_instrument")) {
312 m_propertyManager->declareProperty(std::make_unique<ArrayProperty<int32_t>>("empty_instrument", "0"));
313 }
314}
315
321void PDDetermineCharacterizations::overrideRunNumProperty(const std::string &inputName, const std::string &propName) {
322 if (this->isDefault(inputName))
323 return;
324
325 std::vector<int32_t> runnumbers = this->getProperty(inputName);
326 if ((!runnumbers.empty()) && (runnumbers[0] != 0)) {
327 if (runnumbers[0] < 0) {
328 runnumbers.erase(runnumbers.begin(), runnumbers.end());
329 runnumbers.emplace_back(0);
330 }
331 m_propertyManager->setProperty(propName, runnumbers);
332 }
333}
334
337 // setup property manager to return
338 const std::string managerName = getPropertyValue("ReductionProperties");
339 if (PropertyManagerDataService::Instance().doesExist(managerName)) {
341 } else {
342 m_propertyManager = std::make_shared<Kernel::PropertyManager>();
343 PropertyManagerDataService::Instance().addOrReplace(managerName, m_propertyManager);
344 }
345
347
348 m_characterizations = getProperty(CHAR_PROP_NAME);
349 if (bool(m_characterizations) && (m_characterizations->rowCount() > 0)) {
350 API::MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
351 auto run = inputWS->mutableRun();
352
353 double frequency = getLogValue(run, FREQ_PROP_NAME);
354
355 double wavelength = getLogValue(run, WL_PROP_NAME);
356
357 // determine the container name
358 std::string container;
359 if (run.hasProperty("SampleContainer")) {
360 const auto containerProp = run.getLogData("SampleContainer");
361
362 // the property is normally a TimeSeriesProperty
363 const auto containerPropSeries = dynamic_cast<TimeSeriesProperty<std::string> *>(containerProp);
364 if (containerPropSeries) {
365 // assume that only the first value matters
366 container = containerPropSeries->valuesAsVector().front();
367 } else {
368 // try as a normal Property
369 container = containerProp->value();
370 }
371
372 // remove whitespace from the value
373 container = Kernel::Strings::replaceAll(container, " ", "");
374 }
375
376 getInformationFromTable(frequency, wavelength, container);
377 }
378
379 overrideRunNumProperty("BackRun", "container");
380 overrideRunNumProperty("NormRun", "vanadium");
381 overrideRunNumProperty("NormBackRun", "vanadium_background");
382 overrideRunNumProperty("EmptyEnv", "empty_environment");
383 overrideRunNumProperty("EmptyInstr", "empty_instrument");
384
385 std::vector<std::string> expectedNames = getColumnNames();
386 for (auto &expectedName : expectedNames) {
387 if (m_propertyManager->existsProperty(expectedName)) {
388 g_log.debug() << expectedName << ":" << m_propertyManager->getPropertyValue(expectedName) << "\n";
389 } else {
390 g_log.warning() << expectedName << " DOES NOT EXIST\n";
391 }
392 }
393}
394
395} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
double value
The value of the point.
Definition: FitMW.cpp:51
double left
Definition: LineProfile.cpp:80
double right
Definition: LineProfile.cpp:81
#define fabs(x)
Definition: Matrix.cpp:22
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Kernel::Logger & g_log
Definition: Algorithm.h:451
bool isDefault(const std::string &name) const
Definition: Algorithm.cpp:2084
bool hasProperty(const std::string &name) const
Does the property exist on the object.
Definition: LogManager.cpp:265
Kernel::Property * getProperty(const std::string &name) const
Returns the named property as a pointer.
Definition: LogManager.cpp:404
double getLogAsSingleValue(const std::string &name, Kernel::Math::StatisticType statistic=Kernel::Math::Mean) const
Definition: LogManager.h:149
This class stores information regarding an experimental run as a series of log entries.
Definition: Run.h:38
A property class for workspaces.
void getInformationFromTable(const double frequency, const double wavelength, const std::string &canName)
Fill in the property manager from the correct line in the table.
const std::string category() const override
Algorithm's category for identification.
void overrideRunNumProperty(const std::string &inputName, const std::string &propName)
Set the run number in the property manager from algoritm inputs.
double getLogValue(const API::Run &run, const std::string &propName)
Get a value from one of a set of logs.
const std::string name() const override
Algorithms name for identification.
std::map< std::string, std::string > validateInputs() override
More intesive input checking.
void init() override
Initialize the algorithm's properties.
int version() const override
Algorithm's version for identification.
void setDefaultsInPropManager()
Set the default values in the property manager.
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
The concrete, templated class for properties.
virtual const std::string & units() const
Returns the units of the property, if any, as a string.
Definition: Property.cpp:179
Manage the lifetime of a class intended to be a singleton.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
A specialised Property class for holding a series of time-value pairs.
std::vector< TYPE > valuesAsVector() const
Return the time series's values (unfiltered) as a vector<TYPE>
std::shared_ptr< const ITableWorkspace > ITableWorkspace_const_sptr
shared pointer to Mantid::API::ITableWorkspace (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::vector< std::string > getColumnNames()
These should match those in LoadPDCharacterizations.
bool closeEnough(const double left, const double right)
Compare two numbers to be in agreement within 5%.
MANTID_KERNEL_DLL std::string replaceAll(const std::string &input, const std::string &charStr, const std::string &substitute)
Return a string with all occurrences of the characters in the input replaced by the replace string.
Definition: Strings.cpp:94
STL namespace.
Describes the direction (within an algorithm) of a Property.
Definition: Property.h:50
@ Input
An input workspace.
Definition: Property.h:53