34#include <boost/algorithm/string.hpp>
35#include <boost/regex.hpp>
54 m_coordSystem(
None), m_BoxStructureAndMethadata(true),
55 m_saveMDVersion(false), m_requiresMDFrameCorrection(false) {}
65 const std::map<std::string, std::set<std::string>> &allEntries = descriptor.
getAllEntries();
66 if (allEntries.count(
"NXentry") == 1) {
67 if (descriptor.
isEntry(
"/MDEventWorkspace") || descriptor.
isEntry(
"/MDHistoWorkspace")) {
82 "The name of the Nexus file to load, as a full or relative path");
85 "Load Box structure and other metadata without events. The "
86 "loaded workspace will be empty and not file-backed.");
89 "Load partial information about the boxes and events. Redundant property "
90 "currently equivalent to MetadataOnly");
93 "Set to true to load the data only on demand.");
97 "For FileBackEnd only: the amount of memory (in MB) to allocate to the "
99 "If not specified, a default of 40% of free physical memory is used.");
102 declareProperty(
"LoadHistory",
true,
"If true, the workspace history will be loaded");
105 "Name of the output MDEventWorkspace.");
113 convention = Kernel::ConfigService::Instance().getString(
"Q.convention");
115 bool fileBacked = this->
getProperty(
"FileBackEnd");
119 bool BoxAndEventInfoOnly = this->
getProperty(
"BoxStructureOnly");
127 std::string for_access;
130 for_access =
"for Read/Write access";
133 for_access =
"for Read access";
141 const std::shared_ptr<Mantid::Nexus::NexusDescriptor> fileInfo =
getFileInfo();
143 std::string entryName;
144 if (
m_file->hasGroup(
"/MDEventWorkspace",
"NXentry")) {
145 entryName =
"MDEventWorkspace";
146 }
else if (
m_file->hasGroup(
"/MDHistoWorkspace",
"NXentry")) {
147 entryName =
"MDHistoWorkspace";
149 throw std::runtime_error(
"Unexpected NXentry name. Expected "
150 "'MDEventWorkspace' or 'MDHistoWorkspace'.");
154 m_file->openGroup(entryName,
"NXentry");
158 if (
m_file->hasAttr(
"SaveMDVersion"))
165 std::vector<int32_t> vecDims;
166 m_file->readData(
"dimensions", vecDims);
168 throw std::runtime_error(
"LoadMD:: Error loading number of dimensions.");
171 throw std::runtime_error(
"LoadMD:: number of dimensions == 0.");
188 if (entryName ==
"MDEventWorkspace") {
190 std::string eventType;
191 m_file->getAttr(
"event_type", eventType);
207 auto prog = std::make_unique<Progress>(
this, 0.0, 0.1, 1);
208 prog->report(
"Load experiment information.");
209 bool lazyLoadExpt = fileBacked;
222 std::string pref_QConvention = Kernel::ConfigService::Instance().getString(
"Q.convention");
223 g_log.
information() <<
"Convention for Q in Preferences is " << pref_QConvention
224 <<
"; Convention of Q in NeXus file is " <<
m_QConvention <<
'\n';
231 transform_alg->setProperty(
"InputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
232 transform_alg->setProperty(
"Scaling", scaling);
233 transform_alg->executeAsChildAlg();
235 ws = std::dynamic_pointer_cast<IMDEventWorkspace>(
tmp);
238 setProperty(
"OutputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
253template <
typename NumT>
256 auto info =
m_file->getInfo();
257 if (info.type != dataType)
258 throw std::runtime_error(
"Unexpected data type " + std::string(dataType) +
" for '" +
name +
259 "' data set with type " + std::string(info.type) +
".");
262 const auto dataDims =
m_file->getInfo().dims;
264 const size_t numDims = dataDims.size();
265 for (
size_t d = 0;
d < numDims;
d++) {
266 nPoints *= dataDims[
d];
268 if (nPoints != ws->getNPoints())
269 throw std::runtime_error(
"Inconsistency between the number of points in '" +
name +
270 "' and the number of bins defined by the dimensions.");
276 g_log.
debug() <<
" failed to read data size: " << dataDims[0] <<
'\n';
292 ws = std::make_shared<MDHistoWorkspace>(
m_dims);
296 auto prog = std::make_unique<Progress>(
this, 0.0, 0.1, 1);
297 prog->report(
"Load experiment information.");
305 ws->history().loadNexus(
m_file.get());
311 m_file->openGroup(
"data",
"NXdata");
328 std::string pref_QConvention = Kernel::ConfigService::Instance().getString(
"Q.convention");
329 g_log.
information() <<
"Convention for Q in Preferences is " << pref_QConvention
330 <<
"; Convention of Q in NeXus file is " <<
m_QConvention <<
'\n';
337 transform_alg->setProperty(
"InputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
338 transform_alg->setProperty(
"Scaling", scaling);
339 transform_alg->executeAsChildAlg();
341 ws = std::dynamic_pointer_cast<MDHistoWorkspace>(
tmp);
345 setProperty(
"OutputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
355 std::ostringstream mess;
356 mess <<
"dimension" <<
d;
358 m_file->getAttr(mess.str(), dimXML);
371 using namespace Geometry;
376 m_file->openGroup(
"data",
"NXdata");
377 m_file->openData(
"signal");
378 m_file->getAttr(
"axes", axes);
381 std::vector<std::string> splitAxes;
382 boost::split(splitAxes, axes, boost::is_any_of(
":"));
385 for (
size_t d = splitAxes.size();
d > 0;
d--) {
386 std::string long_name;
389 std::vector<double> axis;
390 m_file->openData(splitAxes[
d - 1]);
391 m_file->getAttr(
"long_name", long_name);
392 m_file->getAttr(
"units", units);
394 m_file->getAttr(
"frame", frame);
395 }
catch (std::exception &) {
402 m_dims.emplace_back(std::make_shared<MDHistoDimension>(long_name, long_name, *mdFrame,
403 static_cast<coord_t>(axis.front()),
404 static_cast<coord_t>(axis.back()), axis.size() - 1));
411 std::optional<Mantid::API::MDNormalization> &normalization) {
413 uint32_t readVisualNormalization(0);
414 m_file->readData(key, readVisualNormalization);
418 }
catch (std::exception &) {
428 if (
m_file->hasData(
"coordinate_system")) {
429 uint32_t readCoord(0);
430 m_file->readData(
"coordinate_system", readCoord);
433 std::string addressOnEntry =
m_file->getAddress();
434 std::string newAddress = addressOnEntry +
"/experiment0/logs/CoordinateSystem";
435 if (
m_file->hasData(newAddress +
"/value")) {
437 m_file->openAddress(newAddress);
438 m_file->readData(
"value", readCoord);
441 m_file->openAddress(addressOnEntry);
450 }
catch (std::exception &) {
467 throw std::invalid_argument(
"Combination of BoxStructureOnly or "
468 "MetaDataOnly were set to TRUE with "
470 ": this is not possible.");
473 auto prog = std::make_unique<Progress>(
this, 0.0, 1.0, 100);
475 prog->report(
"Opening file.");
478 m_file->getAttr(
"title", title);
479 }
catch (std::exception &) {
494 for (
size_t d = 0;
d < nd;
d++)
502 prog->report(
"Reading box structure from HDD.");
504 auto nDims =
static_cast<int>(nd);
510 prog->report(
"Restoring box structure and connectivity");
511 std::vector<API::IMDNode *> boxTree;
513 size_t numBoxes = boxTree.size();
530 mb = double(10 * loader->getDataChunk() *
sizeof(
MDE)) / double(1024 * 1024);
533 uint64_t cacheMemory =
static_cast<uint64_t
>((mb * 1024. * 1024.) /
sizeof(
MDE)) + 1;
536 bc->getFileIO()->setWriteBufferSize(cacheMemory);
538 g_log.
information() <<
"Setting a DiskBuffer cache size of " << mb <<
" MB, or " << cacheMemory <<
" events.\n";
549 const std::vector<uint64_t> &BoxEventIndex = FlatBoxTree.
getEventIndex();
550 prog->setNumSteps(numBoxes);
551 std::vector<coord_t> boxTemp;
553 for (
size_t i = 0; i < numBoxes; i++) {
559 if (BoxEventIndex[2 * i + 1] > 0)
562 boxTree[i]->loadAndAddFrom(loader.get(), BoxEventIndex[2 * i],
static_cast<size_t>(BoxEventIndex[2 * i + 1]),
570 g_log.
debug() << tim <<
" to create all the boxes and fill them with events.\n";
575 bc->setMaxId(numBoxes);
581 g_log.
debug() << tim <<
" to refreshCache(). " << ws->
getNPoints() <<
" points after refresh.\n";
592 std::map<std::string, std::string> entries;
593 m_file->getEntries(entries);
595 if (entries.find(
"transform_to_orig") != entries.end()) {
597 ws->setTransformToOriginal(transform);
599 if (entries.find(
"transform_from_orig") != entries.end()) {
601 ws->setTransformFromOriginal(transform);
613 m_file->openData(entry_name);
614 std::vector<coord_t>
vec;
619 m_file->getAttr(
"type", type);
620 m_file->getAttr<
int>(
"rows", outD);
621 m_file->getAttr<
int>(
"columns", inD);
628 if ((
"CoordTransformAffine" == type) || (
"CoordTransformAligned" == type)) {
630 affine->setMatrix(mat);
633 g_log.
information(
"Do not know how to process coordinate transform " + type);
644 g_log.
information() <<
"LoadMD: Encountered a legacy file which has a mismatch between "
645 "its MDFrames and its Special Coordinate System. "
646 "Attempting to convert MDFrames.\n";
647 auto numberOfDimensions = ws->getNumDims();
652 std::string selectedFrame;
673 oldFrames[
index] = ws->getDimension(
index)->getMDFrame().name();
679 auto fillUpTo = numberOfDimensions > 3 ? 3 : numberOfDimensions;
680 std::fill_n(framesToSet.begin(), fillUpTo, selectedFrame);
686 for (
auto &frame : framesToSet) {
687 setMDFrameAlg->setProperty(
"InputWorkspace", ws);
688 setMDFrameAlg->setProperty(
"MDFrame", frame);
689 setMDFrameAlg->setProperty(
"Axes", std::vector<int>(1, axesCounter));
691 setMDFrameAlg->executeAsChildAlg();
694 g_log.
warning() <<
"LoadMD: An issue occured while trying to correct "
695 "MDFrames. Trying to revert to original.\n";
699 for (
auto &oldFrame : oldFrames) {
700 setMDFrameAlg->setProperty(
"InputWorkspace", ws);
701 setMDFrameAlg->setProperty(
"MDFrame", oldFrame);
702 setMDFrameAlg->setProperty(
"Axes", std::vector<int>(1, axesCounter));
704 setMDFrameAlg->executeAsChildAlg();
716 auto isQBasedSpecialCoordinateSystem =
true;
718 isQBasedSpecialCoordinateSystem =
false;
722 auto containsOnlyUnkownFrames =
true;
725 containsOnlyUnkownFrames =
false;
731 if (isQBasedSpecialCoordinateSystem && containsOnlyUnkownFrames) {
742 std::string dimd = ws->getDimension(
d)->getName();
747 boost::regex re(
"\\[.*|Q_");
748 if (boost::regex_search(dimd.begin(), dimd.begin() + 2, re))
std::map< DeltaEMode::Type, std::string > index
std::unique_ptr< Mantid::Nexus::File > file_holder_type
#define CALL_MDEVENT_FUNCTION(funcname, workspace)
Macro that makes it possible to call a templated method for a MDEventWorkspace using a IMDEventWorksp...
std::vector< T > const * vec
#define DECLARE_NEXUS_FILELOADER_ALGORITHM(classname)
DECLARE_NEXUS_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro wh...
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
@ Load
allowed here which will be passed to the algorithm
void addDimension(const std::shared_ptr< Mantid::Geometry::IMDDimension > &dim)
Add a dimension.
virtual const std::shared_ptr< Mantid::Nexus::NexusDescriptor > getFileInfo() const noexcept
Required to pass m_fileInfo to static functions Keeping it shared_ptr to match setFileInfo signature ...
std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1) override
Create a Child Algorithm.
void loadNexus(Nexus::File *file)
Load the workspace history from a nexus file.
A property class for workspaces.
WorkspaceHistory & history()
Returns a reference to the WorkspaceHistory.
virtual void setTitle(const std::string &)
Set the title of the workspace.
The class responsible for saving events into nexus file using generic box controller interface Expect...
The class responsible for saving/loading MD boxes structure to/from HDD and for flattening/restoring ...
uint64_t restoreBoxTree(std::vector< API::IMDNode * > &Boxes, API::BoxController_sptr &bc, bool FileBackEnd, bool BoxStructureOnly=false)
Method recovers the interconnected box structure from the plain tree into box tree,...
static void loadExperimentInfos(Mantid::Nexus::File *const file, const std::string &filename, std::shared_ptr< API::MultipleExperimentInfos > mei, const Mantid::Nexus::NexusDescriptor &fileInfo, const std::string ¤tGroup, bool lazy=false)
const std::string & getBCXMLdescr() const
void loadBoxStructure(const std::string &fileName, int &nDim, const std::string &EventType, bool onlyEventInfo=false, bool restoreExperimentInfo=false)
load box structure from the file, defined by file name
std::vector< uint64_t > & getEventIndex()
Templated class for a multi-dimensional event "box".
void reserveMemoryForLoad(uint64_t) override
Reserve all the memory required for loading in one step.
static API::IMDEventWorkspace_sptr CreateMDWorkspace(size_t nd, const std::string &eventType="MDLeanEvent", const Mantid::API::MDNormalization &preferredNormalization=Mantid::API::MDNormalization::VolumeNormalization, const Mantid::API::MDNormalization &preferredNormalizationHisto=Mantid::API::MDNormalization::VolumeNormalization)
Create a MDEventWorkspace of the given type.
std::shared_ptr< MDEventWorkspace< MDE, nd > > sptr
Typedef for a shared pointer of this kind of event workspace.
void refreshCache() override
Refresh the cache of # of points, signal, and error.
void setCoordinateSystem(const Kernel::SpecialCoordinateSystem coordSystem) override
Set the coordinate system.
uint64_t getNPoints() const override
Returns the total number of points (events) in this workspace.
void setBox(API::IMDNode *box) override
Set the base-level box contained within.
Mantid::API::BoxController_sptr getBoxController() override
Returns the BoxController used in this workspace.
Templated class holding data about a neutron detection event in N-dimensions (for example,...
static std::string getTypeName()
static const std::string GeneralFrameName
static const std::string HKLName
Input argument type for MDFrameFactory chainable factory.
static const std::string QLabName
static const std::string QSampleName
static const std::string UnknownFrameName
CPUTimer : Timer that uses the CPU time, rather than wall-clock time to measure execution time.
Records the filename and the description of failure.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
void debug(const std::string &msg)
Logs at debug level.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
The concrete, templated class for properties.
Load a .nxs file into a MDEventWorkspace.
std::vector< double > qDimensions(const API::IMDWorkspace_sptr &ws)
Negative scaling for Q dimensions.
void loadDimensions()
Load all the dimensions into this->m_dims.
boost::scoped_ptr< Nexus::File > m_file
Open file handle.
void checkForRequiredLegacyFixup(const API::IMDWorkspace_sptr &ws)
Checks if a worspace is a certain type of legacy file.
std::vector< Mantid::Geometry::IMDDimension_sptr > m_dims
Each dimension object loaded.
API::CoordTransform * loadAffineMatrix(const std::string &entry_name)
Load a given affine matrix.
Kernel::SpecialCoordinateSystem m_coordSystem
Coordinate system.
void loadSlab(const std::string &name, NumT *data, const DataObjects::MDHistoWorkspace_sptr &ws, NXnumtype dataType)
Load a slab of double data into a bare array.
void doLoad(typename DataObjects::MDEventWorkspace< MDE, nd >::sptr ws)
Helper method.
void loadVisualNormalization(const std::string &key, std::optional< Mantid::API::MDNormalization > &normalization)
void init() override
Initialise the properties.
bool m_requiresMDFrameCorrection
MDFrame correction flag.
void loadCoordinateSystem()
Load the coordinate system.
std::string m_QConvention
QConvention.
std::string m_filename
Name of that file.
int confidence(Nexus::NexusDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
std::optional< Mantid::API::MDNormalization > m_visualNormalizationHisto
void loadHisto()
Perform loading for a MDHistoWorkspace.
int m_saveMDVersion
Version of SaveMD used to save the file.
void loadAffineMatricies(const API::IMDWorkspace_sptr &ws)
Load all the affine matricies.
bool m_BoxStructureAndMethadata
load only the box structure with empty boxes but do not tload boxes events
std::optional< Mantid::API::MDNormalization > m_visualNormalization
Visual normalization.
static const std::string VISUAL_NORMALIZATION_KEY_HISTO
static const std::string VISUAL_NORMALIZATION_KEY
Named entry.
void loadDimensions2()
Load all the dimensions into this->m_dims The dimensions are stored as an nxData array.
void execLoader() override
Run the algorithm.
void setMDFrameOnWorkspaceFromLegacyFile(const API::IMDWorkspace_sptr &ws)
Sets MDFrames for workspaces from legacy files.
const std::string name() const override
Algorithm's name for identification.
size_t m_numDims
Number of dimensions in loaded file.
void loadQConvention()
Load the convention for Q
Class that provides for a standard Nexus exception.
const std::map< std::string, std::set< std::string > > & getAllEntries() const noexcept
Returns a const reference of the internal map holding all entries in the Nexus HDF5 file.
bool isEntry(const std::string &entryName, const std::string &groupClass) const noexcept
Checks if a full-address entry exists for a particular groupClass in a Nexus dataset.
The primitive types published by this API.
static unsigned short constexpr INT8
static unsigned short constexpr FLOAT64
std::shared_ptr< IMDEventWorkspace > IMDEventWorkspace_sptr
Shared pointer to Mantid::API::IMDEventWorkspace.
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< IMDWorkspace > IMDWorkspace_sptr
Shared pointer to the IMDWorkspace base class.
std::shared_ptr< BoxController > BoxController_sptr
Shared ptr to BoxController.
MDNormalization
Enum describing different ways to normalize the signal in a MDWorkspace.
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
std::shared_ptr< MDHistoWorkspace > MDHistoWorkspace_sptr
A shared pointer to a MDHistoWorkspace.
MANTID_GEOMETRY_DLL IMDDimension_sptr createDimension(const std::string &dimensionXMLString)
Creates IMDDimension objects based on input XML.
std::unique_ptr< const MDFrame > MDFrame_const_uptr
MDFrameFactory_uptr MANTID_GEOMETRY_DLL makeMDFrameFactoryChain()
Make a complete factory chain.
SpecialCoordinateSystem
Special coordinate systems for Q3D.
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
@ Output
An output workspace.