Mantid
Loading...
Searching...
No Matches
BoxControllerNeXusIO.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 +
8
16
17#include <H5Cpp.h>
18#include <Poco/File.h>
19
20#include <algorithm>
21#include <string>
22
23namespace Mantid::DataObjects {
24// Default headers(attributes) describing the contents of the data, written by
25// this class
26const char *EventHeaders[] = {"signal, errorSquared, center (each dim.)",
27 "signal, errorSquared, expInfoIndex, goniometerIndex, detectorId, center (each "
28 "dim.)"};
29
30std::string BoxControllerNeXusIO::g_EventGroupName("event_data");
31std::string BoxControllerNeXusIO::g_DBDataName("free_space_blocks");
32
37 : m_File(nullptr), m_ReadOnly(true), m_dataChunk(DATA_CHUNK), m_bc(bc), m_BlockStart(2, 0), m_BlockSize(2, 0),
38 m_CoordSize(sizeof(coord_t)), m_EventType(FatEvent), m_EventsVersion("1.0"),
39 m_EventDataVersion(EventDataVersion::EDVGoniometer), m_ReadConversion(noConversion) {
40 m_BlockSize[1] = 5 + m_bc->getNDims();
41
42 std::copy(std::cbegin(EventHeaders), std::cend(EventHeaders), std::back_inserter(m_EventsTypeHeaders));
43
44 m_EventsTypesSupported.resize(2);
47}
49BoxControllerNeXusIO::EventType BoxControllerNeXusIO::TypeFromString(const std::vector<std::string> &typesSupported,
50 const std::string &typeName) {
51 auto it = std::find(typesSupported.begin(), typesSupported.end(), typeName);
52 if (it == typesSupported.end())
53 throw std::invalid_argument("Unsupported event type: " + typeName + " provided ");
54
55 return static_cast<EventType>(std::distance(typesSupported.begin(), it));
56}
71void BoxControllerNeXusIO::setDataType(const size_t blockSize, const std::string &typeName) {
72 if (blockSize == 4 || blockSize == 8) {
73
74 m_CoordSize = static_cast<unsigned int>(blockSize);
76
77 switch (m_EventType) {
78 case (LeanEvent):
79 m_BlockSize[1] = 2 + m_bc->getNDims();
81 break;
82 case (FatEvent):
83 m_BlockSize[1] = 5 + m_bc->getNDims();
85 break;
86 default:
87 throw std::invalid_argument(" Unsupported event kind Identified ");
88 }
89 } else
90 throw std::invalid_argument("The class currently supports 4(float) and "
91 "8(double) event coordinates only");
92}
93
105void BoxControllerNeXusIO::getDataType(size_t &CoordSize, std::string &typeName) const {
106 CoordSize = m_CoordSize;
108}
109
118bool BoxControllerNeXusIO::openFile(const std::string &fileName, const std::string &mode) {
119 // file already opened
120 if (m_File)
121 return false;
122
123 std::lock_guard<std::mutex> _lock(m_fileMutex);
124 m_ReadOnly = true;
125 if (mode.find('w') != std::string::npos || mode.find('W') != std::string::npos) {
126 m_ReadOnly = false;
127 }
128
129 // open file if it exists or create it if not in the mode requested
130 m_fileName = API::FileFinder::Instance().getFullPath(fileName);
131 if (m_fileName.empty()) {
132 if (!m_ReadOnly) {
133 std::string filePath = Kernel::ConfigService::Instance().getString("defaultsave.directory");
134 if (filePath.empty())
135 m_fileName = fileName;
136 else
137 m_fileName = filePath + "/" + fileName;
138 } else
139 throw Kernel::Exception::FileError("Can not open file to read ", m_fileName);
140 }
141
142 auto nDims = static_cast<int>(this->m_bc->getNDims());
143
144 bool group_exists;
145 m_File = std::unique_ptr<Mantid::Nexus::File>(MDBoxFlatTree::createOrOpenMDWSgroup(
147
148 // we are in MD workspace Class group now
149 std::map<std::string, std::string> groupEntries;
150 m_File->getEntries(groupEntries);
151 if (groupEntries.find(g_EventGroupName) != groupEntries.end()) // yes, open it
153 else // create and open it
155 // we are in MDEvent group now (either created or opened)
156
157 // read if exist and create if not the group, which is responsible for saving DiskBuffer information;
159
160 if (m_ReadOnly)
162 else
164
165 return true;
166}
167
173void BoxControllerNeXusIO::copyFileTo(const std::string &destFilename) {
174 // Some OSs (observed on Windows) take an exclusive lock on the file
175 // To copy the file must be closed, copied and reopened. To avoid
176 // paying for this where not necessary first try without closing first
177 try {
178 Poco::File(this->getFileName()).copyTo(destFilename);
179 return;
180 } catch (const Poco::Exception &) {
181 try {
182 this->closeFile();
183 Poco::File(this->getFileName()).copyTo(destFilename);
184 } catch (...) {
185 // if an exception happened during the copy attempt to reopen the original
186 this->openFile(this->getFileName(), m_ReadOnly ? "r" : "w");
187 throw;
188 }
189 this->openFile(this->getFileName(), m_ReadOnly ? "r" : "w");
190 }
191}
192
196 if (m_ReadOnly)
198 "The NXdata group: " + g_EventGroupName + " does not exist in the file opened for read", m_fileName);
199
200 try {
201 m_File->makeGroup(g_EventGroupName, "NXdata", true);
202 m_File->putAttr("version", m_EventsVersion);
203 } catch (...) {
204 throw Kernel::Exception::FileError("Can not create new NXdata group: " + g_EventGroupName, m_fileName);
205 }
206}
207
211
212 m_File->openGroup(g_EventGroupName, "NXdata");
213 std::string fileGroupVersion;
214 m_File->getAttr("version", fileGroupVersion);
215
216 if (fileGroupVersion != m_EventsVersion)
217 throw Kernel::Exception::FileError("Trying to open existing data grop to write new event data but the "
218 "group with differetn version: " +
219 fileGroupVersion + " already exists ",
220 m_fileName);
221}
224
225 // Are data already there?
226 std::string EventData("event_data");
227 std::map<std::string, std::string> groupEntries;
228 m_File->getEntries(groupEntries);
229 if (groupEntries.find(EventData) != groupEntries.end()) // yes, open it
230 {
232 } else // no, create it
233 {
234 // Prepare the event data array for writing operations:
236
237 // Now the chunk size.
238 // m_Blocksize == (number_events_to_write_at_a_time, data_items_per_event)
240 chunk[0] = m_dataChunk;
241
242 // Make and open the data
243 if (m_CoordSize == 4)
244 m_File->makeCompData("event_data", NXnumtype::FLOAT32, m_BlockSize, NXcompression::NONE, chunk, true);
245 else
246 m_File->makeCompData("event_data", NXnumtype::FLOAT64, m_BlockSize, NXcompression::NONE, chunk, true);
247
248 // A little bit of description for humans to read later
249 m_File->putAttr("description", m_EventsTypeHeaders[m_EventType]);
250 // disk buffer knows that the file has no events
251 this->setFileLength(0);
252 }
253}
257 // Open the data
258 m_File->openData("event_data");
259
260 Nexus::Info info = m_File->getInfo();
261 NXnumtype Type = info.type;
262
264 switch (Type) {
265 case (NXnumtype::FLOAT64):
266 if (m_CoordSize == 4)
268 break;
269 case (NXnumtype::FLOAT32):
270 if (m_CoordSize == 8)
272 break;
273
274 default:
275 throw Kernel::Exception::FileError("Unknown events data format ", m_fileName);
276 }
277
278 auto ndim2 = static_cast<size_t>(info.dims[1]); // number of columns
280
281 // HACK -- there is no difference between empty event dataset and the dataset
282 // with 1 event.
283 // It is unclear how to deal with this stuff but the situations, where the
284 // dataset was created and closed without writing there anything
285 // and then opened again to write data into it are probably rare.
286 uint64_t nFilePoints = info.dims[0];
287 this->setFileLength(nFilePoints);
288}
292 std::vector<uint64_t> freeSpaceBlocks;
293 this->getFreeSpaceVector(freeSpaceBlocks);
294 if (freeSpaceBlocks.empty())
295 freeSpaceBlocks.resize(2, 0); // Needs a minimum size
296
297 // // Get a vector of the free space blocks to save to the file
298 Nexus::DimVector free_dims(2, 2);
299 free_dims[0] = int64_t(freeSpaceBlocks.size() / 2);
300 Nexus::DimVector free_chunk(2, 2);
301 free_chunk[0] = int64_t(m_dataChunk);
302
303 std::map<std::string, std::string> groupEntries;
304 m_File->getEntries(groupEntries);
305 if (groupEntries.find(g_DBDataName) != groupEntries.end()) // data exist, open it
306 {
307 // Read the free space blocks in from the existing file
308 m_File->readData(g_DBDataName, freeSpaceBlocks);
309 this->setFreeSpaceVector(freeSpaceBlocks);
310 } else // create and open the group
311 {
312 if (m_ReadOnly)
313 throw Kernel::Exception::FileError("Attempt to create new DB group in the read-only file", m_fileName);
314 m_File->writeExtendibleData(g_DBDataName, freeSpaceBlocks, free_dims, free_chunk);
315 }
316}
317
318//-------------------------------------------------------------------------------------------------------------------------------------
323template <typename Type>
324void BoxControllerNeXusIO::saveGenericBlock(const std::vector<Type> &DataBlock, const uint64_t blockPosition) const {
325 Nexus::DimVector start(2, 0);
326 // Specify the dimensions
328
329 std::lock_guard<std::mutex> _lock(m_fileMutex);
330 start[0] = blockPosition;
331 dims[0] = Nexus::dimsize_t(DataBlock.size() / this->getNDataColums());
332
333 // ugly cast but why would putSlab change the data?. This is NeXus bug which
334 // makes putSlab method non-constant
335 auto &mData = const_cast<std::vector<Type> &>(DataBlock);
336
337 {
338 m_File->putSlab<Type>(mData, start, dims);
339
340 if (blockPosition + dims[0] > this->getFileLength())
341 this->setFileLength(blockPosition + dims[0]);
342 }
343}
344
349void BoxControllerNeXusIO::saveBlock(const std::vector<float> &DataBlock, const uint64_t blockPosition) const {
350 this->saveGenericBlock(DataBlock, blockPosition);
351}
356void BoxControllerNeXusIO::saveBlock(const std::vector<double> &DataBlock, const uint64_t blockPosition) const {
357 this->saveGenericBlock(DataBlock, blockPosition);
358}
359
362
363 // Is the event of type MDLeanEvent of MDEvent
364 size_t coordSize;
365 std::string typeName;
366 getDataType(coordSize, typeName);
367
368 // Cross-validation implemented in a not very elegant way, but does the job
369 // MDLeanEvent only accepts EDVLean
370 if (typeName == MDLeanEvent<1>::getTypeName() && version != EDV::EDVLean)
371 throw std::invalid_argument("Cannot set the event data version to other than EDVLean");
372 // MDEvent cannot accept EDVLean
373 if (typeName == MDEvent<1>::getTypeName() && version == EDV::EDVLean)
374 throw std::invalid_argument("Cannot set the event data version to EDVLean");
375
376 m_EventDataVersion = version;
377}
378
379void BoxControllerNeXusIO::setEventDataVersion(const size_t &traitsCount) {
380 using EDV = EventDataVersion;
381 auto edv = static_cast<EventDataVersion>(traitsCount);
382 // sucks I couldn't create this list dynamically
383 std::initializer_list<EDV> valid_versions = {EDV::EDVLean, EDV::EDVOriginal, EDV::EDVGoniometer};
384 const auto valid_edv = std::find(std::cbegin(valid_versions), std::cend(valid_versions), edv);
385 if (valid_edv != std::cend(valid_versions)) {
386 setEventDataVersion(*valid_edv);
387 return;
388 } else {
389 // should not reach here
390 throw std::invalid_argument("Could not find a valid version");
391 }
392}
393
395 // m_BlockSize[1] is the number of data events associated to an MDLeanEvent
396 // or MDEvent object.
397 uint64_t size(m_BlockSize[1]);
398 switch (m_EventDataVersion) {
400 break; // no adjusting is necessary
401 case (EventDataVersion::EDVOriginal): // we're dealing with an old Nexus file
402 size -= 1; // old Nexus file doesn't have goniometer index info
403 break;
405 break; // no adjusting is necessary
406 default:
407 throw std::runtime_error("Unknown event data version");
408 }
409 return size;
410}
411
412template <typename FloatOrDouble>
413void BoxControllerNeXusIO::adjustEventDataBlock(std::vector<FloatOrDouble> &Block,
414 const std::string &accessMode) const {
415 // check the validity of accessMode
416 const std::vector<std::string> validAccessModes{"READ", "WRITE"};
417 if (std::find(validAccessModes.begin(), validAccessModes.end(), accessMode) == validAccessModes.end())
418 throw std::runtime_error("Unknown access mode");
419
420 switch (m_EventDataVersion) {
422 break; // no adjusting is necessary
423 // we're dealing with and old Nexus file
425 size_t blockSize(static_cast<size_t>(Block.size()));
426 // number of data items in the old Nexus file associated to a single event
427 size_t eventSize(dataEventCount());
428
429 // we just read event data from an old Nexus file. Goniometer index must
430 // be inserted
431 if (accessMode == "READ") {
432 // Block size is a multiple of eventSize
433 size_t eventCount = blockSize / eventSize;
434 if (eventCount * eventSize != blockSize) // this shouldn't happen
435 throw std::runtime_error("Data block does not represent an integer number of events");
436 // Loop to insert goniometer index
437 std::vector<FloatOrDouble> backupBlock(Block);
438 Block.resize(eventCount * (eventSize + 1));
439 size_t blockCounter(0);
440 size_t backupBlockCounter(0);
441 for (size_t i = 0; i < eventCount; i++) {
442 // signal, error, and expInfoIndex occupy the first three data items
443 for (size_t j = 0; j < 3; j++) {
444 Block[blockCounter] = backupBlock[backupBlockCounter];
445 blockCounter++;
446 backupBlockCounter++;
447 }
448 Block[blockCounter] = 0; // here's the goniometer index!
449 blockCounter++;
450 for (size_t j = 3; j < eventSize; j++) {
451 Block[blockCounter] = backupBlock[backupBlockCounter];
452 blockCounter++;
453 backupBlockCounter++;
454 }
455 }
456 }
457 // we want to write the Block to an old Nexus file. Goniometer info must
458 // be removed
459 else if (accessMode == "WRITE") {
460 // Block size is a multiple of (eventSize + 1)
461 size_t eventCount = blockSize / (eventSize + 1);
462 if (eventCount * (eventSize + 1) != blockSize) // this shouldn't happen
463 throw std::runtime_error("Data block does not represent an integer number of events");
464 // Loop to remove goniometer index
465 std::vector<FloatOrDouble> backupBlock(Block);
466 Block.resize(eventCount * eventSize);
467 size_t blockCounter(0);
468 size_t backupBlockCounter(0);
469 for (size_t i = 0; i < eventCount; i++) {
470 // signal, error, and expInfoIndex occupy the first three data items
471 for (size_t j = 0; j < 3; j++) {
472 Block[blockCounter] = backupBlock[backupBlockCounter];
473 blockCounter++;
474 backupBlockCounter++;
475 }
476 backupBlockCounter++; // skip the goniometer index
477 for (size_t j = 3; j < eventSize; j++) {
478 Block[blockCounter] = backupBlock[backupBlockCounter];
479 blockCounter++;
480 backupBlockCounter++;
481 }
482 }
483 }
484 break;
485 }
487 break; // no adjusting is necessary
488 default:
489 throw std::runtime_error("Unknown event data version");
490 }
491}
492
493// explicit instantiations
494template DLLExport void BoxControllerNeXusIO::adjustEventDataBlock<float>(std::vector<float> &Block,
495 const std::string &accessMode) const;
496template DLLExport void BoxControllerNeXusIO::adjustEventDataBlock<double>(std::vector<double> &Block,
497 const std::string &accessMode) const;
498
499template <typename Type>
500void BoxControllerNeXusIO::loadGenericBlock(std::vector<Type> &Block, const uint64_t blockPosition,
501 const size_t nPoints) const {
502 if (blockPosition + nPoints > this->getFileLength())
503 throw Kernel::Exception::FileError("Attemtp to read behind the file end", m_fileName);
504
505 Nexus::DimVector start(2, 0);
506 start[0] = blockPosition;
507
509 size[0] = nPoints;
510 size[1] = dataEventCount(); // data item count per event in the Nexus file
511
512 std::lock_guard<std::mutex> _lock(m_fileMutex);
513
514 Block.resize(size[0] * size[1]);
515 m_File->getSlab(&Block[0], start, size);
516
517 adjustEventDataBlock(Block, "READ"); // insert goniometer info if necessary
518}
519
521template <typename FROM, typename TO> void convertFormats(const std::vector<FROM> &inData, std::vector<TO> &outData) {
522 outData.reserve(inData.size());
523 for (size_t i = 0; i < inData.size(); i++) {
524 outData.emplace_back(static_cast<TO>(inData[i]));
525 }
526}
532void BoxControllerNeXusIO::loadBlock(std::vector<float> &Block, const uint64_t blockPosition,
533 const size_t nPoints) const {
534 std::vector<double> tmp;
535 switch (m_ReadConversion) {
536 case (noConversion):
537 loadGenericBlock(Block, blockPosition, nPoints);
538 break;
539 case (doubleToFolat):
540 loadGenericBlock(tmp, blockPosition, nPoints);
541 convertFormats(tmp, Block);
542 break;
543 default:
544 throw Kernel::Exception::FileError(" Attempt to read float data from unsupported file format", m_fileName);
545 }
546}
552void BoxControllerNeXusIO::loadBlock(std::vector<double> &Block, const uint64_t blockPosition,
553 const size_t nPoints) const {
554 std::vector<float> tmp;
555 switch (m_ReadConversion) {
556 case (noConversion):
557 loadGenericBlock(Block, blockPosition, nPoints);
558 break;
559 case (floatToDouble):
560 loadGenericBlock(tmp, blockPosition, nPoints);
561 convertFormats(tmp, Block);
562 break;
563 default:
564 throw Kernel::Exception::FileError(" Attempt to read double data from unsupported file format", m_fileName);
565 }
566}
567
568//-------------------------------------------------------------------------------------------------------------------------------------
569
572 std::lock_guard<std::mutex> _lock(m_fileMutex);
573 m_File->flush();
574}
577 if (m_File) {
578 // write all file-backed data still stack in the data buffer into the file.
579 this->flushCache();
580 // lock file
581 std::lock_guard<std::mutex> _lock(m_fileMutex);
582
583 m_File->closeData(); // close events data
584 if (!m_ReadOnly) // write free space groups from the disk buffer
585 {
586 std::vector<uint64_t> freeSpaceBlocks;
587 this->getFreeSpaceVector(freeSpaceBlocks);
588 if (!freeSpaceBlocks.empty()) {
589 Nexus::DimVector free_dims(2, 2);
590 free_dims[0] = Nexus::dimsize_t(freeSpaceBlocks.size() / 2);
591
592 m_File->writeUpdatedData(g_DBDataName, freeSpaceBlocks, free_dims);
593 }
594 }
595
596 m_File->closeGroup(); // close events group
597 m_File->closeGroup(); // close workspace group
598 m_File->close(); // close NeXus file
599 m_File = nullptr;
600 }
601}
602
604} // namespace Mantid::DataObjects
gsl_vector * tmp
constexpr Mantid::Nexus::dimsize_t NX_UNLIMITED(-1)
#define DLLExport
Definitions of the DLLImport compiler directives for MSVC.
Definition System.h:37
This class is used by MDBox and MDGridBox in order to intelligently determine optimal behavior.
size_t getNDims() const
Get # of dimensions.
DataBlock: The DataBlock class holds information about a contiguous block of spectrum numbers.
Definition DataBlock.h:28
void setEventDataVersion(const EventDataVersion &version)
Nexus::DimVector m_BlockSize
the vector, which describes the event specific data size, namely how many column an event is composed...
void prepareNxSdata_CurVersion()
Open the NXS data blocks for loading/saving.
EventDataVersion
The version of the "event_data" Nexus dataset.
void prepareNxSToWrite_CurVersion()
Helper function which prepares NeXus event structure to accept events
void flushData() const override
Clear NeXus internal cache.
void saveBlock(const std::vector< float > &, const uint64_t) const override
Save float data block on specific position within properly opened NeXus data array.
bool m_ReadOnly
identifier if the file open only for reading or is in read/write
std::vector< std::string > m_EventsTypeHeaders
data headers used for different events types
void loadBlock(std::vector< float > &, const uint64_t, const size_t) const override
Load float data block from the opened NeXus file.
BoxControllerNeXusIO(API::BoxController *const bc)
Constructor.
void getDataType(size_t &CoordSize, std::string &typeName) const override
As save/load operations use void data type, these function allow set up/get the type name provided fo...
static EventType TypeFromString(const std::vector< std::string > &typesSupported, const std::string &typeName)
get event type form its string representation
EventDataVersion m_EventDataVersion
"data_event" dataset version in the current Nexus file
@ doubleToFolat
conversion btween fload/double requested by the client
std::string m_fileName
full file name (with path) of the Nexis file responsible for the IO operations (as NeXus filename has...
enum Mantid::DataObjects::BoxControllerNeXusIO::EventType m_EventType
size_t m_dataChunk
The size of the events block which can be written in the neXus array at once (continuous part of the ...
const std::string & getFileName() const override
get the full file name of the file used for IO operations
void setDataType(const size_t blockSize, const std::string &typeName) override
The optional method to set up the event type and the size of the event coordinate As save/load operat...
static std::string g_DBDataName
the group name to save disk buffer data
EventType
possible event types this class understands.
enum Mantid::DataObjects::BoxControllerNeXusIO::CoordConversion m_ReadConversion
uint64_t dataEventCount(void) const
Number of data items in Nexus dataset "data_event" associated with the particular event data version.
std::string m_EventsVersion
The version of the md events data block.
void OpenAndCheckEventGroup()
Open existing Event group and check the attributes necessary for this algorithm to work.
std::unique_ptr< Nexus::File > m_File
the file Handler responsible for Nexus IO operations;
bool openFile(const std::string &fileName, const std::string &mode) override
Open the file to use in IO operations with events.
void adjustEventDataBlock(std::vector< FloatOrDouble > &Block, const std::string &accessMode) const
Insert goniometer info in a block of event data, if necessary.
void saveGenericBlock(const std::vector< Type > &DataBlock, const uint64_t blockPosition) const
Save generc data block on specific position within properly opened NeXus data array.
static std::string g_EventGroupName
the name of the Nexus data group for saving the events
void CreateEventGroup()
Create group responsible for keeping events and add necessary attributes to it.
API::BoxController *const m_bc
shared pointer to the box controller, which is repsoponsible for this IO
void getDiskBufferFileData()
Load free space blocks from the data file or create the NeXus place to read/write them.
unsigned int m_CoordSize
number of bytes in the event coordinates (coord_t length).
void copyFileTo(const std::string &destFilename) override
Copy the file contents to a new location.
std::vector< std::string > m_EventsTypesSupported
the symbolic description of the event types currently supported by the class
std::mutex m_fileMutex
lock Nexus file operations as Nexus is not thread safe
void closeFile() override
flush disk buffer data from memory and close underlying NeXus file
void loadGenericBlock(std::vector< Type > &Block, const uint64_t blockPosition, const size_t nPoints) const
Load generic data block from the opened NeXus file.
static Mantid::Nexus::File * createOrOpenMDWSgroup(const std::string &fileName, int &nDims, const std::string &WSEventType, bool readOnly, bool &alreadyExists)
The function to create a NeXus MD workspace group with specified events type and number of dimensions...
Templated class holding data about a neutron detection event in N-dimensions (for example,...
Definition MDEvent.h:36
static std::string getTypeName()
Definition MDEvent.h:199
Templated class holding data about a neutron detection event in N-dimensions (for example,...
Definition MDLeanEvent.h:60
static std::string getTypeName()
uint64_t getFileLength() const
Definition DiskBuffer.h:106
void flushCache()
Flush out all the data in the memory; and writes out everything in the to-write cache.
void setFileLength(const uint64_t length) const
Set the length of the file that this MRU writes to.
Definition DiskBuffer.h:111
void getFreeSpaceVector(std::vector< uint64_t > &free) const
Returns a vector with two entries per free block: position and size.
void setFreeSpaceVector(std::vector< uint64_t > const &free)
Sets the free space map.
Records the filename and the description of failure.
Definition Exception.h:98
The primitive types published by this API.
static unsigned short constexpr FLOAT32
static unsigned short constexpr FLOAT64
void convertFormats(const std::vector< FROM > &inData, std::vector< TO > &outData)
Helper funcion which allows to convert one data fomat into another.
std::vector< dimsize_t > DimVector
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
Definition MDTypes.h:27
This structure holds the type and dimensions of a primative field/array.
DimVector dims
The dimensions of the file.
NXnumtype type
The primative type for the field.