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) {}
66 if (descriptor.
isEntry(
"/MDEventWorkspace") || descriptor.
isEntry(
"/MDHistoWorkspace")) {
80 "The name of the Nexus file to load, as a full or relative path");
83 "Load Box structure and other metadata without events. The "
84 "loaded workspace will be empty and not file-backed.");
87 "Load partial information about the boxes and events. Redundant property "
88 "currently equivalent to MetadataOnly");
91 "Set to true to load the data only on demand.");
95 "For FileBackEnd only: the amount of memory (in MB) to allocate to the "
97 "If not specified, a default of 40% of free physical memory is used.");
100 declareProperty(
"LoadHistory",
true,
"If true, the workspace history will be loaded");
103 "Name of the output MDEventWorkspace.");
111 convention = Kernel::ConfigService::Instance().getString(
"Q.convention");
113 bool fileBacked = this->
getProperty(
"FileBackEnd");
117 bool BoxAndEventInfoOnly = this->
getProperty(
"BoxStructureOnly");
125 std::string for_access;
128 for_access =
"for Read/Write access";
131 for_access =
"for Read access";
138 std::string entryName;
139 if (
m_file->hasGroup(
"/MDEventWorkspace",
"NXentry")) {
140 entryName =
"MDEventWorkspace";
141 }
else if (
m_file->hasGroup(
"/MDHistoWorkspace",
"NXentry")) {
142 entryName =
"MDHistoWorkspace";
144 throw std::runtime_error(
"Unexpected NXentry name. Expected "
145 "'MDEventWorkspace' or 'MDHistoWorkspace'.");
149 m_file->openGroup(entryName,
"NXentry");
153 if (
m_file->hasAttr(
"SaveMDVersion"))
160 std::vector<int32_t> vecDims;
161 m_file->readData(
"dimensions", vecDims);
163 throw std::runtime_error(
"LoadMD:: Error loading number of dimensions.");
166 throw std::runtime_error(
"LoadMD:: number of dimensions == 0.");
183 if (entryName ==
"MDEventWorkspace") {
185 std::string eventType;
186 m_file->getAttr(
"event_type", eventType);
202 auto prog = std::make_unique<Progress>(
this, 0.0, 0.1, 1);
203 prog->report(
"Load experiment information.");
204 bool lazyLoadExpt = fileBacked;
217 std::string pref_QConvention = Kernel::ConfigService::Instance().getString(
"Q.convention");
218 g_log.
information() <<
"Convention for Q in Preferences is " << pref_QConvention
219 <<
"; Convention of Q in NeXus file is " <<
m_QConvention <<
'\n';
226 transform_alg->setProperty(
"InputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
227 transform_alg->setProperty(
"Scaling", scaling);
228 transform_alg->executeAsChildAlg();
230 ws = std::dynamic_pointer_cast<IMDEventWorkspace>(
tmp);
233 setProperty(
"OutputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
248template <
typename NumT>
251 auto info =
m_file->getInfo();
252 if (info.type != dataType)
253 throw std::runtime_error(
"Unexpected data type " + std::string(dataType) +
" for '" +
name +
254 "' data set with type " + std::string(info.type) +
".");
257 const auto dataDims =
m_file->getInfo().dims;
259 const size_t numDims = dataDims.size();
260 for (
size_t d = 0;
d < numDims;
d++) {
261 nPoints *= dataDims[
d];
263 if (nPoints != ws->getNPoints())
264 throw std::runtime_error(
"Inconsistency between the number of points in '" +
name +
265 "' and the number of bins defined by the dimensions.");
271 g_log.
debug() <<
" failed to read data size: " << dataDims[0] <<
'\n';
287 ws = std::make_shared<MDHistoWorkspace>(
m_dims);
291 auto prog = std::make_unique<Progress>(
this, 0.0, 0.1, 1);
292 prog->report(
"Load experiment information.");
300 ws->history().loadNexus(
m_file.get());
306 m_file->openGroup(
"data",
"NXdata");
323 std::string pref_QConvention = Kernel::ConfigService::Instance().getString(
"Q.convention");
324 g_log.
information() <<
"Convention for Q in Preferences is " << pref_QConvention
325 <<
"; Convention of Q in NeXus file is " <<
m_QConvention <<
'\n';
332 transform_alg->setProperty(
"InputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
333 transform_alg->setProperty(
"Scaling", scaling);
334 transform_alg->executeAsChildAlg();
336 ws = std::dynamic_pointer_cast<MDHistoWorkspace>(
tmp);
340 setProperty(
"OutputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
350 std::ostringstream mess;
351 mess <<
"dimension" <<
d;
353 m_file->getAttr(mess.str(), dimXML);
366 using namespace Geometry;
371 m_file->openGroup(
"data",
"NXdata");
372 m_file->openData(
"signal");
373 m_file->getAttr(
"axes", axes);
376 std::vector<std::string> splitAxes;
377 boost::split(splitAxes, axes, boost::is_any_of(
":"));
380 for (
size_t d = splitAxes.size();
d > 0;
d--) {
381 std::string long_name;
384 std::vector<double> axis;
385 m_file->openData(splitAxes[
d - 1]);
386 m_file->getAttr(
"long_name", long_name);
387 m_file->getAttr(
"units", units);
389 m_file->getAttr(
"frame", frame);
390 }
catch (std::exception &) {
397 m_dims.emplace_back(std::make_shared<MDHistoDimension>(long_name, long_name, *mdFrame,
398 static_cast<coord_t>(axis.front()),
399 static_cast<coord_t>(axis.back()), axis.size() - 1));
406 std::optional<Mantid::API::MDNormalization> &normalization) {
408 uint32_t readVisualNormalization(0);
409 m_file->readData(key, readVisualNormalization);
413 }
catch (std::exception &) {
423 if (
m_file->hasData(
"coordinate_system")) {
424 uint32_t readCoord(0);
425 m_file->readData(
"coordinate_system", readCoord);
428 std::string
const addressOnEntry =
m_file->getAddress();
429 std::string
const newAddress = addressOnEntry +
"/experiment0/logs/CoordinateSystem";
430 if (
m_file->hasData(newAddress +
"/value")) {
432 m_file->openAddress(newAddress);
433 m_file->readData(
"value", readCoord);
436 m_file->openAddress(addressOnEntry);
445 }
catch (std::exception &) {
462 throw std::invalid_argument(
"Combination of BoxStructureOnly or "
463 "MetaDataOnly were set to TRUE with "
465 ": this is not possible.");
468 auto prog = std::make_unique<Progress>(
this, 0.0, 1.0, 100);
470 prog->report(
"Opening file.");
473 m_file->getAttr(
"title", title);
474 }
catch (std::exception &) {
489 for (
size_t d = 0;
d < nd;
d++)
497 prog->report(
"Reading box structure from HDD.");
499 auto nDims =
static_cast<int>(nd);
505 prog->report(
"Restoring box structure and connectivity");
506 std::vector<API::IMDNode *> boxTree;
508 size_t numBoxes = boxTree.size();
525 mb = double(10 * loader->getDataChunk() *
sizeof(
MDE)) / double(1024 * 1024);
528 uint64_t cacheMemory =
static_cast<uint64_t
>((mb * 1024. * 1024.) /
sizeof(
MDE)) + 1;
531 bc->getFileIO()->setWriteBufferSize(cacheMemory);
533 g_log.
information() <<
"Setting a DiskBuffer cache size of " << mb <<
" MB, or " << cacheMemory <<
" events.\n";
544 const std::vector<uint64_t> &BoxEventIndex = FlatBoxTree.
getEventIndex();
545 prog->setNumSteps(numBoxes);
546 std::vector<coord_t> boxTemp;
548 for (
size_t i = 0; i < numBoxes; i++) {
554 if (BoxEventIndex[2 * i + 1] > 0)
557 boxTree[i]->loadAndAddFrom(loader.get(), BoxEventIndex[2 * i],
static_cast<size_t>(BoxEventIndex[2 * i + 1]),
565 g_log.
debug() << tim <<
" to create all the boxes and fill them with events.\n";
570 bc->setMaxId(numBoxes);
576 g_log.
debug() << tim <<
" to refreshCache(). " << ws->
getNPoints() <<
" points after refresh.\n";
587 std::map<std::string, std::string> entries;
588 m_file->getEntries(entries);
590 if (entries.find(
"transform_to_orig") != entries.end()) {
592 ws->setTransformToOriginal(transform);
594 if (entries.find(
"transform_from_orig") != entries.end()) {
596 ws->setTransformFromOriginal(transform);
608 m_file->openData(entry_name);
609 std::vector<coord_t>
vec;
614 m_file->getAttr(
"type", type);
615 m_file->getAttr<
int>(
"rows", outD);
616 m_file->getAttr<
int>(
"columns", inD);
623 if ((
"CoordTransformAffine" == type) || (
"CoordTransformAligned" == type)) {
625 affine->setMatrix(mat);
628 g_log.
information(
"Do not know how to process coordinate transform " + type);
639 g_log.
information() <<
"LoadMD: Encountered a legacy file which has a mismatch between "
640 "its MDFrames and its Special Coordinate System. "
641 "Attempting to convert MDFrames.\n";
642 auto numberOfDimensions = ws->getNumDims();
647 std::string selectedFrame;
668 oldFrames[
index] = ws->getDimension(
index)->getMDFrame().name();
674 auto fillUpTo = numberOfDimensions > 3 ? 3 : numberOfDimensions;
675 std::fill_n(framesToSet.begin(), fillUpTo, selectedFrame);
681 for (
auto &frame : framesToSet) {
682 setMDFrameAlg->setProperty(
"InputWorkspace", ws);
683 setMDFrameAlg->setProperty(
"MDFrame", frame);
684 setMDFrameAlg->setProperty(
"Axes", std::vector<int>(1, axesCounter));
686 setMDFrameAlg->executeAsChildAlg();
689 g_log.
warning() <<
"LoadMD: An issue occured while trying to correct "
690 "MDFrames. Trying to revert to original.\n";
694 for (
auto &oldFrame : oldFrames) {
695 setMDFrameAlg->setProperty(
"InputWorkspace", ws);
696 setMDFrameAlg->setProperty(
"MDFrame", oldFrame);
697 setMDFrameAlg->setProperty(
"Axes", std::vector<int>(1, axesCounter));
699 setMDFrameAlg->executeAsChildAlg();
711 auto isQBasedSpecialCoordinateSystem =
true;
713 isQBasedSpecialCoordinateSystem =
false;
717 auto containsOnlyUnkownFrames =
true;
720 containsOnlyUnkownFrames =
false;
726 if (isQBasedSpecialCoordinateSystem && containsOnlyUnkownFrames) {
737 std::string dimd = ws->getDimension(
d)->getName();
742 boost::regex re(
"\\[.*|Q_");
743 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_LAZY_FILELOADER_ALGORITHM(classname)
DECLARE_NEXUS_LAZY_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.
virtual 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)
Create a Child Algorithm.
@ Load
allowed here which will be passed to the algorithm
void addDimension(const std::shared_ptr< Mantid::Geometry::IMDDimension > &dim)
Add a dimension.
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(Mantid::Nexus::File *const file, const std::string &filename, std::shared_ptr< API::MultipleExperimentInfos > mei, const std::string ¤tGroup, bool lazy=false)
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 const > settings)
Add a PropertySettings instance to the chain of settings for a given property.
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.
int confidence(Nexus::NexusDescriptorLazy &descriptor) const override
Returns a confidence value that this algorithm can load a file.
void loadCoordinateSystem()
Load the coordinate system.
std::string m_QConvention
QConvention.
std::string m_filename
Name of that file.
void exec() override
Run the algorithm.
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 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.
bool isEntry(std::string const &entryName, std::string const &groupClass) const
Checks if a full-address entry exists for a particular groupClass in a Nexus dataset.
bool classTypeExists(std::string const &classType) const
Query if a given type exists somewhere in the file.
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.
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.