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
12#include "MantidDataObjects/DllConfig.h"
17
18#include <H5Cpp.h>
19
20#include <algorithm>
21#include <filesystem>
22#include <string>
23
24namespace Mantid::DataObjects {
25// Default headers(attributes) describing the contents of the data, written by
26// this class
27const char *EventHeaders[] = {"signal, errorSquared, center (each dim.)",
28 "signal, errorSquared, expInfoIndex, goniometerIndex, detectorId, center (each "
29 "dim.)"};
30
31std::string BoxControllerNeXusIO::g_EventGroupName("event_data");
32std::string BoxControllerNeXusIO::g_DBDataName("free_space_blocks");
33
38 : m_File(nullptr), m_ReadOnly(true), m_dataChunk(DATA_CHUNK), m_bc(bc), m_BlockStart(2, 0), m_BlockSize(2, 0),
39 m_CoordSize(sizeof(coord_t)), m_EventType(FatEvent), m_EventsVersion("1.0"),
40 m_EventDataVersion(EventDataVersion::EDVGoniometer), m_ReadConversion(noConversion) {
41 m_BlockSize[1] = 5 + m_bc->getNDims();
42
43 std::copy(std::cbegin(EventHeaders), std::cend(EventHeaders), std::back_inserter(m_EventsTypeHeaders));
44
45 m_EventsTypesSupported.resize(2);
48}
50BoxControllerNeXusIO::EventType BoxControllerNeXusIO::TypeFromString(const std::vector<std::string> &typesSupported,
51 const std::string &typeName) {
52 auto it = std::find(typesSupported.begin(), typesSupported.end(), typeName);
53 if (it == typesSupported.end())
54 throw std::invalid_argument("Unsupported event type: " + typeName + " provided ");
55
56 return static_cast<EventType>(std::distance(typesSupported.begin(), it));
57}
72void BoxControllerNeXusIO::setDataType(const size_t blockSize, const std::string &typeName) {
73 if (blockSize == 4 || blockSize == 8) {
74
75 m_CoordSize = static_cast<unsigned int>(blockSize);
77
78 switch (m_EventType) {
79 case (LeanEvent):
80 m_BlockSize[1] = 2 + m_bc->getNDims();
82 break;
83 case (FatEvent):
84 m_BlockSize[1] = 5 + m_bc->getNDims();
86 break;
87 default:
88 throw std::invalid_argument(" Unsupported event kind Identified ");
89 }
90 } else
91 throw std::invalid_argument("The class currently supports 4(float) and "
92 "8(double) event coordinates only");
93}
94
106void BoxControllerNeXusIO::getDataType(size_t &CoordSize, std::string &typeName) const {
107 CoordSize = m_CoordSize;
109}
110
119bool BoxControllerNeXusIO::openFile(const std::string &fileName, const std::string &mode) {
120 // file already opened
121 if (m_File)
122 return false;
123
124 std::lock_guard<std::mutex> _lock(m_fileMutex);
125 m_ReadOnly = true;
126 if (mode.find('w') != std::string::npos || mode.find('W') != std::string::npos) {
127 m_ReadOnly = false;
128 }
129
130 // open file if it exists or create it if not in the mode requested
131 m_fileName = API::FileFinder::Instance().getFullPath(fileName).string();
132 if (m_fileName.empty()) {
133 if (!m_ReadOnly) {
134 std::string filePath = Kernel::ConfigService::Instance().getString("defaultsave.directory");
135 if (filePath.empty())
136 m_fileName = fileName;
137 else
138 m_fileName = filePath + "/" + fileName;
139 } else
140 throw Kernel::Exception::FileError("Can not open file to read ", m_fileName);
141 }
142
143 auto nDims = static_cast<int>(this->m_bc->getNDims());
144
145 bool group_exists;
146 m_File = std::unique_ptr<Mantid::Nexus::File>(MDBoxFlatTree::createOrOpenMDWSgroup(
148
149 // we are in MD workspace Class group now
150 std::map<std::string, std::string> groupEntries;
151 m_File->getEntries(groupEntries);
152 if (groupEntries.find(g_EventGroupName) != groupEntries.end()) // yes, open it
154 else // create and open it
156 // we are in MDEvent group now (either created or opened)
157
158 // read if exist and create if not the group, which is responsible for saving DiskBuffer information;
160
161 if (m_ReadOnly)
163 else
165
166 return true;
167}
168
174void BoxControllerNeXusIO::copyFileTo(const std::string &destFilename) {
175 // Some OSs (observed on Windows) take an exclusive lock on the file
176 // To copy the file must be closed, copied and reopened. To avoid
177 // paying for this where not necessary first try without closing first
178 try {
179 std::filesystem::copy_file(this->getFileName(), destFilename, std::filesystem::copy_options::overwrite_existing);
180 return;
181 } catch (const std::filesystem::filesystem_error &) {
182 try {
183 this->closeFile();
184 std::filesystem::copy_file(this->getFileName(), destFilename, std::filesystem::copy_options::overwrite_existing);
185 } catch (...) {
186 // if an exception happened during the copy attempt to reopen the original
187 this->openFile(this->getFileName(), m_ReadOnly ? "r" : "w");
188 throw;
189 }
190 this->openFile(this->getFileName(), m_ReadOnly ? "r" : "w");
191 }
192}
193
197 if (m_ReadOnly)
199 "The NXdata group: " + g_EventGroupName + " does not exist in the file opened for read", m_fileName);
200
201 try {
202 m_File->makeGroup(g_EventGroupName, "NXdata", true);
203 m_File->putAttr("version", m_EventsVersion);
204 } catch (...) {
205 throw Kernel::Exception::FileError("Can not create new NXdata group: " + g_EventGroupName, m_fileName);
206 }
207}
208
212
213 m_File->openGroup(g_EventGroupName, "NXdata");
214 std::string fileGroupVersion;
215 m_File->getAttr("version", fileGroupVersion);
216
217 if (fileGroupVersion != m_EventsVersion)
218 throw Kernel::Exception::FileError("Trying to open existing data grop to write new event data but the "
219 "group with differetn version: " +
220 fileGroupVersion + " already exists ",
221 m_fileName);
222}
225
226 // Are data already there?
227 std::string EventData("event_data");
228 std::map<std::string, std::string> groupEntries;
229 m_File->getEntries(groupEntries);
230 if (groupEntries.find(EventData) != groupEntries.end()) // yes, open it
231 {
233 } else // no, create it
234 {
235 // Prepare the event data array for writing operations:
237
238 // Now the chunk size.
239 // m_Blocksize == (number_events_to_write_at_a_time, data_items_per_event)
241 chunk[0] = m_dataChunk;
242
243 // Make and open the data
244 if (m_CoordSize == 4)
245 m_File->makeCompData("event_data", NXnumtype::FLOAT32, m_BlockSize, NXcompression::NONE, chunk, true);
246 else
247 m_File->makeCompData("event_data", NXnumtype::FLOAT64, m_BlockSize, NXcompression::NONE, chunk, true);
248
249 // A little bit of description for humans to read later
250 m_File->putAttr("description", m_EventsTypeHeaders[m_EventType]);
251 // disk buffer knows that the file has no events
252 this->setFileLength(0);
253 }
254}
258 // Open the data
259 m_File->openData("event_data");
260
261 Nexus::Info info = m_File->getInfo();
262 NXnumtype Type = info.type;
263
265 switch (Type) {
266 case (NXnumtype::FLOAT64):
267 if (m_CoordSize == 4)
269 break;
270 case (NXnumtype::FLOAT32):
271 if (m_CoordSize == 8)
273 break;
274
275 default:
276 throw Kernel::Exception::FileError("Unknown events data format ", m_fileName);
277 }
278
279 auto ndim2 = static_cast<size_t>(info.dims[1]); // number of columns
281
282 // HACK -- there is no difference between empty event dataset and the dataset
283 // with 1 event.
284 // It is unclear how to deal with this stuff but the situations, where the
285 // dataset was created and closed without writing there anything
286 // and then opened again to write data into it are probably rare.
287 uint64_t nFilePoints = info.dims[0];
288 this->setFileLength(nFilePoints);
289}
293 std::vector<uint64_t> freeSpaceBlocks;
294 this->getFreeSpaceVector(freeSpaceBlocks);
295 if (freeSpaceBlocks.empty())
296 freeSpaceBlocks.resize(2, 0); // Needs a minimum size
297
298 // // Get a vector of the free space blocks to save to the file
299 Nexus::DimVector free_dims(2, 2);
300 free_dims[0] = int64_t(freeSpaceBlocks.size() / 2);
301 Nexus::DimVector free_chunk(2, 2);
302 free_chunk[0] = int64_t(m_dataChunk);
303
304 std::map<std::string, std::string> groupEntries;
305 m_File->getEntries(groupEntries);
306 if (groupEntries.find(g_DBDataName) != groupEntries.end()) // data exist, open it
307 {
308 // Read the free space blocks in from the existing file
309 m_File->readData(g_DBDataName, freeSpaceBlocks);
310 this->setFreeSpaceVector(freeSpaceBlocks);
311 } else // create and open the group
312 {
313 if (m_ReadOnly)
314 throw Kernel::Exception::FileError("Attempt to create new DB group in the read-only file", m_fileName);
315 m_File->writeExtendibleData(g_DBDataName, freeSpaceBlocks, free_dims, free_chunk);
316 }
317}
318
319//-------------------------------------------------------------------------------------------------------------------------------------
324template <typename Type>
325void BoxControllerNeXusIO::saveGenericBlock(const std::vector<Type> &DataBlock, const uint64_t blockPosition) const {
326 Nexus::DimVector start(2, 0);
327 // Specify the dimensions
329
330 std::lock_guard<std::mutex> _lock(m_fileMutex);
331 start[0] = blockPosition;
332 dims[0] = Nexus::dimsize_t(DataBlock.size() / this->getNDataColums());
333
334 // ugly cast but why would putSlab change the data?. This is NeXus bug which
335 // makes putSlab method non-constant
336 auto &mData = const_cast<std::vector<Type> &>(DataBlock);
337
338 {
339 m_File->putSlab<Type>(mData, start, dims);
340
341 if (blockPosition + dims[0] > this->getFileLength())
342 this->setFileLength(blockPosition + dims[0]);
343 }
344}
345
350void BoxControllerNeXusIO::saveBlock(const std::vector<float> &DataBlock, const uint64_t blockPosition) const {
351 this->saveGenericBlock(DataBlock, blockPosition);
352}
357void BoxControllerNeXusIO::saveBlock(const std::vector<double> &DataBlock, const uint64_t blockPosition) const {
358 this->saveGenericBlock(DataBlock, blockPosition);
359}
360
363
364 // Is the event of type MDLeanEvent of MDEvent
365 size_t coordSize;
366 std::string typeName;
367 getDataType(coordSize, typeName);
368
369 // Cross-validation implemented in a not very elegant way, but does the job
370 // MDLeanEvent only accepts EDVLean
371 if (typeName == MDLeanEvent<1>::getTypeName() && version != EDV::EDVLean)
372 throw std::invalid_argument("Cannot set the event data version to other than EDVLean");
373 // MDEvent cannot accept EDVLean
374 if (typeName == MDEvent<1>::getTypeName() && version == EDV::EDVLean)
375 throw std::invalid_argument("Cannot set the event data version to EDVLean");
376
377 m_EventDataVersion = version;
378}
379
380void BoxControllerNeXusIO::setEventDataVersion(const size_t &traitsCount) {
381 using EDV = EventDataVersion;
382 auto edv = static_cast<EventDataVersion>(traitsCount);
383 // sucks I couldn't create this list dynamically
384 std::initializer_list<EDV> valid_versions = {EDV::EDVLean, EDV::EDVOriginal, EDV::EDVGoniometer};
385 const auto valid_edv = std::find(std::cbegin(valid_versions), std::cend(valid_versions), edv);
386 if (valid_edv != std::cend(valid_versions)) {
387 setEventDataVersion(*valid_edv);
388 return;
389 } else {
390 // should not reach here
391 throw std::invalid_argument("Could not find a valid version");
392 }
393}
394
396 // m_BlockSize[1] is the number of data events associated to an MDLeanEvent
397 // or MDEvent object.
398 uint64_t size(m_BlockSize[1]);
399 switch (m_EventDataVersion) {
401 break; // no adjusting is necessary
402 case (EventDataVersion::EDVOriginal): // we're dealing with an old Nexus file
403 size -= 1; // old Nexus file doesn't have goniometer index info
404 break;
406 break; // no adjusting is necessary
407 default:
408 throw std::runtime_error("Unknown event data version");
409 }
410 return size;
411}
412
413template <typename FloatOrDouble>
414void BoxControllerNeXusIO::adjustEventDataBlock(std::vector<FloatOrDouble> &Block,
415 const std::string &accessMode) const {
416 // check the validity of accessMode
417 const std::vector<std::string> validAccessModes{"READ", "WRITE"};
418 if (std::find(validAccessModes.begin(), validAccessModes.end(), accessMode) == validAccessModes.end())
419 throw std::runtime_error("Unknown access mode");
420
421 switch (m_EventDataVersion) {
423 break; // no adjusting is necessary
424 // we're dealing with and old Nexus file
426 size_t blockSize(static_cast<size_t>(Block.size()));
427 // number of data items in the old Nexus file associated to a single event
428 size_t eventSize(dataEventCount());
429
430 // we just read event data from an old Nexus file. Goniometer index must
431 // be inserted
432 if (accessMode == "READ") {
433 // Block size is a multiple of eventSize
434 size_t eventCount = blockSize / eventSize;
435 if (eventCount * eventSize != blockSize) // this shouldn't happen
436 throw std::runtime_error("Data block does not represent an integer number of events");
437 // Loop to insert goniometer index
438 std::vector<FloatOrDouble> backupBlock(Block);
439 Block.resize(eventCount * (eventSize + 1));
440 size_t blockCounter(0);
441 size_t backupBlockCounter(0);
442 for (size_t i = 0; i < eventCount; i++) {
443 // signal, error, and expInfoIndex occupy the first three data items
444 for (size_t j = 0; j < 3; j++) {
445 Block[blockCounter] = backupBlock[backupBlockCounter];
446 blockCounter++;
447 backupBlockCounter++;
448 }
449 Block[blockCounter] = 0; // here's the goniometer index!
450 blockCounter++;
451 for (size_t j = 3; j < eventSize; j++) {
452 Block[blockCounter] = backupBlock[backupBlockCounter];
453 blockCounter++;
454 backupBlockCounter++;
455 }
456 }
457 }
458 // we want to write the Block to an old Nexus file. Goniometer info must
459 // be removed
460 else if (accessMode == "WRITE") {
461 // Block size is a multiple of (eventSize + 1)
462 size_t eventCount = blockSize / (eventSize + 1);
463 if (eventCount * (eventSize + 1) != blockSize) // this shouldn't happen
464 throw std::runtime_error("Data block does not represent an integer number of events");
465 // Loop to remove goniometer index
466 std::vector<FloatOrDouble> backupBlock(Block);
467 Block.resize(eventCount * eventSize);
468 size_t blockCounter(0);
469 size_t backupBlockCounter(0);
470 for (size_t i = 0; i < eventCount; i++) {
471 // signal, error, and expInfoIndex occupy the first three data items
472 for (size_t j = 0; j < 3; j++) {
473 Block[blockCounter] = backupBlock[backupBlockCounter];
474 blockCounter++;
475 backupBlockCounter++;
476 }
477 backupBlockCounter++; // skip the goniometer index
478 for (size_t j = 3; j < eventSize; j++) {
479 Block[blockCounter] = backupBlock[backupBlockCounter];
480 blockCounter++;
481 backupBlockCounter++;
482 }
483 }
484 }
485 break;
486 }
488 break; // no adjusting is necessary
489 default:
490 throw std::runtime_error("Unknown event data version");
491 }
492}
493
494// explicit instantiations
495template MANTID_DATAOBJECTS_DLL void
496BoxControllerNeXusIO::adjustEventDataBlock<float>(std::vector<float> &Block, const std::string &accessMode) const;
497template MANTID_DATAOBJECTS_DLL void
498BoxControllerNeXusIO::adjustEventDataBlock<double>(std::vector<double> &Block, const std::string &accessMode) const;
499
500template <typename Type>
501void BoxControllerNeXusIO::loadGenericBlock(std::vector<Type> &Block, const uint64_t blockPosition,
502 const size_t nPoints) const {
503 if (blockPosition + nPoints > this->getFileLength())
504 throw Kernel::Exception::FileError("Attemtp to read behind the file end", m_fileName);
505
506 Nexus::DimVector start(2, 0);
507 start[0] = blockPosition;
508
510 size[0] = nPoints;
511 size[1] = dataEventCount(); // data item count per event in the Nexus file
512
513 std::lock_guard<std::mutex> _lock(m_fileMutex);
514
515 Block.resize(size[0] * size[1]);
516 m_File->getSlab(&Block[0], start, size);
517
518 adjustEventDataBlock(Block, "READ"); // insert goniometer info if necessary
519}
520
522template <typename FROM, typename TO> void convertFormats(const std::vector<FROM> &inData, std::vector<TO> &outData) {
523 outData.reserve(inData.size());
524 for (size_t i = 0; i < inData.size(); i++) {
525 outData.emplace_back(static_cast<TO>(inData[i]));
526 }
527}
533void BoxControllerNeXusIO::loadBlock(std::vector<float> &Block, const uint64_t blockPosition,
534 const size_t nPoints) const {
535 std::vector<double> tmp;
536 switch (m_ReadConversion) {
537 case (noConversion):
538 loadGenericBlock(Block, blockPosition, nPoints);
539 break;
540 case (doubleToFolat):
541 loadGenericBlock(tmp, blockPosition, nPoints);
542 convertFormats(tmp, Block);
543 break;
544 default:
545 throw Kernel::Exception::FileError(" Attempt to read float data from unsupported file format", m_fileName);
546 }
547}
553void BoxControllerNeXusIO::loadBlock(std::vector<double> &Block, const uint64_t blockPosition,
554 const size_t nPoints) const {
555 std::vector<float> tmp;
556 switch (m_ReadConversion) {
557 case (noConversion):
558 loadGenericBlock(Block, blockPosition, nPoints);
559 break;
560 case (floatToDouble):
561 loadGenericBlock(tmp, blockPosition, nPoints);
562 convertFormats(tmp, Block);
563 break;
564 default:
565 throw Kernel::Exception::FileError(" Attempt to read double data from unsupported file format", m_fileName);
566 }
567}
568
569//-------------------------------------------------------------------------------------------------------------------------------------
570
573 std::lock_guard<std::mutex> _lock(m_fileMutex);
574 m_File->flush();
575}
578 if (m_File) {
579 // write all file-backed data still stack in the data buffer into the file.
580 this->flushCache();
581 // lock file
582 std::lock_guard<std::mutex> _lock(m_fileMutex);
583
584 m_File->closeData(); // close events data
585 if (!m_ReadOnly) // write free space groups from the disk buffer
586 {
587 std::vector<uint64_t> freeSpaceBlocks;
588 this->getFreeSpaceVector(freeSpaceBlocks);
589 if (!freeSpaceBlocks.empty()) {
590 Nexus::DimVector free_dims(2, 2);
591 free_dims[0] = Nexus::dimsize_t(freeSpaceBlocks.size() / 2);
592
593 m_File->writeUpdatedData(g_DBDataName, freeSpaceBlocks, free_dims);
594 }
595 }
596
597 m_File->closeGroup(); // close events group
598 m_File->closeGroup(); // close workspace group
599 m_File->close(); // close NeXus file
600 m_File = nullptr;
601 }
602}
603
605} // namespace Mantid::DataObjects
gsl_vector * tmp
constexpr Mantid::Nexus::dimsize_t NX_UNLIMITED(-1)
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 adjustEventDataBlock(std::vector< FloatOrDouble > &Block, const std::string &accessMode) const
Insert goniometer info in a block of event data, if necessary.
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 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:40
static std::string getTypeName()
Definition MDEvent.h:204
Templated class holding data about a neutron detection event in N-dimensions (for example,...
Definition MDLeanEvent.h:64
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.