20using namespace Kernel;
24std::string generateDifferenceMessage(
const std::string &item,
const std::string &wsName,
const std::string &wsValue,
25 const std::string &firstValue) {
26 std::stringstream stringstream;
27 stringstream <<
"Item \"" << item <<
"\" has different values in workspaces! Found: " << wsValue <<
" in workspace "
28 << wsName <<
" but the value in the first workspace was: " << firstValue <<
"." << std::endl;
29 return stringstream.str();
38 "time series. The initial times are taken as the start times "
39 "for the run. Sample logs must be numeric.";
45 "logs to generate a warning if "
46 "different when merging.";
49 "Can either be empty for a comparison of the strings, a "
50 "single value for all warn sample logs, or a comma "
51 "separated list of values (must be the same length as "
55 "when merging. If there is a "
56 "difference the run is skipped.";
59 "Can either be empty for a comparison of the strings, a "
60 "single value for all fail sample logs, or a comma "
61 "separated list of values (must be the same length as "
65 "logs to sum into a single entry. "
66 "Sample logs must be numeric.";
82 : parameterNames(
std::move(parName)), m_logger(logger) {
94 m_logMap.insert(instrumentMap.begin(), instrumentMap.end());
115 std::string paramsTolerances;
142 bool skipIfInPrimaryMap) {
148 auto tolerancesStringVector = tokenizerTolerances.
asVector();
153 auto j = tolerancesVector.begin();
155 for (; i !=
tokenizer.
end() && j != tolerancesVector.end(); ++i, ++j) {
168 throw std::invalid_argument(
"Error when making list of merge items, sample log \"" + item +
169 "\" defined more than once!");
175 if (uncombinableLogs.count(mergeType) != 0) {
176 bool skipLog =
false;
178 uncombinableLogs.erase(mergeType);
179 for (
auto &logType : uncombinableLogs) {
181 throw std::invalid_argument(
"Error when making list of merge items, sample log " + item +
182 " being used for two incompatible merge types!");
192 std::shared_ptr<Property> prop;
194 prop = std::shared_ptr<Property>(ws.
getLog(item)->
clone());
195 }
catch (std::invalid_argument &) {
197 <<
"\", does not exist in workspace! This sample log will be ignored." << std::endl;
208 <<
" could not be converted to a numeric type. "
209 "This sample log will be ignored.\n"
238 const std::vector<std::string> &tolerances) {
239 size_t numberTolerances = tolerances.size();
241 std::vector<double> tolerancesVector(numberNames);
243 if (numberNames == numberTolerances && numberTolerances > 1) {
245 std::transform(tolerances.begin(), tolerances.end(), tolerancesVector.begin(),
246 [](
const std::string &val) { return std::stod(val); });
247 }
catch (std::invalid_argument &) {
248 throw std::invalid_argument(
"Error when creating tolerances vector. "
249 "Please ensure each comma separated value is "
251 }
catch (std::out_of_range &) {
252 throw std::out_of_range(
"Error when creating tolerances vector. Please "
253 "ensure each comma separated value is within "
254 "double precision range.");
256 if (std::any_of(tolerancesVector.cbegin(), tolerancesVector.cend(), [](
const auto value) { return value < 0.; })) {
257 throw std::out_of_range(
"Error when creating tolerances vector. Please "
258 "ensure all tolerance values are positive.");
260 }
else if (tolerances.empty()) {
261 std::fill(tolerancesVector.begin(), tolerancesVector.end(), -1.0);
262 }
else if (numberTolerances == 1) {
265 value = std::stod(tolerances.front());
266 std::fill(tolerancesVector.begin(), tolerancesVector.end(),
value);
267 }
catch (std::invalid_argument &) {
268 throw std::invalid_argument(
"The single tolerance value requested can "
269 "not be converted to a number. Please ensure "
270 "it is a single number, or a comma separated "
272 }
catch (std::out_of_range &) {
273 throw std::out_of_range(
"The single tolerance value requested can not be "
274 "converted to a double. Please ensure tolerance "
275 "is within double precision range.");
278 throw std::out_of_range(
"The single tolerance value requested is "
279 "negative. Please ensure it is positive.");
281 throw std::invalid_argument(
"Invalid length of tolerances, found " +
std::to_string(numberTolerances) +
282 " tolerance values but " +
std::to_string(numberNames) +
" names.");
285 return tolerancesVector;
298 std::shared_ptr<Property> returnProp;
299 const std::string originalUnit = ws.
getLog(item)->
units();
305 }
catch (std::invalid_argument &) {
308 std::string startTime = ws.
run().
startTime().toISO8601String();
310 timeSeriesProp->addValue(startTime,
value);
329 std::shared_ptr<Property> returnProp;
331 const std::string originalUnit = ws.
getLog(item)->
units();
334 if (returnProp->type() !=
"string") {
357 }
catch (std::invalid_argument &) {
372 const std::string &logName = item.first.first;
374 Property *addeeWSProperty = addeeWS->getLog(logName);
375 const std::string originalUnit = addeeWS->getLog(logName)->
units();
377 double addeeWSNumericValue = 0.;
378 double outWSNumericValue = 0.;
381 addeeWSNumericValue = addeeWS->getLogAsSingleValue(logName);
382 outWSNumericValue = outWS->getLogAsSingleValue(logName);
383 }
catch (std::invalid_argument &) {
384 if (item.second.isNumeric) {
385 throw std::invalid_argument(logName +
" could not be converted to a numeric type");
389 switch (item.first.second) {
391 this->
updateSumProperty(addeeWSNumericValue, outWSNumericValue, *outWS, logName);
403 this->
checkWarnProperty(*addeeWS, addeeWSProperty, item.second, addeeWSNumericValue, outWSNumericValue, logName);
406 this->
checkErrorProperty(*addeeWS, addeeWSProperty, item.second, addeeWSNumericValue, outWSNumericValue, logName);
409 outWS->getLog(logName)->setUnits(originalUnit);
437 const std::string &name) {
441 timeSeriesProp->merge(addeeTimeSeries);
442 }
catch (std::invalid_argument &) {
443 Types::Core::DateAndTime startTime = addeeWS.
run().
startTime();
445 timeSeriesProp->addValue(startTime,
value);
463 const std::string &name) {
464 const std::string addeeWSVal = addeeWS.
getLog(name)->
value();
486 const double outWSNumericValue,
const std::string &name) {
512 const double outWSNumericValue,
const std::string &name) {
516 throw std::invalid_argument(
517 generateDifferenceMessage(name, addeeWS.
getName(), addeeWSProperty->
value(), behaviour.
property->value()));
532 const double outWSNumericValue) {
534 return std::abs(addeeWSNumericValue - outWSNumericValue) < behaviour.
tolerance;
549 return behaviour.
property->value() == addeeWSProperty->
value();
559 std::string propertyToReset = item.first.first;
565 const Property *outWSProperty = outWS->run().getProperty(propertyToReset);
566 item.second.property = std::shared_ptr<Property>(outWSProperty->
clone());
579 const auto &propName = prop->name();
580 addeeWS->mutableRun().removeProperty(propName);
594 auto property = std::unique_ptr<Kernel::Property>(item->clone());
595 addeeWS->mutableRun().addProperty(std::move(property));
607 std::string
const &propertyToReset = item.first.first;
610 auto property = std::unique_ptr<Kernel::Property>(item.second.property->clone());
611 ws->mutableRun().addProperty(std::move(property),
true);
613 ws->mutableRun().getProperty(propertyToReset)->setValue(item.second.property->value());
double value
The value of the point.
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.
double getLogAsSingleValue(const std::string &name, Kernel::Math::StatisticType statistic=Kernel::Math::Mean) const
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.
static const std::string LIST_DOC
static const std::string FAIL_DOC
static const std::string WARN_DOC
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...
static const std::string FAIL_PROP
Kernel::Logger & m_logger
static const std::string LIST_PROP
static const std::string TIME_SERIES_PROP
std::pair< std::string, MergeLogType > SampleLogsKey
static const std::string TIME_SERIES_DOC
static const std::string SUM_DOC
static const std::string WARN_TOL_PROP
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
static const std::string FAIL_TOL_DOC
void setUpdatedSampleLogs(const API::MatrixWorkspace_sptr &outWS)
Set the values in the map to be the same as those in the output workspace.
static const std::string WARN_PROP
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 ¶ms, API::MatrixWorkspace &ws, const std::string ¶msTolerances="", 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.
static const std::string FAIL_TOL_PROP
static const std::string SUM_PROP
static const std::string WARN_TOL_DOC
void checkWarnProperty(const API::MatrixWorkspace &addeeWS, 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, 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 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 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.
void error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
Base class for properties.
virtual const std::string & units() const
Returns the units of the property, if any, as a string.
virtual void setUnits(const std::string &unit)
Sets the units of the property, as a string.
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
std::string to_string(const wide_integer< Bits, Signed > &n)
std::string TIME_SERIES_MERGE
std::string WARN_MERGE_TOLERANCES
std::string FAIL_MERGE_TOLERANCES
std::shared_ptr< Kernel::Property > property
std::string sampleLogsWarnTolerances
std::string sampleLogsWarn
std::string sampleLogsFail
std::string sampleLogsSum
std::string sampleLogsList
std::string sampleLogsTimeSeries
std::string sampleLogsFailTolerances