34#include <boost/algorithm/string.hpp>
35#include <boost/regex.hpp>
36#include <nexus/NeXusException.hpp>
55 m_coordSystem(
None), m_BoxStructureAndMethadata(true),
56 m_saveMDVersion(false), m_requiresMDFrameCorrection(false) {}
66 const std::map<std::string, std::set<std::string>> &allEntries = descriptor.
getAllEntries();
67 if (allEntries.count(
"NXentry") == 1) {
68 if (descriptor.
isEntry(
"/MDEventWorkspace") || descriptor.
isEntry(
"/MDHistoWorkspace")) {
83 "The name of the Nexus file to load, as a full or relative path");
86 "Load Box structure and other metadata without events. The "
87 "loaded workspace will be empty and not file-backed.");
90 "Load partial information about the boxes and events. Redundant property "
91 "currently equivalent to MetadataOnly");
94 "Set to true to load the data only on demand.");
98 "For FileBackEnd only: the amount of memory (in MB) to allocate to the "
100 "If not specified, a default of 40% of free physical memory is used.");
103 declareProperty(
"LoadHistory",
true,
"If true, the workspace history will be loaded");
106 "Name of the output MDEventWorkspace.");
116 bool fileBacked = this->
getProperty(
"FileBackEnd");
120 bool BoxAndEventInfoOnly = this->
getProperty(
"BoxStructureOnly");
128 std::string for_access;
131 for_access =
"for Read/Write access";
134 for_access =
"for Read access";
142 const std::shared_ptr<Mantid::Kernel::NexusHDF5Descriptor> fileInfo =
getFileInfo();
144 std::string entryName;
145 if (fileInfo->isEntry(
"/MDEventWorkspace",
"NXentry")) {
146 entryName =
"MDEventWorkspace";
147 }
else if (fileInfo->isEntry(
"/MDHistoWorkspace",
"NXentry")) {
148 entryName =
"MDHistoWorkspace";
150 throw std::runtime_error(
"Unexpected NXentry name. Expected "
151 "'MDEventWorkspace' or 'MDHistoWorkspace'.");
155 m_file->openGroup(entryName,
"NXentry");
159 if (
m_file->hasAttr(
"SaveMDVersion"))
166 std::vector<int32_t> vecDims;
167 m_file->readData(
"dimensions", vecDims);
169 throw std::runtime_error(
"LoadMD:: Error loading number of dimensions.");
172 throw std::runtime_error(
"LoadMD:: number of dimensions == 0.");
189 if (entryName ==
"MDEventWorkspace") {
191 std::string eventType;
192 m_file->getAttr(
"event_type", eventType);
208 bool lazyLoadExpt = fileBacked;
222 g_log.
information() <<
"Convention for Q in Preferences is " << pref_QConvention
223 <<
"; Convention of Q in NeXus file is " <<
m_QConvention <<
'\n';
230 transform_alg->setProperty(
"InputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
231 transform_alg->setProperty(
"Scaling", scaling);
232 transform_alg->executeAsChildAlg();
234 ws = std::dynamic_pointer_cast<IMDEventWorkspace>(
tmp);
237 setProperty(
"OutputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
253 ::NeXus::NXnumtype dataType) {
255 if (
m_file->getInfo().type != dataType)
256 throw std::runtime_error(
"Unexpected data type for '" +
name +
"' data set.'");
259 size_t numDims =
m_file->getInfo().dims.size();
260 std::vector<int> size(numDims);
261 for (
size_t d = 0;
d < numDims;
d++) {
262 nPoints *=
static_cast<int>(
m_file->getInfo().dims[
d]);
263 size[
d] =
static_cast<int>(
m_file->getInfo().dims[
d]);
265 if (nPoints !=
static_cast<int>(ws->getNPoints()))
266 throw std::runtime_error(
"Inconsistency between the number of points in '" +
name +
267 "' and the number of bins defined by the dimensions.");
268 std::vector<int> start(numDims, 0);
270 m_file->getSlab(data, start, size);
272 g_log.
debug() <<
" start: " << start[0] <<
" size: " << size[0] <<
'\n';
288 ws = std::make_shared<MDHistoWorkspace>(
m_dims);
299 ws->history().loadNexus(
m_file.get());
305 m_file->openGroup(
"data",
"NXdata");
307 this->
loadSlab(
"signal", ws->mutableSignalArray(), ws, ::NeXus::FLOAT64);
308 this->
loadSlab(
"errors_squared", ws->mutableErrorSquaredArray(), ws, ::NeXus::FLOAT64);
309 this->
loadSlab(
"num_events", ws->mutableNumEventsArray(), ws, ::NeXus::FLOAT64);
310 this->
loadSlab(
"mask", ws->mutableMaskArray(), ws, ::NeXus::INT8);
323 g_log.
information() <<
"Convention for Q in Preferences is " << pref_QConvention
324 <<
"; Convention of Q in NeXus file is " <<
m_QConvention <<
'\n';
331 transform_alg->setProperty(
"InputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
332 transform_alg->setProperty(
"Scaling", scaling);
333 transform_alg->executeAsChildAlg();
335 ws = std::dynamic_pointer_cast<MDHistoWorkspace>(
tmp);
339 setProperty(
"OutputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
349 std::ostringstream mess;
350 mess <<
"dimension" <<
d;
352 m_file->getAttr(mess.str(), dimXML);
365 using namespace Geometry;
370 m_file->openGroup(
"data",
"NXdata");
371 m_file->openData(
"signal");
372 m_file->getAttr(
"axes", axes);
375 std::vector<std::string> splitAxes;
376 boost::split(splitAxes, axes, boost::is_any_of(
":"));
379 for (
size_t d = splitAxes.size();
d > 0;
d--) {
380 std::string long_name;
383 std::vector<double> axis;
384 m_file->openData(splitAxes[
d - 1]);
385 m_file->getAttr(
"long_name", long_name);
386 m_file->getAttr(
"units", units);
388 m_file->getAttr(
"frame", frame);
389 }
catch (std::exception &) {
396 m_dims.emplace_back(std::make_shared<MDHistoDimension>(long_name, splitAxes[
d - 1], *mdFrame,
397 static_cast<coord_t>(axis.front()),
398 static_cast<coord_t>(axis.back()), axis.size() - 1));
405 boost::optional<Mantid::API::MDNormalization> &normalization) {
407 uint32_t readVisualNormalization(0);
408 m_file->readData(key, readVisualNormalization);
410 }
catch (::NeXus::Exception &) {
412 }
catch (std::exception &) {
423 uint32_t readCoord(0);
424 m_file->readData(
"coordinate_system", readCoord);
426 }
catch (::NeXus::Exception &) {
427 auto pathOnEntry =
m_file->getPath();
429 m_file->openPath(pathOnEntry +
"/experiment0/logs/CoordinateSystem");
431 m_file->readData(
"value", readCoord);
433 }
catch (::NeXus::Exception &) {
436 m_file->openPath(pathOnEntry);
444 }
catch (std::exception &) {
461 throw std::invalid_argument(
"Combination of BoxStructureOnly or "
462 "MetaDataOnly were set to TRUE with "
464 ": this is not possible.");
467 auto prog = std::make_unique<Progress>(
this, 0.0, 1.0, 100);
469 prog->report(
"Opening file.");
472 m_file->getAttr(
"title", title);
473 }
catch (std::exception &) {
488 for (
size_t d = 0;
d < nd;
d++)
496 prog->report(
"Reading box structure from HDD.");
498 auto nDims =
static_cast<int>(nd);
504 prog->report(
"Restoring box structure and connectivity");
505 std::vector<API::IMDNode *> boxTree;
507 size_t numBoxes = boxTree.size();
524 mb = double(10 * loader->getDataChunk() *
sizeof(
MDE)) / double(1024 * 1024);
527 uint64_t cacheMemory =
static_cast<uint64_t
>((mb * 1024. * 1024.) /
sizeof(
MDE)) + 1;
530 bc->getFileIO()->setWriteBufferSize(cacheMemory);
532 g_log.
information() <<
"Setting a DiskBuffer cache size of " << mb <<
" MB, or " << cacheMemory <<
" events.\n";
543 const std::vector<uint64_t> &BoxEventIndex = FlatBoxTree.
getEventIndex();
544 prog->setNumSteps(numBoxes);
545 std::vector<coord_t> boxTemp;
547 for (
size_t i = 0; i < numBoxes; i++) {
553 if (BoxEventIndex[2 * i + 1] > 0)
556 boxTree[i]->loadAndAddFrom(loader.get(), BoxEventIndex[2 * i],
static_cast<size_t>(BoxEventIndex[2 * i + 1]),
564 g_log.
debug() << tim <<
" to create all the boxes and fill them with events.\n";
569 bc->setMaxId(numBoxes);
575 g_log.
debug() << tim <<
" to refreshCache(). " << ws->
getNPoints() <<
" points after refresh.\n";
586 std::map<std::string, std::string> entries;
587 m_file->getEntries(entries);
589 if (entries.find(
"transform_to_orig") != entries.end()) {
591 ws->setTransformToOriginal(transform);
593 if (entries.find(
"transform_from_orig") != entries.end()) {
595 ws->setTransformFromOriginal(transform);
607 m_file->openData(entry_name);
608 std::vector<coord_t> vec;
613 m_file->getAttr(
"type", type);
614 m_file->getAttr<
int>(
"rows", outD);
615 m_file->getAttr<
int>(
"columns", inD);
622 if ((
"CoordTransformAffine" == type) || (
"CoordTransformAligned" == type)) {
624 affine->setMatrix(mat);
627 g_log.
information(
"Do not know how to process coordinate transform " + type);
638 g_log.
information() <<
"LoadMD: Encountered a legacy file which has a mismatch between "
639 "its MDFrames and its Special Coordinate System. "
640 "Attempting to convert MDFrames.\n";
641 auto numberOfDimensions = ws->getNumDims();
646 std::string selectedFrame;
667 oldFrames[
index] = ws->getDimension(
index)->getMDFrame().name();
673 auto fillUpTo = numberOfDimensions > 3 ? 3 : numberOfDimensions;
674 std::fill_n(framesToSet.begin(), fillUpTo, selectedFrame);
680 for (
auto &frame : framesToSet) {
681 setMDFrameAlg->setProperty(
"InputWorkspace", ws);
682 setMDFrameAlg->setProperty(
"MDFrame", frame);
683 setMDFrameAlg->setProperty(
"Axes", std::vector<int>(1, axesCounter));
685 setMDFrameAlg->executeAsChildAlg();
688 g_log.
warning() <<
"LoadMD: An issue occured while trying to correct "
689 "MDFrames. Trying to revert to original.\n";
693 for (
auto &oldFrame : oldFrames) {
694 setMDFrameAlg->setProperty(
"InputWorkspace", ws);
695 setMDFrameAlg->setProperty(
"MDFrame", oldFrame);
696 setMDFrameAlg->setProperty(
"Axes", std::vector<int>(1, axesCounter));
698 setMDFrameAlg->executeAsChildAlg();
710 auto isQBasedSpecialCoordinateSystem =
true;
712 isQBasedSpecialCoordinateSystem =
false;
716 auto containsOnlyUnkownFrames =
true;
719 containsOnlyUnkownFrames =
false;
725 if (isQBasedSpecialCoordinateSystem && containsOnlyUnkownFrames) {
736 std::string dimd = ws->getDimension(
d)->getName();
741 boost::regex re(
"\\[.*|Q_");
742 if (boost::regex_search(dimd.begin(), dimd.begin() + 2, re))
std::map< DeltaEMode::Type, std::string > index
std::unique_ptr<::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...
#define DECLARE_NEXUS_HDF5_FILELOADER_ALGORITHM(classname)
DECLARE_NEXUS_HDF5_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM mac...
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::Kernel::NexusHDF5Descriptor > 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,...
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()
static void loadExperimentInfos(::NeXus::File *const file, const std::string &filename, std::shared_ptr< API::MultipleExperimentInfos > mei, const Mantid::Kernel::NexusHDF5Descriptor &fileInfo, const std::string ¤tGroup, bool lazy=false)
Templated class for a multi-dimensional event "box".
void reserveMemoryForLoad(uint64_t) override
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.
uint64_t getNPoints() const override
std::shared_ptr< MDEventWorkspace< MDE, nd > > sptr
Typedef for a shared pointer of this kind of event workspace.
void setCoordinateSystem(const Kernel::SpecialCoordinateSystem coordSystem) override
Set the coordinate system.
void refreshCache() override
Refresh the cache (integrated signal of each box)
Mantid::API::BoxController_sptr getBoxController() override
Returns the BoxController used in this workspace.
void setBox(API::IMDNode *box) override
Set the base-level box contained within.
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.
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-path entry exists for a particular groupClass in a Nexus dataset.
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
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.
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.
int confidence(Kernel::NexusHDF5Descriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
API::CoordTransform * loadAffineMatrix(const std::string &entry_name)
Load a given affine matrix.
Kernel::SpecialCoordinateSystem m_coordSystem
Coordinate system.
void doLoad(typename DataObjects::MDEventWorkspace< MDE, nd >::sptr ws)
Helper method.
void loadSlab(const std::string &name, void *data, const DataObjects::MDHistoWorkspace_sptr &ws, ::NeXus::NXnumtype dataType)
Load a slab of double data into a bare array.
boost::optional< Mantid::API::MDNormalization > m_visualNormalizationHisto
void init() override
Initialise the properties.
bool m_requiresMDFrameCorrection
MDFrame correction flag.
void loadCoordinateSystem()
Load the coordinate system.
boost::scoped_ptr< ::NeXus::File > m_file
Open file handle.
std::string m_QConvention
QConvention.
std::string m_filename
Name of that file.
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
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 loadVisualNormalization(const std::string &key, boost::optional< Mantid::API::MDNormalization > &normalization)
void execLoader() override
Run the algorithm.
void setMDFrameOnWorkspaceFromLegacyFile(const API::IMDWorkspace_sptr &ws)
Sets MDFrames for workspaces from legacy files.
boost::optional< Mantid::API::MDNormalization > m_visualNormalization
Visual normalization.
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
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.