Mantid
Loading...
Searching...
No Matches
NexusFileIO.h
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2007 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 +
7#pragma once
10#include "MantidAPI/Progress.h"
14#include "MantidNexus/DllConfig.h"
15#include <boost/date_time/c_local_time_adjustor.hpp>
16#include <boost/date_time/local_time_adjustor.hpp>
17#include <boost/date_time/posix_time/posix_time.hpp>
18#include <boost/scoped_array.hpp>
19
20#include <boost/optional.hpp>
21#include <climits>
22#include <memory>
23#include <nexus/NeXusFile.hpp>
24
25namespace Mantid {
26namespace NeXus {
27MANTID_NEXUS_DLL int getNexusEntryTypes(const std::string &fileName, std::vector<std::string> &entryName,
28 std::vector<std::string> &definition);
29
38class MANTID_NEXUS_DLL NexusFileIO {
39
40public:
41 // Helper typedef
42 using optional_size_t = boost::optional<size_t>;
43
46
49
52
54 void openNexusWrite(const std::string &fileName, optional_size_t entryNumber = optional_size_t(),
55 const bool append_to_file = true);
57 int writeNexusProcessedHeader(const std::string &title, const std::string &wsName = "") const;
59 void closeNexusFile();
61 void closeGroup();
63 int writeNexusSampleLogs(const Mantid::API::Run &runProperties) const;
65 int writeNexusProcessedData2D(const API::MatrixWorkspace_const_sptr &localworkspace, const bool &uniformSpectra,
66 const std::vector<int> &indices, const char *group_name, bool write2Ddata) const;
67
69 int writeNexusTableWorkspace(const API::ITableWorkspace_const_sptr &itableworkspace, const char *group_name) const;
70
71 int writeNexusProcessedDataEvent(const DataObjects::EventWorkspace_const_sptr &ws);
72
73 int writeNexusProcessedDataEventCombined(const DataObjects::EventWorkspace_const_sptr &ws,
74 std::vector<int64_t> &indices, double *tofs, float *weights,
75 float *errorSquareds, int64_t *pulsetimes, bool compress) const;
76
77 int writeEventList(const DataObjects::EventList &el, const std::string &group_name) const;
78
79 template <class T>
80 void writeEventListData(std::vector<T> events, bool writeTOF, bool writePulsetime, bool writeWeight,
81 bool writeError) const;
82 void NXwritedata(const char *name, int datatype, int rank, int *dims_array, void *data, bool compress = false) const;
83
85 int getWorkspaceSize(int &numberOfSpectra, int &numberOfChannels, int &numberOfXpoints, bool &uniformBounds,
86 std::string &axesUnits, std::string &yUnits) const;
88 int getXValues(MantidVec &xValues, const int &spectra) const;
90 int getSpectra(MantidVec &values, MantidVec &errors, const int &spectra) const;
91
93 bool writeNexusBinMasking(const API::MatrixWorkspace_const_sptr &ws) const;
94
96 void resetProgress(Mantid::API::Progress *prog);
97
99 NXhandle fileID;
100
101private:
103 // clang-format off
104 std::shared_ptr< ::NeXus::File> m_filehandle;
105 // clang-format on
111 template <class TYPE>
112 bool writeNxValue(const std::string &name, const TYPE &value, const int nxType,
113 const std::vector<std::string> &attributes, const std::vector<std::string> &avalues) const;
121 template <class T> void writeNumericTimeLog(const Kernel::TimeSeriesProperty<T> *timeSeries) const;
123 template <class TYPE>
124 bool writeSingleValueNXLog(const std::string &name, const TYPE &value, const int nxType,
125 const std::vector<std::string> &attributes, const std::vector<std::string> &avalues) const;
128 bool writeNxNote(const std::string &noteName, const std::string &author, const std::string &date,
129 const std::string &description, const std::string &pairValues) const;
131 void writeNxFloatArray(const std::string &name, const std::vector<double> &values,
132 const std::vector<std::string> &attributes, const std::vector<std::string> &avalues) const;
134 bool writeNxStringArray(const std::string &name, const std::vector<std::string> &values,
135 const std::vector<std::string> &attributes, const std::vector<std::string> &avalues) const;
139 bool checkEntryAtLevel(const std::string &item) const;
141 bool checkAttributeName(const std::string &target) const;
143 bool checkEntryAtLevelByAttribute(const std::string &attribute, std::string &entry) const;
145 int findMantidWSEntries() const;
147 std::time_t to_time_t(const boost::posix_time::ptime &t)
148 {
155 if (t == boost::posix_time::neg_infin)
156 return 0;
157 else if (t == boost::posix_time::pos_infin)
158 return LONG_MAX;
159 boost::posix_time::ptime start(boost::gregorian::date(1970, 1, 1));
160 return (t - start).total_seconds();
161 }
162
164 std::string m_filename;
165
170 template <class T> void writeNexusTimeLog(const Kernel::TimeSeriesProperty<T> *timeSeries) const;
171
173 template <class T> std::string logValueType() const { return "unknown"; }
174
176 template <typename VecType, typename ElemType>
177 void writeNexusVectorColumn(const API::Column_const_sptr &col, const std::string &columnName, int nexusType,
178 const std::string &interpret_as) const;
179
181 template <typename ColumnT, typename NexusT>
182 void writeTableColumn(int type, const std::string &interpret_as, const API::Column &col,
183 const std::string &columnName) const;
184};
185
197template <class TYPE>
198bool NexusFileIO::writeNxValue(const std::string &name, const TYPE &value, const int nxType,
199 const std::vector<std::string> &attributes,
200 const std::vector<std::string> &avalues) const {
201 int dimensions[1] = {1};
202 if (NXmakedata(fileID, name.c_str(), nxType, 1, dimensions) == NX_ERROR)
203 return false;
204 if (NXopendata(fileID, name.c_str()) == NX_ERROR)
205 return false;
206 for (unsigned int it = 0; it < attributes.size(); ++it) {
207 NXputattr(fileID, attributes[it].c_str(), (void *)avalues[it].c_str(), static_cast<int>(avalues[it].size() + 1),
208 NX_CHAR);
209 }
210 NXputdata(fileID, (void *)&value);
211 NXclosedata(fileID);
212 return true;
213}
214
226template <>
227inline bool NexusFileIO::writeNxValue(const std::string &name, const std::string &value, const int nxType,
228 const std::vector<std::string> &attributes,
229 const std::vector<std::string> &avalues) const {
230 (void)nxType;
231 int dimensions[1] = {0};
232 std::string nxstr = value;
233 if (nxstr.empty())
234 nxstr += " ";
235 dimensions[0] = static_cast<int>(nxstr.size() + 1);
236 if (NXmakedata(fileID, name.c_str(), nxType, 1, dimensions) == NX_ERROR)
237 return false;
238 if (NXopendata(fileID, name.c_str()) == NX_ERROR)
239 return false;
240 for (unsigned int it = 0; it < attributes.size(); ++it) {
241 NXputattr(fileID, attributes[it].c_str(), avalues[it].c_str(), static_cast<int>(avalues[it].size() + 1), NX_CHAR);
242 }
243 NXputdata(fileID, reinterpret_cast<void *>(const_cast<char *>(nxstr.c_str())));
244 NXclosedata(fileID);
245 return true;
246}
247
259template <class TYPE>
260bool NexusFileIO::writeSingleValueNXLog(const std::string &name, const TYPE &value, const int nxType,
261 const std::vector<std::string> &attributes,
262 const std::vector<std::string> &avalues) const {
263 if (NXmakegroup(fileID, name.c_str(), "NXlog") == NX_ERROR)
264 return false;
265 NXopengroup(fileID, name.c_str(), "NXlog");
266 int dimensions[1] = {1};
267 if (NXmakedata(fileID, "value", nxType, 1, dimensions) == NX_ERROR)
268 return false;
269 if (NXopendata(fileID, "value") == NX_ERROR)
270 return false;
271 for (unsigned int it = 0; it < attributes.size(); ++it) {
272 NXputattr(fileID, attributes[it].c_str(), (void *)avalues[it].c_str(), static_cast<int>(avalues[it].size() + 1),
273 NX_CHAR);
274 }
275 NXputdata(fileID, (void *)&value);
276 NXclosedata(fileID);
277 NXclosegroup(fileID);
278 return true;
279}
280
293template <>
294inline bool NexusFileIO::writeSingleValueNXLog(const std::string &name, const std::string &value, const int nxType,
295 const std::vector<std::string> &attributes,
296 const std::vector<std::string> &avalues) const {
297 (void)nxType;
298 if (NXmakegroup(fileID, name.c_str(), "NXlog") == NX_ERROR)
299 return false;
300 NXopengroup(fileID, name.c_str(), "NXlog");
301 int dimensions[1] = {0};
302 std::string nxstr = value;
303 if (nxstr.empty())
304 nxstr += " ";
305 dimensions[0] = static_cast<int>(nxstr.size() + 1); // Allow for null-terminator
306 if (NXmakedata(fileID, "value", NX_CHAR, 1, dimensions) == NX_ERROR)
307 return false;
308 if (NXopendata(fileID, "value") == NX_ERROR)
309 return false;
310 for (unsigned int it = 0; it < attributes.size(); ++it) {
311 NXputattr(fileID, attributes[it].c_str(), reinterpret_cast<void *>(const_cast<char *>(avalues[it].c_str())),
312 static_cast<int>(avalues[it].size() + 1), NX_CHAR);
313 }
314 NXputdata(fileID, reinterpret_cast<void *>(const_cast<char *>(nxstr.c_str())));
315 NXclosedata(fileID);
316 NXclosegroup(fileID);
317 return true;
318}
319
324template <class T> void NexusFileIO::writeNumericTimeLog(const Kernel::TimeSeriesProperty<T> *timeSeries) const {
325 // write NXlog section for double values
326 NXstatus status;
327 // get a name for the log, possibly removing the the path component
328 std::string logName = timeSeries->name();
329 size_t ipos = logName.find_last_of("/\\");
330 if (ipos != std::string::npos)
331 logName = logName.substr(ipos + 1);
332 // extract values from timeseries
333 std::map<Types::Core::DateAndTime, T> dV = timeSeries->valueAsMap();
334 std::vector<double> values;
335 std::vector<double> times;
336 Types::Core::DateAndTime t0;
337 bool first = true;
338 for (typename std::map<Types::Core::DateAndTime, T>::const_iterator dv = dV.begin(); dv != dV.end(); ++dv) {
339 T val = dv->second;
340 Types::Core::DateAndTime time = dv->first;
341 values.emplace_back(val);
342 if (first) {
343 t0 = time; // start time of log
344 first = false;
345 }
346 times.emplace_back(Types::Core::DateAndTime::secondsFromDuration(time - t0));
347 }
348 // create log
349 status = NXmakegroup(fileID, logName.c_str(), "NXlog");
350 if (status == NX_ERROR)
351 return;
352
353 NXopengroup(fileID, logName.c_str(), "NXlog");
354 // write log data
355 std::vector<std::string> attributes, avalues;
356 attributes.emplace_back("type");
357 avalues.emplace_back(logValueType<T>());
358 writeNxFloatArray("value", values, attributes, avalues);
359 attributes.clear();
360 avalues.clear();
361 // get ISO time, and save it as an attribute
362 attributes.emplace_back("start");
363 avalues.emplace_back(t0.toISO8601String());
364
365 writeNxFloatArray("time", times, attributes, avalues);
366 NXclosegroup(fileID);
367}
368
370using NexusFileIO_sptr = std::shared_ptr<NexusFileIO>;
371
372} // namespace NeXus
373} // namespace Mantid
double value
The value of the point.
Definition: FitMW.cpp:51
Column is the base class for columns of TableWorkspace.
Definition: Column.h:35
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 class for holding :
Definition: EventList.h:56
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.
std::map< Types::Core::DateAndTime, TYPE > valueAsMap() const
Return the time series as a C++ map<DateAndTime, TYPE>
Utility method for saving NeXus format of Mantid Workspace This class interfaces to the C Nexus API.
Definition: NexusFileIO.h:38
bool writeSingleValueLog(Kernel::Property *prop) const
Write a single value log entry.
void writeNexusTimeLog(const Kernel::TimeSeriesProperty< T > *timeSeries) const
Writes a numeric log to the Nexus file.
API::Progress * m_progress
Allow an externally supplied progress object to be used.
Definition: NexusFileIO.h:109
boost::optional< size_t > optional_size_t
Definition: NexusFileIO.h:42
std::string m_filename
nexus file name
Definition: NexusFileIO.h:164
std::shared_ptr< ::NeXus::File > m_filehandle
C++ API file handle.
Definition: NexusFileIO.h:104
int writeNexusSampleLogs(const Mantid::API::Run &runProperties) const
Write a lgos section.
bool writeNxValue(const std::string &name, const TYPE &value, const int nxType, const std::vector< std::string > &attributes, const std::vector< std::string > &avalues) const
Write a simple value plus possible attributes.
Definition: NexusFileIO.h:198
void writeNxFloatArray(const std::string &name, const std::vector< double > &values, const std::vector< std::string > &attributes, const std::vector< std::string > &avalues) const
write a float array along with any defined attributes
std::time_t to_time_t(const boost::posix_time::ptime &t)
convert posix time to time_t
Definition: NexusFileIO.h:147
std::string logValueType() const
Return the log value type as string.
Definition: NexusFileIO.h:173
int m_nexuscompression
Nexus compression method.
Definition: NexusFileIO.h:107
void writeNumericTimeLog(const Kernel::TimeSeriesProperty< T > *timeSeries) const
Writes a numeric log to the Nexus file.
Definition: NexusFileIO.h:324
bool writeTimeSeriesLog(Kernel::Property *prop) const
Write a time series log entry.
NXhandle fileID
Nexus file handle.
Definition: NexusFileIO.h:99
void writeNumericTimeLog_String(const Kernel::TimeSeriesProperty< std::string > *s_timeSeries) const
Write NXlog data for given string TimeSeriesProperty.
bool isTimeSeries(Kernel::Property *prop) const
Returns true if the given property is a time series property.
bool writeSingleValueNXLog(const std::string &name, const TYPE &value, const int nxType, const std::vector< std::string > &attributes, const std::vector< std::string > &avalues) const
Write a single valued NXLog entry to the Nexus file.
Definition: NexusFileIO.h:260
std::shared_ptr< const ITableWorkspace > ITableWorkspace_const_sptr
shared pointer to Mantid::API::ITableWorkspace (const version)
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< const Column > Column_const_sptr
Definition: Column.h:229
std::shared_ptr< const EventWorkspace > EventWorkspace_const_sptr
shared pointer to a const Workspace2D
MANTID_NEXUS_DLL int getNexusEntryTypes(const std::string &fileName, std::vector< std::string > &entryName, std::vector< std::string > &definition)
Get all the Nexus entry types for a file.
std::shared_ptr< NexusFileIO > NexusFileIO_sptr
Helper typedef for a shared pointer of a NexusFileIO.
Definition: NexusFileIO.h:370
Helper class which provides the Collimation Length for SANS instruments.
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
Definition: cow_ptr.h:172