Mantid
Loading...
Searching...
No Matches
SampleLogsBehaviour.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 +
7#include <utility>
8
10#include "MantidAPI/Run.h"
14#include "MantidKernel/Logger.h"
19
20namespace Mantid::Algorithms {
21
22using namespace Kernel;
23using namespace API;
24
25namespace {
26std::string generateDifferenceMessage(const std::string &item, const std::string &wsName, const std::string &wsValue,
27 const std::string &firstValue) {
28 std::stringstream stringstream;
29 stringstream << "Item \"" << item << "\" has different values in workspaces! Found: " << wsValue << " in workspace "
30 << wsName << " but the value in the first workspace was: " << firstValue << "." << std::endl;
31 return stringstream.str();
32}
33} // namespace
34
35// Names and docs from the properties allowing to override the default (IPF
36// controlled) merging behaviour.
37// These are common between e.g. MergeRuns and ConjoinXRuns.
38const std::string SampleLogsBehaviour::TIME_SERIES_PROP = "SampleLogsTimeSeries";
39const std::string SampleLogsBehaviour::TIME_SERIES_DOC = "A comma separated list of the sample logs to merge into a "
40 "time series. The initial times are taken as the start times "
41 "for the run. Sample logs must be numeric.";
42const std::string SampleLogsBehaviour::LIST_PROP = "SampleLogsList";
43const std::string SampleLogsBehaviour::LIST_DOC = "A comma separated list of the sample logs to merge into a "
44 "list.";
45const std::string SampleLogsBehaviour::WARN_PROP = "SampleLogsWarn";
46const std::string SampleLogsBehaviour::WARN_DOC = "A comma separated list of the sample "
47 "logs to generate a warning if "
48 "different when merging.";
49const std::string SampleLogsBehaviour::WARN_TOL_PROP = "SampleLogsWarnTolerances";
50const std::string SampleLogsBehaviour::WARN_TOL_DOC = "The tolerances for warning if sample logs are different. "
51 "Can either be empty for a comparison of the strings, a "
52 "single value for all warn sample logs, or a comma "
53 "separated list of values (must be the same length as "
54 "SampleLogsWarn).";
55const std::string SampleLogsBehaviour::FAIL_PROP = "SampleLogsFail";
56const std::string SampleLogsBehaviour::FAIL_DOC = "The sample logs to fail if different "
57 "when merging. If there is a "
58 "difference the run is skipped.";
59const std::string SampleLogsBehaviour::FAIL_TOL_PROP = "SampleLogsFailTolerances";
60const std::string SampleLogsBehaviour::FAIL_TOL_DOC = "The tolerances for failing if sample logs are different. "
61 "Can either be empty for a comparison of the strings, a "
62 "single value for all fail sample logs, or a comma "
63 "separated list of values (must be the same length as "
64 "SampleLogsFail).";
65const std::string SampleLogsBehaviour::SUM_PROP = "SampleLogsSum";
66const std::string SampleLogsBehaviour::SUM_DOC = "A comma separated list of the sample "
67 "logs to sum into a single entry. "
68 "Sample logs must be numeric.";
69
83 const SampleLogNames &logEntries, ParameterName parName)
84 : parameterNames(std::move(parName)), m_logger(logger) {
90
91 SampleLogsMap instrumentMap;
92 this->createSampleLogsMapsFromInstrumentParams(instrumentMap, *ws);
93
94 // This adds the parameters from the instrument to the main map, with any
95 // duplicates left as the versions in the MergeRuns arguments.
96 m_logMap.insert(instrumentMap.begin(), instrumentMap.end());
97}
98
107 std::string params = ws.getInstrument()->getParameterAsString(parameterNames.SUM_MERGE, false);
108 setSampleMap(map, MergeLogType::Sum, params, ws, "", true);
109
110 params = ws.getInstrument()->getParameterAsString(parameterNames.TIME_SERIES_MERGE, false);
111 setSampleMap(map, MergeLogType::TimeSeries, params, ws, "", true);
112
113 params = ws.getInstrument()->getParameterAsString(parameterNames.LIST_MERGE, false);
114 setSampleMap(map, MergeLogType::List, params, ws, "", true);
115
116 params = ws.getInstrument()->getParameterAsString(parameterNames.WARN_MERGE, false);
117 std::string paramsTolerances;
118 paramsTolerances = ws.getInstrument()->getParameterAsString(parameterNames.WARN_MERGE_TOLERANCES, false);
119 setSampleMap(map, MergeLogType::Warn, params, ws, paramsTolerances, true);
120
121 params = ws.getInstrument()->getParameterAsString(parameterNames.FAIL_MERGE, false);
122 paramsTolerances = ws.getInstrument()->getParameterAsString(parameterNames.FAIL_MERGE_TOLERANCES, false);
123 setSampleMap(map, MergeLogType::Fail, params, ws, paramsTolerances, true);
124}
125
142void SampleLogsBehaviour::setSampleMap(SampleLogsMap &map, const MergeLogType &mergeType, const std::string &params,
143 MatrixWorkspace &ws, const std::string &paramsTolerances,
144 bool skipIfInPrimaryMap) {
145
147 StringTokenizer tokenizerTolerances(paramsTolerances, ",",
149
150 auto tolerancesStringVector = tokenizerTolerances.asVector();
151
152 std::vector<double> tolerancesVector = createTolerancesVector(tokenizer.asVector().size(), tolerancesStringVector);
153
154 auto i = tokenizer.begin();
155 auto j = tolerancesVector.begin();
156
157 for (; i != tokenizer.end() && j != tolerancesVector.end(); ++i, ++j) {
158 auto item = *i;
159 auto tolerance = *j;
160
161 // Check 1: Does the key exist in the primary map? If so ignore it and
162 // continue.
163 if (skipIfInPrimaryMap && (m_logMap.count(SampleLogsKey(item, mergeType)) != 0)) {
164 continue;
165 }
166
167 // Check 2: If the key (sample log name) already exists in this map throw an
168 // error.
169 if (map.count(SampleLogsKey(item, mergeType)) != 0) {
170 throw std::invalid_argument("Error when making list of merge items, sample log \"" + item +
171 "\" defined more than once!");
172 }
173
174 // Check 3: If the sample log is one that should not be combined with
175 // others, check other incompatible sample logs do not exist too.
176 std::set<MergeLogType> uncombinableLogs = {MergeLogType::Sum, MergeLogType::TimeSeries, MergeLogType::List};
177 if (uncombinableLogs.count(mergeType) != 0) {
178 bool skipLog = false;
179
180 uncombinableLogs.erase(mergeType);
181 for (auto &logType : uncombinableLogs) {
182 if (map.count(SampleLogsKey(item, logType)) > 0)
183 throw std::invalid_argument("Error when making list of merge items, sample log " + item +
184 " being used for two incompatible merge types!");
185 if (skipIfInPrimaryMap && m_logMap.count(SampleLogsKey(item, logType)) > 0)
186 skipLog = true;
187 }
188
189 if (skipLog)
190 continue;
191 }
192
193 // Check 4: Does the sample log exist? If not log an error but continue.
194 std::shared_ptr<Property> prop;
195 try {
196 prop = std::shared_ptr<Property>(ws.getLog(item)->clone());
197 } catch (std::invalid_argument &) {
198 m_logger.error() << "Could not merge sample log \"" << item
199 << "\", does not exist in workspace! This sample log will be ignored." << std::endl;
200 continue;
201 }
202
203 // Check 5: Can the property be converted to a double? If not, and sum or
204 // time series case, log an error but continue.
205 bool isNumeric;
206 double value = 0.0;
207 isNumeric = setNumericValue(item, ws, value);
208 if (!isNumeric && (mergeType == MergeLogType::Sum || mergeType == MergeLogType::TimeSeries)) {
209 m_logger.error() << item
210 << " could not be converted to a numeric type. "
211 "This sample log will be ignored.\n"
212 << std::endl;
213 continue;
214 }
215
216 // For a TimeSeries or a List we need to add a new property to the workspace
217 if (mergeType == MergeLogType::TimeSeries) {
218 prop = addPropertyForTimeSeries(item, value, ws);
219 } else if (mergeType == MergeLogType::List) {
220 prop = addPropertyForList(item, prop->value(), ws);
221 }
222
223 // Finally add the key-value pair to the map
224 map[SampleLogsKey(item, mergeType)] = {prop, tolerance, isNumeric};
225 }
226}
227
239std::vector<double> SampleLogsBehaviour::createTolerancesVector(size_t numberNames,
240 const std::vector<std::string> &tolerances) {
241 size_t numberTolerances = tolerances.size();
242
243 std::vector<double> tolerancesVector(numberNames);
244
245 if (numberNames == numberTolerances && numberTolerances > 1) {
246 try {
247 std::transform(tolerances.begin(), tolerances.end(), tolerancesVector.begin(),
248 [](const std::string &val) { return std::stod(val); });
249 } catch (std::invalid_argument &) {
250 throw std::invalid_argument("Error when creating tolerances vector. "
251 "Please ensure each comma separated value is "
252 "numeric.");
253 } catch (std::out_of_range &) {
254 throw std::out_of_range("Error when creating tolerances vector. Please "
255 "ensure each comma separated value is within "
256 "double precision range.");
257 }
258 if (std::any_of(tolerancesVector.cbegin(), tolerancesVector.cend(), [](const auto value) { return value < 0.; })) {
259 throw std::out_of_range("Error when creating tolerances vector. Please "
260 "ensure all tolerance values are positive.");
261 }
262 } else if (tolerances.empty()) {
263 std::fill(tolerancesVector.begin(), tolerancesVector.end(), -1.0);
264 } else if (numberTolerances == 1) {
265 double value;
266 try {
267 value = std::stod(tolerances.front());
268 std::fill(tolerancesVector.begin(), tolerancesVector.end(), value);
269 } catch (std::invalid_argument &) {
270 throw std::invalid_argument("The single tolerance value requested can "
271 "not be converted to a number. Please ensure "
272 "it is a single number, or a comma separated "
273 "list of numbers.");
274 } catch (std::out_of_range &) {
275 throw std::out_of_range("The single tolerance value requested can not be "
276 "converted to a double. Please ensure tolerance "
277 "is within double precision range.");
278 }
279 if (value < 0)
280 throw std::out_of_range("The single tolerance value requested is "
281 "negative. Please ensure it is positive.");
282 } else {
283 throw std::invalid_argument("Invalid length of tolerances, found " + std::to_string(numberTolerances) +
284 " tolerance values but " + std::to_string(numberNames) + " names.");
285 }
286
287 return tolerancesVector;
288}
289
298std::shared_ptr<Property> SampleLogsBehaviour::addPropertyForTimeSeries(const std::string &item, const double value,
299 MatrixWorkspace &ws) {
300 std::shared_ptr<Property> returnProp;
301 const std::string originalUnit = ws.getLog(item)->units();
302 try {
303 // See if property exists as a TimeSeriesLog already - merging an output of
304 // MergeRuns
305 ws.run().getTimeSeriesProperty<double>(item);
306 returnProp.reset(ws.getLog(item)->clone());
307 } catch (std::invalid_argument &) {
308 // Property does not already exist, so add it setting the first entry
309 std::unique_ptr<Kernel::TimeSeriesProperty<double>> timeSeriesProp(new TimeSeriesProperty<double>(item));
310 std::string startTime = ws.run().startTime().toISO8601String();
311
312 timeSeriesProp->addValue(startTime, value);
313 ws.mutableRun().addProperty(std::move(timeSeriesProp), true);
314
315 returnProp.reset(ws.getLog(item)->clone());
316 }
317 ws.getLog(item)->setUnits(originalUnit); // we lost the unit of the workspace
318 return returnProp;
319}
320
329std::shared_ptr<Property> SampleLogsBehaviour::addPropertyForList(const std::string &item, const std::string &value,
330 MatrixWorkspace &ws) {
331 std::shared_ptr<Property> returnProp;
332
333 const std::string originalUnit = ws.getLog(item)->units();
334 // See if property exists already - merging an output of the calling algorithm
335 returnProp.reset(ws.getLog(item)->clone());
336 if (returnProp->type() != "string") {
337 ws.mutableRun().addProperty(item, value, true);
338 returnProp.reset(ws.getLog(item)->clone());
339 }
340 ws.getLog(item)->setUnits(originalUnit); // we lost the unit of the workspace
341 return returnProp;
342}
343
353bool SampleLogsBehaviour::setNumericValue(const std::string &item, const MatrixWorkspace &ws, double &value) {
354 bool isNumeric;
355
356 try {
357 value = ws.getLogAsSingleValue(item);
358 isNumeric = true;
359 } catch (std::invalid_argument &) {
360 isNumeric = false;
361 }
362
363 return isNumeric;
364}
365
373 for (const auto &item : m_logMap) {
374 const std::string &logName = item.first.first;
375
376 const Property *addeeWSProperty = addeeWS->getLog(logName);
377 const std::string originalUnit = addeeWS->getLog(logName)->units();
378
379 double addeeWSNumericValue = 0.;
380 double outWSNumericValue = 0.;
381
382 try {
383 addeeWSNumericValue = addeeWS->getLogAsSingleValue(logName);
384 outWSNumericValue = outWS->getLogAsSingleValue(logName);
385 } catch (std::invalid_argument &) {
386 if (item.second.isNumeric) {
387 throw std::invalid_argument(logName + " could not be converted to a numeric type");
388 }
389 }
390
391 switch (item.first.second) {
392 case MergeLogType::Sum: {
393 this->updateSumProperty(addeeWSNumericValue, outWSNumericValue, *outWS, logName);
394 break;
395 }
397 this->updateTimeSeriesProperty(*addeeWS, *outWS, logName);
398 break;
399 }
400 case MergeLogType::List: {
401 this->updateListProperty(*addeeWS, *outWS, logName);
402 break;
403 }
405 this->checkWarnProperty(*addeeWS, addeeWSProperty, item.second, addeeWSNumericValue, outWSNumericValue, logName);
406 break;
408 this->checkErrorProperty(*addeeWS, addeeWSProperty, item.second, addeeWSNumericValue, outWSNumericValue, logName);
409 break;
410 }
411 outWS->getLog(logName)->setUnits(originalUnit);
412 }
413}
414
425void SampleLogsBehaviour::updateSumProperty(double addeeWSNumericValue, double outWSNumericValue,
426 MatrixWorkspace &outWS, const std::string &name) {
427 outWS.mutableRun().addProperty(name, addeeWSNumericValue + outWSNumericValue, true);
428}
429
439 const std::string &name) {
440 auto timeSeriesProp = outWS.run().getTimeSeriesProperty<double>(name);
441 try {
442 const auto addeeTimeSeries = addeeWS.run().getTimeSeriesProperty<double>(name);
443 timeSeriesProp->merge(addeeTimeSeries);
444 } catch (std::invalid_argument &) {
445 Types::Core::DateAndTime startTime = addeeWS.run().startTime();
446 double value = addeeWS.run().getLogAsSingleValue(name);
447 timeSeriesProp->addValue(startTime, value);
448 }
449 // Remove this to supress a warning, we will put it back after adding the
450 // workspaces in MergeRuns
451 const Property *addeeWSProperty = addeeWS.run().getProperty(name);
452 m_addeeLogMap.emplace_back(std::shared_ptr<Property>(addeeWSProperty->clone()));
453}
454
465 const std::string &name) {
466 const std::string addeeWSVal = addeeWS.getLog(name)->value();
467 const std::string outWSVal = outWS.run().getProperty(name)->value();
468 outWS.mutableRun().addProperty(name, outWSVal + ", " + addeeWSVal, true);
469}
470
486void SampleLogsBehaviour::checkWarnProperty(const MatrixWorkspace &addeeWS, const Property *addeeWSProperty,
487 const SampleLogBehaviour &behaviour, const double addeeWSNumericValue,
488 const double outWSNumericValue, const std::string &name) {
489
490 if (!isWithinTolerance(behaviour, addeeWSNumericValue, outWSNumericValue) &&
491 !stringPropertiesMatch(behaviour, addeeWSProperty)) {
492 m_logger.warning() << generateDifferenceMessage(name, addeeWS.getName(), addeeWSProperty->value(),
493 behaviour.property->value());
494 }
495}
496
512void SampleLogsBehaviour::checkErrorProperty(const MatrixWorkspace &addeeWS, const Property *addeeWSProperty,
513 const SampleLogBehaviour &behaviour, const double addeeWSNumericValue,
514 const double outWSNumericValue, const std::string &name) {
515
516 if (!isWithinTolerance(behaviour, addeeWSNumericValue, outWSNumericValue) &&
517 !stringPropertiesMatch(behaviour, addeeWSProperty)) {
518 throw std::invalid_argument(
519 generateDifferenceMessage(name, addeeWS.getName(), addeeWSProperty->value(), behaviour.property->value()));
520 }
521}
522
533bool SampleLogsBehaviour::isWithinTolerance(const SampleLogBehaviour &behaviour, const double addeeWSNumericValue,
534 const double outWSNumericValue) {
535 if (behaviour.isNumeric && behaviour.tolerance > 0.0) {
536 return Kernel::withinAbsoluteDifference(addeeWSNumericValue, outWSNumericValue, behaviour.tolerance);
537 }
538
539 return false;
540}
541
550bool SampleLogsBehaviour::stringPropertiesMatch(const SampleLogBehaviour &behaviour, const Property *addeeWSProperty) {
551 return behaviour.property->value() == addeeWSProperty->value();
552}
553
560 for (auto &item : m_logMap) {
561 std::string propertyToReset = item.first.first;
562
563 if (item.first.second == MergeLogType::Warn || item.first.second == MergeLogType::Fail) {
564 continue;
565 }
566
567 const Property *outWSProperty = outWS->run().getProperty(propertyToReset);
568 item.second.property = std::shared_ptr<Property>(outWSProperty->clone());
569 }
570}
571
580 for (const auto &prop : m_addeeLogMap) {
581 const auto &propName = prop->name();
582 addeeWS->mutableRun().removeProperty(propName);
583 }
584}
585
595 for (const auto &item : m_addeeLogMap) {
596 auto property = std::unique_ptr<Kernel::Property>(item->clone());
597 addeeWS->mutableRun().addProperty(std::move(property));
598 }
599 m_addeeLogMap.clear();
600}
601
608 for (auto const &item : m_logMap) {
609 std::string const &propertyToReset = item.first.first;
610
611 if (item.first.second == MergeLogType::TimeSeries) {
612 auto property = std::unique_ptr<Kernel::Property>(item.second.property->clone());
613 ws->mutableRun().addProperty(std::move(property), true);
614 } else if (item.first.second == MergeLogType::Sum || item.first.second == MergeLogType::List) {
615 ws->mutableRun().getProperty(propertyToReset)->setValue(item.second.property->value());
616 }
617 }
618}
619
620} // namespace Mantid::Algorithms
std::string name
Definition Run.cpp:60
double value
The value of the point.
Definition FitMW.cpp:51
double tolerance
Run & mutableRun()
Writable version of the run object.
const Run & run() const
Run details object access.
Geometry::Instrument_const_sptr getInstrument() const
Returns the parameterized instrument.
double getLogAsSingleValue(const std::string &log) const
Access a single value from a log for this experiment.
Kernel::Property * getLog(const std::string &log) const
Access a log for this experiment.
const Types::Core::DateAndTime startTime() const
Return the run start time.
Kernel::Property * getProperty(const std::string &name) const
Returns the named property as a pointer.
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
Definition LogManager.h:90
double getLogAsSingleValue(const std::string &name, Kernel::Math::StatisticType statistic=Kernel::Math::Mean) const
Definition LogManager.h:160
Kernel::TimeSeriesProperty< T > * getTimeSeriesProperty(const std::string &name) const
Returns a property as a time series property.
Base MatrixWorkspace Abstract Class.
const std::string & getName() const override
Get the workspace name.
Definition Workspace.cpp:59
void removeSampleLogsFromWorkspace(const API::MatrixWorkspace_sptr &addeeWS)
When doing a time series merge we need to remove, then add back the sample log in the addee workspace...
std::pair< std::string, MergeLogType > SampleLogsKey
void readdSampleLogToWorkspace(const API::MatrixWorkspace_sptr &addeeWS)
When doing a time series merge we need to remove, then add back the sample log in the addee workspace...
bool setNumericValue(const std::string &item, const API::MatrixWorkspace &ws, double &value)
Tries to set the numeric value of a property.
void updateListProperty(const API::MatrixWorkspace &addeeWS, API::MatrixWorkspace &outWS, const std::string &name)
Perform the update for a list property, appending a new value to the existing string.
std::vector< double > createTolerancesVector(const size_t numberNames, const std::vector< std::string > &tolerances)
Creates a vector of tolerances with the same size as the number of sample logs for the merge type.
std::vector< std::shared_ptr< Kernel::Property > > m_addeeLogMap
SampleLogsBehaviour(const API::MatrixWorkspace_sptr &ws, Kernel::Logger &logger, const SampleLogNames &logEntries={}, ParameterName parName={})
Create and initialise an object that is responsbile for keeping track of the merge types,...
void updateTimeSeriesProperty(const API::MatrixWorkspace &addeeWS, const API::MatrixWorkspace &outWS, const std::string &name)
Perform the update for a time series property, adding a new value to the existing time series propert...
std::map< SampleLogsKey, SampleLogBehaviour > SampleLogsMap
void setUpdatedSampleLogs(const API::MatrixWorkspace_sptr &outWS)
Set the values in the map to be the same as those in the output workspace.
void resetSampleLogs(const API::MatrixWorkspace_sptr &ws)
Resets the sample logs in the workspace to the values in the map.
std::shared_ptr< Kernel::Property > addPropertyForTimeSeries(const std::string &item, const double value, API::MatrixWorkspace &ws)
Adds a property to the workspace provided for a TimeSeries merge type.
bool stringPropertiesMatch(const SampleLogBehaviour &behaviour, const Kernel::Property *addeeWSProperty)
Check if a sample log value in the addee workspace matches one in the first workspace.
std::shared_ptr< Kernel::Property > addPropertyForList(const std::string &item, const std::string &value, API::MatrixWorkspace &ws)
Adds a property to the workspace provided for a List merge type.
void setSampleMap(SampleLogsMap &map, const MergeLogType &, const std::string &params, API::MatrixWorkspace &ws, const std::string &paramsTolerances="", bool skipIfInPrimaryMap=false)
This method updates the map with the sample log behaviour, and adds the new property to the workspace...
void mergeSampleLogs(const API::MatrixWorkspace_sptr &addeeWS, const API::MatrixWorkspace_sptr &outWS)
Create and update sample logs according to instrument parameters.
struct Mantid::Algorithms::SampleLogsBehaviour::ParameterName parameterNames
bool isWithinTolerance(const SampleLogBehaviour &behaviour, const double addeeWSNumber, const double outWSNumber)
Check if a sample log value in the addee workspace is numeric and within tolerances.
void updateSumProperty(double addeeWSNumber, double outWSNumber, API::MatrixWorkspace &outWS, const std::string &name)
Perform the update for a sum property, adding a new value to the existing one.
void checkWarnProperty(const API::MatrixWorkspace &addeeWS, const Kernel::Property *addeeWSProperty, const SampleLogBehaviour &behaviour, const double addeeWSNumber, const double outWSNumber, const std::string &name)
Performs the check to see if a warning should be generated because logs are different.
void checkErrorProperty(const API::MatrixWorkspace &addeeWS, const Kernel::Property *addeeWSProperty, const SampleLogBehaviour &behaviour, const double addeeWSNumber, const double outWSNumber, const std::string &name)
Performs the check to see if an error should be generated because logs are different.
void createSampleLogsMapsFromInstrumentParams(SampleLogsMap &instrumentMap, API::MatrixWorkspace &ws)
Extracts all of the settings from the instrument parameters, and adds them to a map of sample log beh...
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition Logger.h:51
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
Base class for properties.
Definition Property.h:95
virtual const std::string & units() const
Returns the units of the property, if any, as a string.
Definition Property.cpp:194
virtual void setUnits(const std::string &unit)
Sets the units of the property, as a string.
Definition Property.cpp:201
virtual Property * clone() const =0
'Virtual copy constructor'
virtual std::string value() const =0
Returns the value of the property as a string.
Iterator begin()
Iterator referring to first element in the container.
@ TOK_IGNORE_EMPTY
ignore empty tokens
@ TOK_TRIM
remove leading and trailing whitespace from tokens
Iterator end()
Iterator referring to the past-the-end element in the container.
const TokenVec & asVector()
Returns a vector of tokenized strings.
A specialised Property class for holding a series of time-value pairs.
Mantid::Kernel::StringTokenizer tokenizer
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
MANTID_KERNEL_DLL bool withinAbsoluteDifference(T const x, T const y, S const tolerance)
Test whether x, y are within absolute tolerance tol.
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)