10#include <nexus/NeXusFile.hpp>
11#include <nexus/NeXusException.hpp>
21#include "MantidKernel/PropertyWithValue.tcc"
23#include <boost/algorithm/string/split.hpp>
28using namespace ::
NeXus;
32#pragma warning(disable : 4805)
46template <
typename NumT>
47std::unique_ptr<Property> makeProperty(::NeXus::File *file,
const std::string &name,
48 const std::vector<Types::Core::DateAndTime> ×) {
49 std::vector<NumT> values;
50 file->getData(values);
52 if (values.size() == 1) {
53 return std::make_unique<PropertyWithValue<NumT>>(name, values[0]);
55 return std::make_unique<ArrayProperty<NumT>>(name, std::move(values));
58 auto prop = std::make_unique<TimeSeriesProperty<NumT>>(name);
59 prop->addValues(times, values);
60 return std::unique_ptr<Property>(std::move(prop));
71std::unique_ptr<Property> makeTimeSeriesBoolProperty(::NeXus::File *file,
const std::string &name,
72 const std::vector<Types::Core::DateAndTime> ×) {
73 std::vector<uint8_t> savedValues;
74 file->getData(savedValues);
75 const size_t nvals = savedValues.size();
76 std::vector<bool> realValues(nvals);
77 for (
size_t i = 0; i < nvals; ++i) {
78 realValues[i] = (savedValues[i] != 0);
80 auto prop = std::make_unique<TimeSeriesProperty<bool>>(name);
81 prop->addValues(times, realValues);
82 return std::unique_ptr<Property>(std::move(prop));
86std::unique_ptr<Property> makeStringProperty(::NeXus::File *file,
const std::string &name,
87 const std::vector<Types::Core::DateAndTime> ×) {
88 std::vector<std::string> values;
90 std::string bigString = file->getStrData();
91 return std::make_unique<PropertyWithValue<std::string>>(name, bigString);
93 if (file->getInfo().dims.size() != 2)
94 throw std::runtime_error(
"NXlog loading failed on field " + name +
". Expected rank 2.");
95 int64_t numStrings = file->getInfo().dims[0];
96 int64_t span = file->getInfo().dims[1];
97 auto data = std::make_unique<char[]>(numStrings * span);
98 file->getData(data.get());
99 values.reserve(
static_cast<size_t>(numStrings));
100 for (int64_t i = 0; i < numStrings; i++)
101 values.emplace_back(data.get() + i * span);
103 auto prop = std::make_unique<TimeSeriesProperty<std::string>>(name);
104 prop->addValues(times, values);
105 return std::unique_ptr<Property>(std::move(prop));
111void getTimeAndStart(::NeXus::File *file, std::vector<double> &timeSec, std::string &startStr) {
112 file->openData(
"time");
113 file->getData(timeSec);
116 file->getAttr(
"start", startStr);
117 }
catch (::NeXus::Exception &) {
131std::unique_ptr<Property> loadPropertyCommon(::NeXus::File *file,
const std::string &group,
132 const std::vector<double> &timeSec, std::string &startStr) {
133 std::vector<Types::Core::DateAndTime> times;
134 if (!timeSec.empty()) {
136 if (startStr.empty())
137 startStr =
"2000-01-01T00:00:00";
139 Types::Core::DateAndTime start(startStr);
140 times.reserve(timeSec.size());
141 std::transform(timeSec.cbegin(), timeSec.cend(), std::back_inserter(times),
142 [&start](
const auto &time) { return start + time; });
145 file->openData(
"value");
146 std::unique_ptr<Property> retVal =
nullptr;
147 switch (file->getInfo().type) {
148 case ::NeXus::FLOAT32:
149 retVal = makeProperty<float>(file, group, times);
151 case ::NeXus::FLOAT64:
152 retVal = makeProperty<double>(file, group, times);
155 retVal = makeProperty<int32_t>(file, group, times);
157 case ::NeXus::UINT32:
158 retVal = makeProperty<uint32_t>(file, group, times);
161 retVal = makeProperty<int64_t>(file, group, times);
163 case ::NeXus::UINT64:
164 retVal = makeProperty<uint64_t>(file, group, times);
167 retVal = makeStringProperty(file, group, times);
169 case ::NeXus::UINT8: {
172 const bool typeIsBool = file->hasAttr(
"boolean");
173 file->openData(
"value");
176 retVal = makeTimeSeriesBoolProperty(file, group, times);
181 case ::NeXus::UINT16:
188 std::string unitsStr;
190 file->getAttr(
"units", unitsStr);
191 }
catch (::NeXus::Exception &) {
199 retVal->setUnits(unitsStr);
206std::unique_ptr<Property>
loadProperty(::NeXus::File *file,
const std::string &group,
208 file->openGroup(group,
"NXlog");
211 std::vector<double> timeSec;
212 std::string startStr;
215 if (fileInfo.
isEntry(prefix +
"/" + group +
"/time")) {
216 getTimeAndStart(file, timeSec, startStr);
219 return loadPropertyCommon(file, group, timeSec, startStr);
230std::unique_ptr<Property>
loadProperty(::NeXus::File *file,
const std::string &group) {
231 file->openGroup(group,
"NXlog");
234 std::vector<double> timeSec;
235 std::string startStr;
238 std::map<std::string, std::string> entries = file->getEntries();
239 if (entries.find(
"time") != entries.end()) {
240 getTimeAndStart(file, timeSec, startStr);
243 return loadPropertyCommon(file, group, timeSec, startStr);
bool isEntry(const std::string &entryName, const std::string &groupClass) const noexcept
Checks if a full-path entry exists for a particular groupClass in a Nexus dataset.
Namespace with helper methods for loading and saving Property's (logs) to NXS files.
DLLExport std::unique_ptr< Property > loadProperty(::NeXus::File *file, const std::string &group, const Mantid::Kernel::NexusHDF5Descriptor &fileInfo, const std::string &prefix)
Opens a NXlog group in a nexus file and creates the correct Property object from it.