Mantid
Loading...
Searching...
No Matches
AddLogDerivative.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 +
9#include "MantidAPI/Run.h"
13#include "MantidKernel/System.h"
15
16using namespace Mantid::Kernel;
17using namespace Mantid::API;
18using Mantid::Types::Core::DateAndTime;
19
20namespace Mantid::Algorithms {
21
22// Register the algorithm into the AlgorithmFactory
23DECLARE_ALGORITHM(AddLogDerivative)
24
25//----------------------------------------------------------------------------------------------
26
27//----------------------------------------------------------------------------------------------
30void AddLogDerivative::init() {
31 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::InOut),
32 "An input/output workspace. The new log will be added to it.");
33 declareProperty("LogName", "", std::make_shared<MandatoryValidator<std::string>>(),
34 "The name that will identify the log entry to perform a derivative.\n"
35 "This log must be a numerical series (double).");
36 declareProperty("Derivative", 1, std::make_shared<BoundedValidator<int>>(1, 10),
37 "How many derivatives to perform. Default 1.");
38 declareProperty("NewLogName", "",
39 "Name of the newly created log. If not "
40 "specified, the string '_derivativeN' will "
41 "be appended to the original name");
42}
43
44//----------------------------------------------------------------------------------------------
55 const std::string &name, int numDerivatives) {
56 if (input->size() < numDerivatives + 1)
57 throw std::runtime_error("Log " + input->name() + " only has " + Strings::toString(input->size()) +
58 " values. Need at least " + Strings::toString(numDerivatives + 1) +
59 " to make this derivative.");
60
61 std::vector<double> values, dVal;
62 std::vector<double> times, dTime;
63 values = input->valuesAsVector();
64 times = input->timesAsVectorSeconds();
65
66 for (int deriv = 0; deriv < numDerivatives; deriv++) {
67 dVal.clear();
68 dTime.clear();
69 double t0 = times[0];
70 double y0 = values[0];
71 for (size_t i = 0; i < times.size() - 1; i++) {
72 double y1 = values[i + 1];
73 double t1 = times[i + 1];
74 if (t1 != t0) {
75 // Avoid repeated time values giving infinite derivatives
76 double dy = (y1 - y0) / (t1 - t0);
77 double t = (t0 + t1) / 2.0;
78 dVal.emplace_back(dy);
79 dTime.emplace_back(t);
80 // For the next time interval
81 t0 = t1;
82 y0 = y1;
83 }
84 }
85 times = dTime;
86 values = dVal;
87
88 progress.report("Add Log Derivative");
89 }
90
91 if (times.empty())
92 throw std::runtime_error("Log " + input->name() +
93 " did not have enough non-repeated time values to "
94 "make this derivative.");
95
96 // Convert time in sec to DateAndTime
97 DateAndTime start = input->nthTime(0);
98 std::vector<DateAndTime> timeFull;
99 timeFull.reserve(times.size());
100
101 std::transform(times.begin(), times.end(), std::back_inserter(timeFull),
102 [&start](const double time) { return start + time; });
103
104 // Create the TSP out of it
105 auto out = new TimeSeriesProperty<double>(name);
106 out->addValues(timeFull, values);
107 return out;
108}
109
110//----------------------------------------------------------------------------------------------
114 MatrixWorkspace_sptr ws = getProperty("InputWorkspace");
115 std::string LogName = getPropertyValue("LogName");
116 std::string NewLogName = getPropertyValue("NewLogName");
117 int Derivative = getProperty("Derivative");
118 if (!ws)
119 return;
120
121 if (NewLogName.empty())
122 NewLogName = LogName + "_derivative" + Strings::toString(Derivative);
123
124 Run &run = ws->mutableRun();
125 if (!run.hasProperty(LogName))
126 throw std::invalid_argument("Log " + LogName + " not found in the workspace sample logs.");
127 Property *prop = run.getProperty(LogName);
128 if (!prop)
129 throw std::invalid_argument("Log " + LogName + " not found in the workspace sample logs.");
130 auto *tsp = dynamic_cast<TimeSeriesProperty<double> *>(prop);
131 if (!tsp)
132 throw std::invalid_argument("Log " + LogName +
133 " is not a numerical series "
134 "(TimeSeriesProperty<double>"
135 ") so we can't perform its "
136 "derivative.");
137
138 Progress progress(this, 0.0, 1.0, Derivative);
139
140 // Perform derivative
141 TimeSeriesProperty<double> *output = makeDerivative(progress, tsp, NewLogName, Derivative);
142 // Add the log
143 run.addProperty(output, true);
144
145 g_log.notice() << "Added log named " << NewLogName << '\n';
146}
147
148} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
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
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
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
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
Definition: LogManager.h:79
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
This class stores information regarding an experimental run as a series of log entries.
Definition: Run.h:38
A property class for workspaces.
Takes an existing sample log, and calculates its first or second derivative, and adds it as a new log...
void exec() override
Run the algorithm.
static Mantid::Kernel::TimeSeriesProperty< double > * makeDerivative(API::Progress &progress, Mantid::Kernel::TimeSeriesProperty< double > *input, const std::string &name, int numDerivatives)
Perform the N^th derivative of a log.
const std::string name() const override
Algorithm's name for identification.
BoundedValidator is a validator that requires the values to be between upper or lower bounds,...
void notice(const std::string &msg)
Logs at notice level.
Definition: Logger.cpp:95
Validator to check that a property is not left empty.
Base class for properties.
Definition: Property.h:94
const std::string & name() const
Get the property's name.
Definition: Property.cpp:60
A specialised Property class for holding a series of time-value pairs.
int size() const override
Returns the number of values at UNIQUE time intervals in the time series.
std::vector< TYPE > valuesAsVector() const
Return the time series's values (unfiltered) as a vector<TYPE>
std::vector< double > timesAsVectorSeconds() const
Return the series as list of times, where the time is the number of seconds since the start.
Types::Core::DateAndTime nthTime(int n) const
Returns n-th time. NOTE: Complexity is order(n)! regardless of filter.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::string toString(const T &value)
Convert a number to a string.
Definition: Strings.cpp:703
@ InOut
Both an input & output workspace.
Definition: Property.h:55