18#include "MantidHistogramData/Histogram.h"
32using Mantid::Types::Core::DateAndTime;
45 "Name of input Matrix workspace containing the log to export. ");
48 "Name of the workspace containing the log events in Export. ");
50 declareProperty(
"CalculateFirstDerivative",
false,
51 "If specified then the first derivative of exported data "
52 "will be calcualted and put to spectrum 1.");
54 declareProperty(
"LogName",
"",
"Log's name to filter events.");
56 std::vector<std::string> units{
"Seconds",
"Nano Seconds"};
57 declareProperty(
"UnitOfTime",
"Seconds", std::make_shared<Kernel::StringListValidator>(units),
58 "StartTime, StopTime and DeltaTime can be given in various unit."
59 "The unit can be 'Seconds' or 'Nanoseconds' from run start time."
60 "They can also be defined as 'Percentage' of total run time.");
63 "Relative starting time of the output series. "
64 "Its unit is determined by property UnitOfTime.");
67 "Relative stopping time of the output series."
68 "Its unit is determined by property UnitOfTime.");
70 declareProperty(
"OutputAbsoluteTime",
false,
"If true, the output times will be absolute time to 1990.01.01.");
72 declareProperty(
"NumberEntriesExport",
EMPTY_INT(),
73 "Number of entries of the log to be exported. Default is all entries.");
75 declareProperty(
"IsEventWorkspace",
true,
76 "If set to true, output workspace "
77 "is EventWorkspace. Otherwise, it "
91 bool exportEpochTime =
getProperty(
"OutputAbsoluteTime");
93 int numberoutputentries =
getProperty(
"NumberEntriesExport");
94 bool outputeventworkspace =
getProperty(
"IsEventWorkspace");
96 bool cal1stderiv =
getProperty(
"CalculateFirstDerivative");
99 exportLog(logname, time_unit, start_time, stop_time, exportEpochTime, outputeventworkspace, numberoutputentries,
125 const double &stoptime,
const bool exportepoch,
bool outputeventws,
int numentries,
126 bool cal_first_deriv) {
129 std::vector<Types::Core::DateAndTime> times;
130 std::vector<double> values;
132 if (!logname.empty()) {
136 std::stringstream errmsg;
137 errmsg <<
"TimeSeriesProperty Log " << logname <<
" does not exist in workspace " <<
m_inputWS->getName();
139 throw std::invalid_argument(errmsg.str());
141 times = tlog->timesAsVector();
142 values = tlog->valuesAsVector();
144 throw std::runtime_error(
"Log name cannot be left empty.");
148 double timeunitfactor = 1.;
149 if (timeunit ==
"Seconds")
150 timeunitfactor = 1.E-9;
154 size_t i_stop = times.size() - 1;
156 bool i_start_cal =
false;
158 int64_t timerangens = times.back().totalNanoseconds() - times.front().totalNanoseconds();
159 double timerange =
static_cast<double>(timerangens) * timeunitfactor;
160 g_log.
debug() <<
"Time range is " << timerange <<
", Start time is " << starttime <<
"\n";
161 if (timerange < starttime) {
162 i_start = times.size() - 1;
170 throw std::runtime_error(
"Unable to find proton_charge for run start time. "
171 "Failed to get partial time series.");
176 numentries =
static_cast<int>(times.size());
177 }
else if (numentries <= 0) {
179 errmsg <<
"For Export Log, NumberEntriesExport must be greater than 0. "
183 throw std::runtime_error(errmsg.str());
184 }
else if (
static_cast<size_t>(numentries) > times.size()) {
185 numentries =
static_cast<int>(times.size());
195 setupWorkspace2D(i_start, i_stop, numentries, times, values, exportepoch, timeunitfactor, nspec);
212 vector<DateAndTime> ×, vector<double> values,
const bool &epochtime,
213 const double &timeunitfactor,
size_t nspec) {
215 int64_t timeshift(0);
218 Types::Core::DateAndTime runstart(
m_inputWS->run().getProperty(
"run_start")->value());
219 timeshift = runstart.totalNanoseconds();
223 size_t outsize = stop_index - start_index + 1;
224 if (outsize >
static_cast<size_t>(numentries))
225 outsize =
static_cast<size_t>(numentries);
228 m_outWS = create<Workspace2D>(nspec, Points(outsize));
230 auto &vecX =
m_outWS->mutableX(0);
231 auto &vecY =
m_outWS->mutableY(0);
232 auto &vecE =
m_outWS->mutableE(0);
235 size_t i_time =
index + start_index;
237 if (i_time >= times.size()) {
238 std::stringstream errss;
239 errss <<
"It shouldn't happen that the index is out of boundary."
240 <<
"start index = " << start_index <<
", output size = " << outsize <<
", index = " <<
index <<
"\n";
241 throw std::runtime_error(errss.str());
244 int64_t dtns = times[i_time].totalNanoseconds() - timeshift;
245 vecX[
index] =
static_cast<double>(dtns) * timeunitfactor;
246 vecY[
index] = values[i_time];
264 vector<DateAndTime> ×, vector<double> values,
265 const bool &epochtime) {
266 Types::Core::DateAndTime runstart(
m_inputWS->run().getProperty(
"run_start")->value());
269 const size_t numberOfSpectra = 1;
271 size_t outsize = stop_index - start_index + 1;
272 if (outsize >
static_cast<size_t>(numentries))
273 outsize =
static_cast<size_t>(numentries);
275 std::shared_ptr<EventWorkspace> outEventWS =
276 create<EventWorkspace>(*
m_inputWS, numberOfSpectra, HistogramData::BinEdges(2));
280 EventList &outEL = outEventWS->getSpectrum(0);
287 int64_t time_shift_ns(0);
290 time_shift_ns = runstart.totalNanoseconds();
293 for (
size_t i = 0; i < outsize; i++) {
294 Types::Core::DateAndTime tnow = times[i + start_index];
295 int64_t dt = tnow.totalNanoseconds() - time_shift_ns;
298 double dtmsec =
static_cast<double>(dt) / 1000.0;
302 outEventWS->sortAll(
TOF_SORT,
nullptr);
306 outEventWS->setBinEdges(0, HistogramData::BinEdges{events.begin()->tof(), events.rbegin()->tof()});
320 const double &rel_start_time,
size_t &i_start,
321 const double &rel_stop_time,
size_t &i_stop,
322 const double &time_factor) {
325 i_stop = vec_times.size() - 1;
328 Types::Core::DateAndTime run_start(0);
329 if (
m_inputWS->run().hasProperty(
"proton_charge")) {
332 throw std::runtime_error(
"Found the run property proton_charge but failed to interpret it "
333 "as a time series property of double values (failed dynamic cast).");
335 run_start = ts->nthTime(0);
337 g_log.
warning(
"Property proton_charge does not exist so it is unable to "
338 "determine run start time. "
339 "StartTime and StopTime are ignored. TimeSeriesProperty is "
340 "exported in full length.");
346 int64_t start_time_ns = run_start.totalNanoseconds() +
static_cast<int64_t
>(rel_start_time / time_factor);
347 Types::Core::DateAndTime start_time(start_time_ns);
348 i_start =
static_cast<size_t>(std::lower_bound(vec_times.begin(), vec_times.end(), start_time) - vec_times.begin());
356 int64_t stop_time_ns = run_start.totalNanoseconds() +
static_cast<int64_t
>(rel_stop_time / time_factor);
357 Types::Core::DateAndTime stop_time(stop_time_ns);
358 i_stop =
static_cast<size_t>(std::lower_bound(vec_times.begin(), vec_times.end(), stop_time) - vec_times.begin());
366 g_log.
error(
"It is not supported to calculate first derivative if the "
367 "output is an EventWorkspace.");
372 size_t datasize =
m_outWS->mutableX(1).size();
373 auto vecX =
m_outWS->mutableX(0);
374 auto vecY =
m_outWS->mutableY(0);
375 auto &derivX =
m_outWS->mutableX(1);
376 auto &derivY =
m_outWS->mutableY(1);
377 if (vecY.size() != datasize)
378 throw std::runtime_error(
"Output workspace 2D is not supposed to have "
379 "different size of X and Y.");
381 std::stringstream errmsg_ss;
382 for (
size_t i = 1; i < datasize - 1; ++i) {
386 double dx = vecX[i + 1] - vecX[i];
388 errmsg_ss <<
"Entry " << i <<
": " << vecX[i] <<
" >= " << vecX[i + 1] <<
"\n";
391 derivY[i] = (vecY[i + 1] - vecY[i]) / dx;
396 derivX[datasize - 1] = vecX[datasize - 1];
400 std::string errmsg = errmsg_ss.str();
416 const bool &export_epoch) {
418 m_outWS->mutableRun().addProperty(
"SampleLogName", log_name,
true);
419 m_outWS->mutableRun().addProperty(
"TimeUnit", time_unit,
true);
421 std::string is_epoch(
"0");
424 m_outWS->mutableRun().addProperty(
"IsEpochTime", is_epoch,
true);
#define DECLARE_ALGORITHM(classname)
std::map< DeltaEMode::Type, std::string > index
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Class to represent the axis of a workspace.
virtual const std::shared_ptr< Kernel::Unit > & setUnit(const std::string &unitName)
Set the unit on the Axis.
void clearDetectorIDs()
Clear the detector IDs set.
A property class for workspaces.
ExportTimeSeriesLog : Read a TimeSeries log and return some information required by users.
API::MatrixWorkspace_sptr m_inputWS
void calculateFirstDerivative(bool is_event_ws)
void setupMetaData(const std::string &log_name, const std::string &time_unit, const bool &export_epoch)
Set up the meta data such as sample log name, unit of time, whether the time is epoch to the output w...
void setupWorkspace2D(const size_t &start_index, const size_t &stop_index, int numentries, std::vector< Types::Core::DateAndTime > ×, std::vector< double > values, const bool &epochtime, const double &timeunitfactor, size_t nspec)
Set up the output workspace in a Workspace2D.
API::MatrixWorkspace_sptr m_outWS
void setupEventWorkspace(const size_t &start_index, const size_t &stop_index, int numentries, std::vector< Types::Core::DateAndTime > ×, std::vector< double > values, const bool &epochtime)
Set up an Event workspace.
bool calculateTimeSeriesRangeByTime(std::vector< Types::Core::DateAndTime > &vec_times, const double &rel_start_time, size_t &i_start, const double &rel_stop_time, size_t &i_stop, const double &time_factor)
Calculate the range of time vector by start time and stop time.
void exportLog(const std::string &logname, const std::string &timeunit, const double &starttime, const double &stoptime, const bool exportepoch, bool outputeventws, int numentries, bool cal_first_deriv)
Export part of designated log to an file in column format and a output file.
void exec() override
Main execution.
std::vector< WeightedEventNoTime > & getWeightedEventsNoTime()
Return the list of WeightedEvent contained.
void reserve(size_t num) override
Reserve a certain number of entries in event list of the specified eventType.
void switchTo(Mantid::API::EventType newType) override
Switch the EventList to use the given EventType (TOF, WEIGHTED, or WEIGHTED_NOTIME)
void addEventQuickly(const Types::Event::TofEvent &event)
Append an event to the histogram, without clearing the cache, to make it faster.
Info about a single neutron detection event, including a weight and error value, but excluding the pu...
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
void error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
A specialised Property class for holding a series of time-value pairs.
Helper class which provides the Collimation Length for SANS instruments.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
@ InOut
Both an input & output workspace.
@ Output
An output workspace.