14#include "MantidNexus/NexusFile.h"
18using namespace Kernel;
19using namespace Types::Core;
23Logger
g_log(
"LogManager");
25const std::string START_TIME_NAME(
"start_time");
26const std::string END_TIME_NAME(
"end_time");
29template <
typename T>
bool convertSingleValue(
const Property *property,
double &
value) {
30 if (
auto log =
dynamic_cast<const PropertyWithValue<T> *
>(property)) {
31 value =
static_cast<double>(*log);
38bool convertSingleValueToDouble(
const Property *property,
double &
value) {
42 return convertSingleValue<double>(property,
value) || convertSingleValue<int32_t>(property,
value) ||
43 convertSingleValue<int64_t>(property,
value) || convertSingleValue<uint32_t>(property,
value) ||
44 convertSingleValue<uint64_t>(property,
value) || convertSingleValue<float>(property,
value);
50 const Kernel::TimeROI *timeRoi =
nullptr) {
51 if (
const auto *log =
dynamic_cast<const ITimeSeriesProperty *
>(property)) {
52 value = log->extractStatistic(function, timeRoi);
62 const Kernel::TimeROI *timeRoi =
nullptr) {
63 return convertSingleValue<T>(property,
value) || convertTimeSeriesToDouble<T>(property,
value, function, timeRoi);
68 const Kernel::TimeROI *timeRoi =
nullptr) {
72 return convertPropertyToDouble<double>(property,
value, function, timeRoi) ||
73 convertPropertyToDouble<int32_t>(property,
value, function, timeRoi) ||
74 convertPropertyToDouble<int64_t>(property,
value, function, timeRoi) ||
75 convertPropertyToDouble<uint32_t>(property,
value, function, timeRoi) ||
76 convertPropertyToDouble<uint64_t>(property,
value, function, timeRoi) ||
77 convertPropertyToDouble<float>(property,
value, function, timeRoi);
93 std::make_unique<Kernel::
Cache<
std::pair<
std::string, Kernel::Math::StatisticType>, double>>()) {}
97 m_timeroi(
std::make_unique<Kernel::
TimeROI>(*other.m_timeroi)),
98 m_singleValueCache(
std::make_unique<Kernel::
Cache<
std::pair<
std::string, Kernel::Math::StatisticType>, double>>(
99 *other.m_singleValueCache)) {}
107 m_singleValueCache = std::make_unique<Kernel::Cache<std::pair<std::string, Kernel::Math::StatisticType>,
double>>(
108 *other.m_singleValueCache);
118 this->addProperty<std::string>(START_TIME_NAME, start.toISO8601String(),
true);
119 this->addProperty<std::string>(END_TIME_NAME, end.toISO8601String(),
true);
134 if (start_time != DateAndTime::GPS_EPOCH) {
137 }
catch (std::invalid_argument &) {
141 const std::string run_start_prop(
"run_start");
145 if (start_time != DateAndTime::GPS_EPOCH) {
148 }
catch (std::invalid_argument &) {
152 std::string errorMsg{
"No valid start time has been set for this run."};
156 throw std::runtime_error(errorMsg);
170 }
catch (std::invalid_argument &) {
174 const std::string run_end_prop(
"run_end");
178 }
catch (std::invalid_argument &) {
182 std::string errorMsg{
"No valid end time has been set for this run."};
186 throw std::runtime_error(errorMsg);
207 getTimeSeriesProperty<double>(
"proton_charge");
209 throw std::runtime_error(
"First pulse time is not available. Log \"proton_charge\" is empty.");
216 const DateAndTime reference(
"1991-01-01T00:00:00");
217 const std::vector<DateAndTime> × = log->
timesAsVector();
218 const size_t maxSkip{100};
219 const size_t maxIndex = std::min(
static_cast<size_t>(log->
realSize()), maxSkip);
220 const auto it = std::find_if(times.cbegin(), times.cbegin() + maxIndex,
221 [&reference](
const auto &time) { return time >= reference; });
222 if (it != times.cbegin() + maxIndex) {
225 return times[maxIndex - 1];
236 getTimeSeriesProperty<double>(
"proton_charge");
238 throw std::runtime_error(
"Last pulse time is not available. Log \"proton_charge\" is empty.");
248 const std::string log_name{
"proton_charge"};
250 error +=
" Log " + log_name +
" is not found.";
257 error +=
" Log " + log_name +
" is not a time series of floating-point values.";
262 error +=
" Log " + log_name +
" is empty.";
291 newMgr->
m_manager = std::unique_ptr<PropertyManager>(
m_manager->cloneInTimeROI(timeROI));
296 TimeROI outputTimeROI(timeROI);
298 newMgr->
m_timeroi = std::make_unique<Kernel::TimeROI>(outputTimeROI);
309 this->
m_manager = std::unique_ptr<PropertyManager>(other.m_manager->cloneInTimeROI(timeROI));
335 m_manager->filterByProperty(filter, excludedFromFiltering);
352 std::string
name = prop->name();
356 m_manager->declareProperty(std::move(prop),
"");
376 for (
unsigned int stat = 0; stat < 7; ++stat) {
392 size_t total{
m_timeroi->getMemorySize()};
394 for (
const auto &p :
m_manager->getProperties()) {
397 total += p->getMemorySize() +
sizeof(
Property *);
416 throw std::invalid_argument(
"LogManager::getTimeSeriesProperty - '" +
name +
"' is not a TimeSeriesProperty");
449 return timeSeriesProp->getStatistics(
m_timeroi.get());
453 if (Mantid::API::convertSingleValueToDouble(prop,
value))
471 return (*valueProp)();
473 throw std::invalid_argument(
"Run::getPropertyValueAsType - '" +
name +
"' is not of the requested type");
486 double singleValue(0.0);
487 const auto key = std::make_pair(
name, statistic);
491 if (!convertPropertyToDouble(log, singleValue, statistic, &filter)) {
495 singleValue = std::stod(stringLog->value());
496 }
catch (
const std::invalid_argument &) {
497 throw std::invalid_argument(
"Run::getPropertyAsSingleValue - Property \"" +
name +
498 "\" cannot be converted to a numeric value.");
501 throw std::invalid_argument(
"Run::getPropertyAsSingleValue - Property \"" +
name +
502 "\" is not a single numeric value or numeric time series.");
524 if (convertSingleValue<int32_t>(prop, discard) || convertSingleValue<int64_t>(prop, discard) ||
525 convertSingleValue<uint32_t>(prop, discard) || convertSingleValue<uint64_t>(prop, discard)) {
526 singleValue = std::stoi(prop->
value());
528 throw std::invalid_argument(
"Run::getPropertyAsIntegerValue - Property \"" +
name +
529 "\" cannot be converted to an integer value.");
555 for (
auto prop : props) {
568 for (
auto prop : props) {
570 tsp->clearOutdated();
590 file->makeGroup(
group,
"NXgroup",
true);
591 file->putAttr(
"version", 1);
594 std::vector<Property *> props =
m_manager->getProperties();
595 for (
auto &prop : props) {
597 prop->saveProperty(file);
598 }
catch (std::invalid_argument &exc) {
624 throw std::runtime_error(
"LogManager::loadNexus should not be used");
637 if (!
group.empty()) {
638 file->openGroup(
group,
"NXgroup");
640 std::map<std::string, std::string> entries;
641 file->getEntries(entries);
644 if (!(
group.empty() || keepOpen)) {
653 auto itNxLogEntries = allEntries.find(
"NXlog");
654 const auto nxLogEntries = (itNxLogEntries != allEntries.end()) ? itNxLogEntries->second : std::set<std::string>{};
656 const auto levels = std::count(prefix.begin(), prefix.end(),
'/');
658 auto itLower = nxLogEntries.lower_bound(prefix);
660 if (itLower == nxLogEntries.end()) {
663 if (itLower->compare(0, prefix.size(), prefix) != 0) {
667 for (
auto it = itLower; it != nxLogEntries.end() && it->compare(0, prefix.size(), prefix) == 0; ++it) {
669 const std::string &absoluteEntryName = *it;
670 if (std::count(absoluteEntryName.begin(), absoluteEntryName.end(),
'/') != levels + 1) {
673 const std::string nameClass = absoluteEntryName.substr(absoluteEntryName.find_last_of(
'/') + 1);
683 throw std::runtime_error(
"Kernel_TimeROI is not a TimeSeriesPropertyBool");
687 m_manager->declareOrReplaceProperty(std::move(prop));
702 for (
const auto &name_class : entries) {
704 if (name_class.second ==
"NXlog") {
713 throw std::runtime_error(
"Kernel_TimeROI is not a TimeSeriesPropertyBool");
717 m_manager->declareOrReplaceProperty(std::move(prop));
769#define INSTANTIATE(TYPE) \
770 template MANTID_API_DLL Kernel::TimeSeriesProperty<TYPE> *LogManager::getTimeSeriesProperty(const std::string &) \
772 template MANTID_API_DLL TYPE LogManager::getPropertyValueAsType(const std::string &) const;
double value
The value of the point.
#define INSTANTIATE(TYPE)
This class contains the information about the log entries.
double getTimeAveragedStd(const std::string &name) const
Get the time averaged standard deviation for a log.
bool operator!=(const LogManager &other) const
virtual size_t getMemorySize() const
Return an approximate memory size for the object in bytes.
virtual void removeDataOutsideTimeROI()
For the time series properties, remove values according to TimeROI.
const Types::Core::DateAndTime endTime() const
Return the run end time.
virtual void setTimeROI(const Kernel::TimeROI &timeroi)
bool hasProperty(const std::string &name) const
Does the property exist on the object.
const Kernel::TimeROI & getTimeROI() const
void copyAndFilterProperties(const LogManager &other, const Kernel::TimeROI &timeROI)
Copy properties from another LogManager; filter copied time series properties according to TimeROI.
const std::vector< Kernel::Property * > & getLogData() const
Access all log entries.
double getTimeAveragedValue(const std::string &name) const
Get the time averaged value for a log.
std::unique_ptr< Kernel::PropertyManager > m_manager
A pointer to a property manager.
Kernel::TimeSeriesPropertyStatistics getStatistics(const std::string &name) const
Returns various statistics computations for a given property.
Kernel::TimeSeriesProperty< bool > * getInvalidValuesFilter(const std::string &logName) const
returns the invalid values log if the log has a matching invalid values log filter
bool hasStartTime() const
const Types::Core::DateAndTime startTime() const
Return the run start time.
void clearOutdatedTimeSeriesLogValues()
Empty all but the last value out of all TimeSeriesProperty logs.
void clearSingleValueCache()
Clear the cache of calculated statistics.
virtual ~LogManager()
Destructor.
int getPropertyAsIntegerValue(const std::string &name) const
Returns a property as an integer value.
std::unique_ptr< Kernel::Cache< std::pair< std::string, Kernel::Math::StatisticType >, double > > m_singleValueCache
Cache for the retrieved single values.
Kernel::Property * getProperty(const std::string &name) const
Returns the named property as a pointer.
const Types::Core::DateAndTime getFirstPulseTime() const
Return the first pulse time from sample logs.
void removeProperty(const std::string &name, bool delProperty=true)
Remove a named property.
virtual void filterByTime(const Types::Core::DateAndTime start, const Types::Core::DateAndTime stop)
Filter the logs by time.
static const std::string PROTON_CHARGE_LOG_NAME
Name of the log entry containing the proton charge when retrieved using getProtonCharge.
const std::vector< Kernel::Property * > & getProperties() const
Return all of the current properties.
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
double getPropertyAsSingleValue(const std::string &name, Kernel::Math::StatisticType statistic=Kernel::Math::Mean) const
Returns a property as a single double value from its name.
static std::string getInvalidValuesFilterLogName(const std::string &logName)
Gets the correct log name for the matching invalid values log for a given log name.
LogManager * cloneInTimeROI(const Kernel::TimeROI &timeROI)
Create a new LogManager with a partial copy of its time series properties according to TimeROI.
void clearTimeSeriesLogs()
Empty the values out of all TimeSeriesProperty logs.
virtual void saveNexus(Nexus::File *file, const std::string &group, bool keepOpen=false) const
Save the run to a NeXus file with a given group name.
LogManager & operator=(const LogManager &other)
bool operator==(const LogManager &other) const
std::unique_ptr< Kernel::TimeROI > m_timeroi
HeldType getPropertyValueAsType(const std::string &name) const
Get the value of a property as the given TYPE.
void clearLogs()
Clear the logs.
bool hasValidProtonChargeLog(std::string &error) const
Check if the proton_charge log exists, is of valid type, and is not empty.
Kernel::TimeSeriesProperty< T > * getTimeSeriesProperty(const std::string &name) const
Returns a property as a time series property.
static const std::string PROTON_CHARGE_UNFILTERED_LOG_NAME
Flag to signify if a filter has been applied to the proton charge log.
virtual void loadNexus(Nexus::File *file, const std::string &group, const Mantid::Nexus::NexusDescriptor &fileInfo, const std::string &prefix, bool keepOpen=false)
Load the run from a NeXus file with a given group name. Overload that uses NexusDescriptor for faster...
bool hasInvalidValuesFilter(const std::string &logName) const
returns true if the log has a matching invalid values log filter
void filterByLog(Mantid::Kernel::LogFilter *filter, const std::vector< std::string > &excludedFromFiltering=std::vector< std::string >())
Filter the run by the given log filter.
const Types::Core::DateAndTime getLastPulseTime() const
Return the last pulse time from sample logs.
void setStartAndEndTime(const Types::Core::DateAndTime &start, const Types::Core::DateAndTime &end)
Set the run start and end.
Cache is a generic caching storage class.
Exception for when an item is not found in a collection.
A non-templated interface to a TimeSeriesProperty.
This class is for filtering TimeSeriesProperty data.
void warning(const std::string &msg)
Logs at warning level.
Property manager helper class.
static std::string getInvalidValuesFilterLogName(const std::string &logName)
Gets the correct log name for the matching invalid values log for a given log name.
The concrete, templated class for properties.
Base class for properties.
virtual std::string value() const =0
Returns the value of the property as a string.
TimeROI : Object that holds information about when the time measurement was active.
void replaceROI(const TimeSeriesProperty< bool > *roi)
static const std::string NAME
the underlying property needs a name
void update_or_replace_intersection(const TimeROI &other)
If this is empty, replace it with the supplied TimeROI, otherwise calculate the intersection.
A specialised Property class for holding a series of time-value pairs.
Types::Core::DateAndTime lastTime() const
Returns the last time.
std::vector< Types::Core::DateAndTime > timesAsVector() const override
Return the time series's times as a vector<DateAndTime>
int realSize() const override
Returns the real size of the time series property map:
const std::map< std::string, std::set< std::string > > & getAllEntries() const noexcept
Returns a const reference of the internal map holding all entries in the Nexus HDF5 file.
Kernel::Logger g_log("ExperimentInfo")
static logger object
StatisticType
Maps a "statistic" to a number.
DLLExport std::unique_ptr< Property > loadProperty(Nexus::File *file, const std::string &group, const Nexus::NexusDescriptor &fileInfo, const std::string &prefix)
Opens a NXlog group in a nexus file and creates the correct Property object from it.
Struct holding some useful statistics for a TimeSeriesProperty.
double time_standard_deviation
time weighted standard deviation
double time_mean
time weighted average