Mantid
Loading...
Searching...
No Matches
NexusClasses.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
10#include <memory>
11#include <utility>
12
13namespace Mantid::Nexus {
14
15static NXDimArray nxdimArray(const DimVector &xd) {
16 NXDimArray ret{0};
17 for (std::size_t i = 0; i < xd.size(); i++) {
18 ret[i] = xd[i];
19 }
20 return ret;
21}
22
23NXInfo::NXInfo(Info const &info, std::string const &name)
24 : nxname(name), rank(info.dims.size()), dims(nxdimArray(info.dims)), type(info.type), allGood(true) {}
25
26std::vector<std::string> NXAttributes::names() const {
27 std::vector<std::string> out;
28 out.reserve(m_values.size());
29 std::transform(m_values.cbegin(), m_values.cend(), std::back_inserter(out),
30 [](auto const &value) -> std::string { return value.first; });
31 return out;
32}
33
34std::vector<std::string> NXAttributes::values() const {
35 std::vector<std::string> out;
36 out.reserve(m_values.size());
37 std::transform(m_values.cbegin(), m_values.cend(), std::back_inserter(out),
38 [](auto const &value) -> std::string { return value.second; });
39 return out;
40}
41
46std::string NXAttributes::operator()(const std::string &name) const {
47 auto it = m_values.find(name);
48 if (it == m_values.end())
49 return "";
50 return it->second;
51}
52
57void NXAttributes::set(const std::string &name, const std::string &value) { m_values[name] = value; }
58
63template <typename T> void NXAttributes::set(const std::string &name, T value) {
65}
66
67//---------------------------------------------------------
68// NXObject methods
69//---------------------------------------------------------
70
73NXObject::NXObject() : m_fileID(nullptr), m_open(false) {}
74
81NXObject::NXObject(File *fileID, NXClass const *parent, const std::string &name) : m_fileID(fileID), m_open(false) {
82 if (parent && !name.empty()) {
83 m_address = parent->address() / name;
84 }
85}
86
93NXObject::NXObject(std::shared_ptr<File> const &fileID, NXClass const *parent, const std::string &name)
94 : m_fileID(fileID), m_open(false) {
95 if (parent && !name.empty()) {
96 m_address = parent->address() / name;
97 }
98}
99
100std::string NXObject::name() const { return m_address.stem(); }
101
105 std::vector<char> buff(128);
106 for (AttrInfo const &ainfo : m_fileID->getAttrInfos()) {
107 if (ainfo.type != NXnumtype::CHAR && ainfo.length != 1) {
108 throw std::runtime_error("Encountered attribute with array value");
109 }
110
111 switch (ainfo.type) {
112 case NXnumtype::CHAR: {
113 attributes.set(ainfo.name, m_fileID->getStrAttr(ainfo.name));
114 break;
115 }
116 case NXnumtype::INT16: {
117 attributes.set(ainfo.name, m_fileID->getAttr<int16_t>(ainfo.name));
118 break;
119 }
120 case NXnumtype::UINT16: {
121 attributes.set(ainfo.name, m_fileID->getAttr<uint16_t>(ainfo.name));
122 break;
123 }
124 case NXnumtype::INT32: {
125 attributes.set(ainfo.name, m_fileID->getAttr<int32_t>(ainfo.name));
126 break;
127 }
128 default:
129 break;
130 }
131 };
132}
133//---------------------------------------------------------
134// NXClass methods
135//---------------------------------------------------------
136
137NXClass::NXClass(const NXClass &parent, const std::string &name) : NXObject(parent.m_fileID, &parent, name) { clear(); }
138
140 clear();
141 for (auto const &entry : m_fileID->getEntries()) {
142 if (entry.second == "SDS") {
143 m_fileID->openData(entry.first);
144 NXInfo info(m_fileID->getInfo(), entry.first);
145 m_fileID->closeData();
146 m_datasets->emplace_back(info);
147 } else if (entry.second.starts_with("NX") || entry.second.starts_with("IX")) {
148 m_groups->emplace_back(NXClassInfo(entry));
149 }
150 }
151}
152
153bool NXClass::isValid(const std::string &address) const { return m_fileID->hasAddress(address); }
154
156 m_fileID->openGroupAddress(m_address);
157 m_open = true;
158 readAllInfo();
159}
160
171bool NXClass::openLocal(const std::string &nxclass) {
172 std::string className = nxclass.empty() ? NX_class() : nxclass;
173 try {
174 m_fileID->openGroup(name(), className);
175 } catch (Exception const &) {
176 return false;
177 }
178 m_open = true;
179 readAllInfo();
180 return true;
181}
182
184 try {
185 m_fileID->closeGroup();
186 } catch (Exception const &) {
187 throw std::runtime_error("Cannot close group " + name() + " of class " + NX_class() + " (trying to close address " +
188 m_address + ")");
189 }
190 m_open = false;
191}
192
194 m_groups.reset(new std::vector<NXClassInfo>);
195 m_datasets.reset(new std::vector<NXInfo>);
196}
197
198std::string NXClass::getString(const std::string &name) const {
199 NXChar buff = openNXChar(name);
200 try {
201 buff.load();
202 return std::string(buff(), buff.dim0());
203 } catch (std::runtime_error &) {
204 // deals with reading uninitialized/empty data
205 return std::string();
206 }
207}
208
209double NXClass::getDouble(const std::string &name) const {
210 NXDouble number = openNXDouble(name);
211 number.load();
212 return *number();
213}
214
215float NXClass::getFloat(const std::string &name) const {
216 NXFloat number = openNXFloat(name);
217 number.load();
218 return *number();
219}
220
221int32_t NXClass::getInt(const std::string &name) const {
222 NXInt number = openNXInt(name);
223 number.load();
224 return *number();
225}
230bool NXClass::containsGroup(const std::string &query) const {
231 return std::any_of(m_groups->cbegin(), m_groups->cend(),
232 [&query](const auto &group) { return group.nxname == query; });
233}
234
240NXInfo NXClass::getDataSetInfo(const std::string &name) const {
241 const auto it = std::find_if(datasets().cbegin(), datasets().cend(),
242 [&name](const auto &dataset) { return dataset.nxname == name; });
243 NXInfo info;
244 if (it != datasets().cend()) {
245 info = *it;
246 } else {
247 info.allGood = false;
248 }
249 return info;
250}
251
255bool NXClass::containsDataSet(const std::string &query) const { return getDataSetInfo(query).allGood; }
256
257//---------------------------------------------------------
258// NXRoot methods
259//---------------------------------------------------------
260
264NXRoot::NXRoot(std::string fname) : m_filename(std::move(fname)) {
265 // Open Nexus file
266 try {
267 m_fileID = std::make_shared<File>(m_filename, NXaccess::READ);
268 } catch (Exception const &e) {
269 std::cout << "NXRoot: Error loading " << m_filename << "\" in read mode: " << e.what() << "\n";
270 throw;
271 }
272 readAllInfo();
273}
274
280NXRoot::NXRoot(std::string fname, const std::string &entry) : m_filename(std::move(fname)) {
281 UNUSED_ARG(entry);
282 // Open Nexus file
283 m_fileID = std::make_shared<File>(m_filename, NXaccess::CREATE5);
284}
285
287 try {
288 m_fileID->close();
289 } catch (...) {
290 // do nothing
291 }
292}
293
294bool NXRoot::isStandard() const { return true; }
295
300 if (groups().empty()) {
301 throw std::runtime_error("Nexus file has no entries");
302 }
303 const auto it =
304 std::find_if(groups().cbegin(), groups().cend(), [](const auto &group) { return group.nxclass == "NXentry"; });
305 if (it != groups().cend()) {
306 return openEntry(it->nxname);
307 }
308 throw std::runtime_error("Nexus file has no entries");
309}
310
311//---------------------------------------------------------
312// NXDataSet methods
313//---------------------------------------------------------
314
320NXDataSet::NXDataSet(const NXClass &parent, const std::string &name) : NXObject(parent.m_fileID, &parent, name) {
321 size_t i = name.find_last_of('/');
322 if (i == std::string::npos)
324 else if (name.empty() || i == name.size() - 1)
325 throw std::runtime_error("Improper dataset name " + name);
326 else
327 m_info.nxname = name.substr(i + 1);
328}
329
330// Opens the data set. Does not read in any data. Call load(...) to load the data
332 NexusAddress group_address(m_address.parent_path());
333 if (group_address == NexusAddress::root())
334 return; // we are in the root group, assume it is open
335 m_fileID->openAddress(group_address);
336 m_fileID->openData(name());
337 m_info = NXInfo(m_fileID->getInfo(), name());
339 m_fileID->closeData();
340}
341
343 m_fileID->openData(name());
344 m_info = NXInfo(m_fileID->getInfo(), name());
346 m_fileID->closeData();
347}
348
355 if (m_info.rank == 0UL) {
356 throw std::out_of_range("NXDataSet::dim0() - Requested dimension greater than rank.");
357 }
358 return m_info.dims[0];
359}
360
367 if (m_info.rank < 2) {
368 throw std::out_of_range("NXDataSet::dim1() - Requested dimension greater than rank.");
369 }
370 return m_info.dims[1];
371}
372
379 if (m_info.rank < 3) {
380 throw std::out_of_range("NXDataSet::dim2() - Requested dimension greater than rank.");
381 }
382 return m_info.dims[2];
383}
384
391 if (m_info.rank < 4) {
392 throw std::out_of_range("NXDataSet::dim3() - Requested dimension greater than rank.");
393 }
394 return m_info.dims[3];
395}
396
397//---------------------------------------------------------
398// NXData methods
399//---------------------------------------------------------
400
401NXData::NXData(const NXClass &parent, const std::string &name) : NXClass(parent, name) {}
402
403} // namespace Mantid::Nexus
std::string name
Definition Run.cpp:60
double value
The value of the point.
Definition FitMW.cpp:51
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:48
Class that provides for a standard Nexus exception.
std::map< std::string, std::string > m_values
the list of attributes
std::vector< std::string > names() const
Returns the list of attribute names.
std::vector< std::string > values() const
Returns the list of attribute values.
std::string operator()(const std::string &name) const
returns the value of attribute with name name
void set(const std::string &name, const std::string &value)
set the attribute's value from string
The base class for a Nexus class (group).
float getFloat(const std::string &name) const
Returns a float.
std::string getString(const std::string &name) const
Returns a string.
void open()
Opens this NXClass using File::openGroupAddress(). Can be slow (or is slow)
void readAllInfo()
Fills in m_groups and m_datasets.
bool containsGroup(const std::string &query) const
Returns whether an individual group (or group) is present.
NXClass()
Private constructor.
bool openLocal(const std::string &nxclass="")
Opens this NXClass using File::openGroup().
std::vector< NXInfo > & datasets() const
Returns a list of all datasets in this NXClass.
NXFloat openNXFloat(const std::string &name) const
Creates and opens a float dataset.
std::vector< NXClassInfo > & groups() const
Returns a list of all classes (or groups) in this NXClass.
double getDouble(const std::string &name) const
Returns a double.
void close()
Close this class.
std::shared_ptr< std::vector< NXClassInfo > > m_groups
Holds info about the child NXClasses.
NXChar openNXChar(const std::string &name) const
Creates and opens a char dataset.
std::shared_ptr< std::vector< NXInfo > > m_datasets
Holds info about the datasets in this NXClass.
NXInt openNXInt(const std::string &name) const
Creates and opens an integer dataset.
NXDouble openNXDouble(const std::string &name) const
Creates and opens a double dataset.
std::string NX_class() const override
The NX class identifier.
NXInfo getDataSetInfo(const std::string &name) const
Returns NXInfo for a dataset.
bool containsDataSet(const std::string &query) const
Returns whether an individual dataset is present.
int32_t getInt(const std::string &name) const
Returns a int.
bool isValid(const std::string &address) const
Check if a address exists relative to the current class address.
void clear()
Deletes content of m_groups and m_datasets.
Templated class implementation of NXDataSet.
void load()
Read all of the datablock in.
void getAttributes()
Reads in attributes.
dimsize_t dim0() const
Returns the number of elements along the first dimension.
void openLocal()
Opens datasets faster but the parent group must be already open.
NXAttributes attributes
Attributes.
dimsize_t dim3() const
Returns the number of elements along the fourth dimension.
NXInfo m_info
Holds the data info.
dimsize_t dim2() const
Returns the number of elements along the third dimension.
void open()
Opens the data set. Does not read in any data. Call load(...) to load the data.
dimsize_t dim1() const
Returns the number of elements along the second dimension.
std::string name() const
Returns the name of the data set.
NXData(const NXClass &parent, const std::string &name)
Constructor.
Implements NXentry Nexus class.
The base abstract class for Nexus classes and data sets.
friend class NXDataSet
a friend class declaration
std::string name() const
Returns the name of the object.
NexusAddress const & address() const
Returns the absolute address to the object.
std::shared_ptr< File > m_fileID
Nexus file id.
NXObject()
Private default constructor.
NexusAddress m_address
Keeps the absolute address to the object.
friend class NXRoot
a friend class declaration
bool m_open
Set to true if the object has been open.
const std::string m_filename
The file name.
bool isStandard() const
True if complies with our understanding of the www.nexusformat.org definition.
NXEntry openEntry(const std::string &name)
Opens an entry – a topmost Nexus class.
~NXRoot() override
Destructor.
NXEntry openFirstEntry()
Open the first NXentry in the file.
This simple class encapsulates some methods for working with paths inside a Nexus file.
NexusAddress parent_path() const
static NexusAddress root()
NexusAddress stem() const
static unsigned short constexpr UINT16
static unsigned short constexpr INT16
static unsigned short constexpr CHAR
static unsigned short constexpr INT32
Header for a base Nexus::Exception.
NXDataSetTyped< char > NXChar
The char dataset type.
std::array< dimsize_t, 4 > NXDimArray
C++ implementation of Nexus classes.
std::vector< dimsize_t > DimVector
static NXDimArray nxdimArray(const DimVector &xd)
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)
Information about an attribute.
This structure holds the type and dimensions of a primative field/array.
Information about a Nexus class.
Structure for keeping information about a Nexus data set, such as the dimensions and the type.
bool allGood
return status
std::size_t rank
number of dimensions of the data
std::string nxname
name of the object
NXDimArray dims
sizes along each dimension