Mantid
Loading...
Searching...
No Matches
LoadMD.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 +
28#include "MantidKernel/MDUnit.h"
30#include "MantidKernel/Memory.h"
34#include <boost/algorithm/string.hpp>
35#include <boost/regex.hpp>
36#include <vector>
37
38using namespace Mantid::Kernel;
39using namespace Mantid::API;
40using namespace Mantid::Geometry;
41using namespace Mantid::DataObjects;
42
43using file_holder_type = std::unique_ptr<Mantid::DataObjects::BoxControllerNeXusIO>;
44
45namespace Mantid::MDAlgorithms {
46
48
49//----------------------------------------------------------------------------------------------
53 : m_numDims(0), // uninitialized incorrect value
54 m_coordSystem(None), m_BoxStructureAndMethadata(true), // this is faster but rarely needed.
55 m_saveMDVersion(false), m_requiresMDFrameCorrection(false) {}
56
64 int confidence = 0;
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")) {
68 confidence = 95;
69 }
70 }
71
72 return confidence;
73}
74
75//----------------------------------------------------------------------------------------------
76
77//----------------------------------------------------------------------------------------------
81 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, ".nxs"),
82 "The name of the Nexus file to load, as a full or relative path");
83
84 declareProperty(std::make_unique<Kernel::PropertyWithValue<bool>>("MetadataOnly", false),
85 "Load Box structure and other metadata without events. The "
86 "loaded workspace will be empty and not file-backed.");
87
88 declareProperty(std::make_unique<Kernel::PropertyWithValue<bool>>("BoxStructureOnly", false),
89 "Load partial information about the boxes and events. Redundant property "
90 "currently equivalent to MetadataOnly");
91
92 declareProperty(std::make_unique<PropertyWithValue<bool>>("FileBackEnd", false),
93 "Set to true to load the data only on demand.");
94 setPropertySettings("FileBackEnd", std::make_unique<EnabledWhenProperty>("MetadataOnly", IS_EQUAL_TO, "0"));
95
96 declareProperty(std::make_unique<PropertyWithValue<double>>("Memory", -1),
97 "For FileBackEnd only: the amount of memory (in MB) to allocate to the "
98 "in-memory cache.\n"
99 "If not specified, a default of 40% of free physical memory is used.");
100 setPropertySettings("Memory", std::make_unique<EnabledWhenProperty>("FileBackEnd", IS_EQUAL_TO, "1"));
101
102 declareProperty("LoadHistory", true, "If true, the workspace history will be loaded");
103
104 declareProperty(std::make_unique<WorkspaceProperty<IMDWorkspace>>("OutputWorkspace", "", Direction::Output),
105 "Name of the output MDEventWorkspace.");
106}
107
108//----------------------------------------------------------------------------------------------
112 m_filename = getPropertyValue("Filename");
113 convention = Kernel::ConfigService::Instance().getString("Q.convention");
114 // Start loading
115 bool fileBacked = this->getProperty("FileBackEnd");
116
117 m_BoxStructureAndMethadata = getProperty("MetadataOnly");
118
119 bool BoxAndEventInfoOnly = this->getProperty("BoxStructureOnly");
120 if (m_BoxStructureAndMethadata || BoxAndEventInfoOnly) {
122 }
123
124 // Nexus constructor/destructor throw, so can not be used with scoped pointers
125 // directly
126 //(do they lock file because of this and this code is useless?)
127 std::string for_access;
128 if (fileBacked) {
129
130 for_access = "for Read/Write access";
131 m_file.reset(new Nexus::File(m_filename, NXaccess::RDWR));
132 } else {
133 for_access = "for Read access";
134 m_file.reset(new Nexus::File(m_filename, NXaccess::READ));
135 }
136
137 if (!m_file)
138 throw Kernel::Exception::FileError("Can not open file " + for_access, m_filename);
139
140 // The main entry
141 const std::shared_ptr<Mantid::Nexus::NexusDescriptor> fileInfo = getFileInfo();
142
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";
148 } else {
149 throw std::runtime_error("Unexpected NXentry name. Expected "
150 "'MDEventWorkspace' or 'MDHistoWorkspace'.");
151 }
152
153 // Open the entry
154 m_file->openGroup(entryName, "NXentry");
155
156 // Check is SaveMD version 2 was used
157 m_saveMDVersion = 0;
158 if (m_file->hasAttr("SaveMDVersion"))
159 m_file->getAttr("SaveMDVersion", m_saveMDVersion);
160
161 if (m_saveMDVersion == 2)
162 this->loadDimensions2();
163 else {
164 // How many dimensions?
165 std::vector<int32_t> vecDims;
166 m_file->readData("dimensions", vecDims);
167 if (vecDims.empty())
168 throw std::runtime_error("LoadMD:: Error loading number of dimensions.");
169 m_numDims = vecDims[0];
170 if (m_numDims == 0)
171 throw std::runtime_error("LoadMD:: number of dimensions == 0.");
172
173 // Now load all the dimension xml
174 this->loadDimensions();
175 }
176
177 // Coordinate system
178 this->loadCoordinateSystem();
179
180 // QConvention (Inelastic or Crystallography)
181 this->loadQConvention();
182
183 // Display normalization settting
184 if (m_file->hasAddress("/" + entryName + "/" + VISUAL_NORMALIZATION_KEY)) {
186 }
187
188 if (entryName == "MDEventWorkspace") {
189 // The type of event
190 std::string eventType;
191 m_file->getAttr("event_type", eventType);
192
193 if (m_file->hasAddress("/" + entryName + "/" + VISUAL_NORMALIZATION_KEY_HISTO)) {
195 }
196
197 // Use the factory to make the workspace of the right type
202 } else {
204 }
205
206 // Now the ExperimentInfo
207 auto prog = std::make_unique<Progress>(this, 0.0, 0.1, 1);
208 prog->report("Load experiment information.");
209 bool lazyLoadExpt = fileBacked;
210 MDBoxFlatTree::loadExperimentInfos(m_file.get(), m_filename, ws, *fileInfo.get(), "MDEventWorkspace", lazyLoadExpt);
211
212 // Wrapper to cast to MDEventWorkspace then call the function
213 CALL_MDEVENT_FUNCTION(this->doLoad, ws);
214
215 // Check if a MDFrame adjustment is required
219 }
220 // Write out the Qconvention
221 // ki-kf for Inelastic convention; kf-ki for Crystallography convention
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';
225
226 if (pref_QConvention != m_QConvention) {
227 std::vector<double> scaling(m_numDims);
228 scaling = qDimensions(ws);
229 g_log.information() << "Transforming Q\n";
230 Algorithm_sptr transform_alg = createChildAlgorithm("TransformMD");
231 transform_alg->setProperty("InputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
232 transform_alg->setProperty("Scaling", scaling);
233 transform_alg->executeAsChildAlg();
234 IMDWorkspace_sptr tmp = transform_alg->getProperty("OutputWorkspace");
235 ws = std::dynamic_pointer_cast<IMDEventWorkspace>(tmp);
236 }
237 // Save to output
238 setProperty("OutputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
239 } else {
240 // MDHistoWorkspace case.
241 this->loadHisto();
242 }
243}
244
253template <typename NumT>
254void LoadMD::loadSlab(const std::string &name, NumT *data, const MDHistoWorkspace_sptr &ws, NXnumtype dataType) {
255 m_file->openData(name);
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) + ".");
260
261 // verify that the number of points is correct
262 const auto dataDims = m_file->getInfo().dims;
263 Nexus::dimsize_t nPoints = 1;
264 const size_t numDims = dataDims.size();
265 for (size_t d = 0; d < numDims; d++) {
266 nPoints *= dataDims[d];
267 }
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.");
271
272 // read the data
273 try {
274 m_file->getData(data);
275 } catch (...) {
276 g_log.debug() << " failed to read data size: " << dataDims[0] << '\n';
277 }
278 m_file->closeData();
279}
280
281//----------------------------------------------------------------------------------------------
286 // Create the initial MDHisto.
288 // If display normalization has been provided. Use that.
290 ws = std::make_shared<MDHistoWorkspace>(m_dims, m_visualNormalization.value());
291 } else {
292 ws = std::make_shared<MDHistoWorkspace>(m_dims); // Whatever MDHistoWorkspace defaults to.
293 }
294
295 // Now the ExperimentInfo
296 auto prog = std::make_unique<Progress>(this, 0.0, 0.1, 1);
297 prog->report("Load experiment information.");
299
300 // Coordinate system
301 ws->setCoordinateSystem(m_coordSystem);
302
303 // Load the WorkspaceHistory "process"
304 if (this->getProperty("LoadHistory")) {
305 ws->history().loadNexus(m_file.get());
306 }
307
308 this->loadAffineMatricies(std::dynamic_pointer_cast<IMDWorkspace>(ws));
309
310 if (m_saveMDVersion == 2)
311 m_file->openGroup("data", "NXdata");
312 // Load each data slab
313 this->loadSlab("signal", ws->mutableSignalArray(), ws, NXnumtype::FLOAT64);
314 this->loadSlab("errors_squared", ws->mutableErrorSquaredArray(), ws, NXnumtype::FLOAT64);
315 this->loadSlab("num_events", ws->mutableNumEventsArray(), ws, NXnumtype::FLOAT64);
316 this->loadSlab("mask", ws->mutableMaskArray(), ws, NXnumtype::INT8);
317
318 m_file->close();
319
320 // Check if a MDFrame adjustment is required
324 }
325
326 // Write out the Qconvention
327 // ki-kf for Inelastic convention; kf-ki for Crystallography convention
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';
331
332 if (pref_QConvention != m_QConvention) {
333 std::vector<double> scaling(m_numDims);
334 scaling = qDimensions(ws);
335 g_log.information() << "Transforming Q\n";
336 Algorithm_sptr transform_alg = createChildAlgorithm("TransformMD");
337 transform_alg->setProperty("InputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
338 transform_alg->setProperty("Scaling", scaling);
339 transform_alg->executeAsChildAlg();
340 IMDWorkspace_sptr tmp = transform_alg->getProperty("OutputWorkspace");
341 ws = std::dynamic_pointer_cast<MDHistoWorkspace>(tmp);
342 }
343
344 // Save to output
345 setProperty("OutputWorkspace", std::dynamic_pointer_cast<IMDWorkspace>(ws));
346}
347
348//----------------------------------------------------------------------------------------------
351 m_dims.clear();
352
353 // Load each dimension, as their XML representation
354 for (size_t d = 0; d < m_numDims; d++) {
355 std::ostringstream mess;
356 mess << "dimension" << d;
357 std::string dimXML;
358 m_file->getAttr(mess.str(), dimXML);
359 // Use the dimension factory to read the XML
360 m_dims.emplace_back(createDimension(dimXML));
361 }
362 // Since this is an old algorithm we will
363 // have to provide an MDFrame correction
365}
366
367//----------------------------------------------------------------------------------------------
371 using namespace Geometry;
372 m_dims.clear();
373
374 std::string axes;
375
376 m_file->openGroup("data", "NXdata");
377 m_file->openData("signal");
378 m_file->getAttr("axes", axes);
379 m_file->closeData();
380
381 std::vector<std::string> splitAxes;
382 boost::split(splitAxes, axes, boost::is_any_of(":"));
383 // Create each dimension from axes data
384 // We loop axes backwards because Mantid
385 for (size_t d = splitAxes.size(); d > 0; d--) {
386 std::string long_name;
387 std::string units;
388 std::string frame;
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);
393 try {
394 m_file->getAttr("frame", frame);
395 } catch (std::exception &) {
398 }
400 m_file->getData(axis);
401 m_file->closeData();
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));
405 }
406 m_file->closeGroup();
407 m_numDims = m_dims.size();
408}
409
410void LoadMD::loadVisualNormalization(const std::string &key,
411 std::optional<Mantid::API::MDNormalization> &normalization) {
412 try {
413 uint32_t readVisualNormalization(0);
414 m_file->readData(key, readVisualNormalization);
415 normalization = static_cast<Mantid::API::MDNormalization>(readVisualNormalization);
416 } catch (Nexus::Exception const &) {
417
418 } catch (std::exception &) {
419 }
420}
421
424 // Current version stores the coordinate system
425 // in its own field. The first version stored it
426 // as a log value so fallback on that if it can't
427 // be found.
428 if (m_file->hasData("coordinate_system")) {
429 uint32_t readCoord(0);
430 m_file->readData("coordinate_system", readCoord);
431 m_coordSystem = static_cast<SpecialCoordinateSystem>(readCoord);
432 } else {
433 std::string addressOnEntry = m_file->getAddress();
434 std::string newAddress = addressOnEntry + "/experiment0/logs/CoordinateSystem";
435 if (m_file->hasData(newAddress + "/value")) {
436 int readCoord(0);
437 m_file->openAddress(newAddress);
438 m_file->readData("value", readCoord);
439 m_coordSystem = static_cast<SpecialCoordinateSystem>(readCoord);
440 // return to where we started
441 m_file->openAddress(addressOnEntry);
442 }
443 }
444}
445
448 try {
449 m_file->getAttr("QConvention", m_QConvention);
450 } catch (std::exception &) {
451 m_QConvention = "Inelastic";
452 }
453}
454
455//----------------------------------------------------------------------------------------------
462template <typename MDE, size_t nd> void LoadMD::doLoad(typename MDEventWorkspace<MDE, nd>::sptr ws) {
463 // Are we using the file back end?
464 bool fileBackEnd = getProperty("FileBackEnd");
465
466 if (fileBackEnd && m_BoxStructureAndMethadata)
467 throw std::invalid_argument("Combination of BoxStructureOnly or "
468 "MetaDataOnly were set to TRUE with "
469 "fileBackEnd "
470 ": this is not possible.");
471
472 CPUTimer tim;
473 auto prog = std::make_unique<Progress>(this, 0.0, 1.0, 100);
474
475 prog->report("Opening file.");
476 std::string title;
477 try {
478 m_file->getAttr("title", title);
479 } catch (std::exception &) {
480 // Leave the title blank if error on loading
481 }
482 ws->setTitle(title);
483
484 // Load the WorkspaceHistory "process"
485 if (this->getProperty("LoadHistory")) {
486 ws->history().loadNexus(m_file.get());
487 }
488
489 this->loadAffineMatricies(std::dynamic_pointer_cast<IMDWorkspace>(ws));
490
491 m_file->closeGroup();
492 m_file->close();
493 // Add each of the dimension
494 for (size_t d = 0; d < nd; d++)
495 ws->addDimension(m_dims[d]);
496
497 // Coordinate system
499
500 // ----------------------------------------- Box Structure
501 // ------------------------------
502 prog->report("Reading box structure from HDD.");
503 MDBoxFlatTree FlatBoxTree;
504 auto nDims = static_cast<int>(nd); // should be safe
505 FlatBoxTree.loadBoxStructure(m_filename, nDims, MDE::getTypeName());
506
508 bc->fromXMLString(FlatBoxTree.getBCXMLdescr());
509
510 prog->report("Restoring box structure and connectivity");
511 std::vector<API::IMDNode *> boxTree;
512 FlatBoxTree.restoreBoxTree(boxTree, bc, fileBackEnd, m_BoxStructureAndMethadata);
513 size_t numBoxes = boxTree.size();
514
515 // ---------------------------------------- DEAL WITH BOXES
516 // ------------------------------------
517 if (fileBackEnd) { // TODO:: call to the file format factory
518 auto loader = std::shared_ptr<DataObjects::BoxControllerNeXusIO>(new DataObjects::BoxControllerNeXusIO(bc.get()));
519 loader->setDataType(sizeof(coord_t), MDE::getTypeName());
520 bc->setFileBacked(loader, m_filename);
521 // boxes have been already made file-backed when restoring the boxTree;
522 // How much memory for the cache?
523 {
524 // TODO: Clean up, only a write buffer now
525 double mb = getProperty("Memory");
526
527 // Defaults have changed, default disk buffer size should be 10 data
528 // chunks TODO: find optimal, 100 may be better.
529 if (mb <= 0)
530 mb = double(10 * loader->getDataChunk() * sizeof(MDE)) / double(1024 * 1024);
531
532 // Express the cache memory in units of number of events.
533 uint64_t cacheMemory = static_cast<uint64_t>((mb * 1024. * 1024.) / sizeof(MDE)) + 1;
534
535 // Set these values in the diskMRU
536 bc->getFileIO()->setWriteBufferSize(cacheMemory);
537
538 g_log.information() << "Setting a DiskBuffer cache size of " << mb << " MB, or " << cacheMemory << " events.\n";
539 }
540 } // Not file back end
541 else if (!m_BoxStructureAndMethadata) {
542 // ---------------------------------------- READ IN THE BOXES
543 // ------------------------------------
544 // TODO:: call to the file format factory
545 auto loader = file_holder_type(new DataObjects::BoxControllerNeXusIO(bc.get()));
546 loader->setDataType(sizeof(coord_t), MDE::getTypeName());
547 loader->openFile(m_filename, "r");
548
549 const std::vector<uint64_t> &BoxEventIndex = FlatBoxTree.getEventIndex();
550 prog->setNumSteps(numBoxes);
551 std::vector<coord_t> boxTemp;
552
553 for (size_t i = 0; i < numBoxes; i++) {
554 prog->report();
555 auto *box = dynamic_cast<MDBox<MDE, nd> *>(boxTree[i]);
556 if (!box)
557 continue;
558
559 if (BoxEventIndex[2 * i + 1] > 0) // Load in memory NOT using the file as the back-end,
560 {
561 boxTree[i]->reserveMemoryForLoad(BoxEventIndex[2 * i + 1]);
562 boxTree[i]->loadAndAddFrom(loader.get(), BoxEventIndex[2 * i], static_cast<size_t>(BoxEventIndex[2 * i + 1]),
563 boxTemp);
564 }
565 }
566 loader->closeFile();
567 } else // box structure and metadata only
568 {
569 }
570 g_log.debug() << tim << " to create all the boxes and fill them with events.\n";
571
572 // Box of ID 0 is the head box.
573 ws->setBox(boxTree[0]);
574 // Make sure the max ID is ok for later ID generation
575 bc->setMaxId(numBoxes);
576
577 // end-of bMetaDataOnly
578 // Refresh cache
579 // TODO:if(!fileBackEnd)ws->refreshCache();
580 ws->refreshCache();
581 g_log.debug() << tim << " to refreshCache(). " << ws->getNPoints() << " points after refresh.\n";
582
583 g_log.debug() << tim << " to finish up.\n";
584}
585
592 std::map<std::string, std::string> entries;
593 m_file->getEntries(entries);
594
595 if (entries.find("transform_to_orig") != entries.end()) {
596 CoordTransform *transform = this->loadAffineMatrix("transform_to_orig");
597 ws->setTransformToOriginal(transform);
598 }
599 if (entries.find("transform_from_orig") != entries.end()) {
600 CoordTransform *transform = this->loadAffineMatrix("transform_from_orig");
601 ws->setTransformFromOriginal(transform);
602 }
603}
604
612CoordTransform *LoadMD::loadAffineMatrix(const std::string &entry_name) {
613 m_file->openData(entry_name);
614 std::vector<coord_t> vec;
615 m_file->getData<coord_t>(vec);
616 std::string type;
617 int inD(0);
618 int outD(0);
619 m_file->getAttr("type", type);
620 m_file->getAttr<int>("rows", outD);
621 m_file->getAttr<int>("columns", inD);
622 m_file->closeData();
623 Matrix<coord_t> mat(vec, outD, inD);
624 // Adjust dimensions
625 inD--;
626 outD--;
627 CoordTransform *transform = nullptr;
628 if (("CoordTransformAffine" == type) || ("CoordTransformAligned" == type)) {
629 auto affine = new CoordTransformAffine(inD, outD);
630 affine->setMatrix(mat);
631 transform = affine;
632 } else {
633 g_log.information("Do not know how to process coordinate transform " + type);
634 }
635 return transform;
636}
637
643
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();
648
649 // Select an MDFrame based on the special coordinates.
650 // Note that for None, we select a General Coordinate System,
651 // unless the name is "Unknown frame"
652 std::string selectedFrame;
653
654 switch (m_coordSystem) {
656 selectedFrame = Mantid::Geometry::QLab::QLabName;
657 break;
660 break;
662 selectedFrame = Mantid::Geometry::HKL::HKLName;
663 break;
664 default:
666 }
667
668 // Get the old frames just in case something goes wrong. In this case we
669 // reset the frames.
670
671 std::vector<std::string> oldFrames(numberOfDimensions, Mantid::Geometry::GeneralFrame::GeneralFrameName);
672 for (size_t index = 0; index < numberOfDimensions; ++index) {
673 oldFrames[index] = ws->getDimension(index)->getMDFrame().name();
674 }
675
676 // We want to set only up to the first three dimensions to the selected Frame;
677 // Everything else will be set to a General Frame
678 std::vector<std::string> framesToSet(numberOfDimensions, Mantid::Geometry::GeneralFrame::GeneralFrameName);
679 auto fillUpTo = numberOfDimensions > 3 ? 3 : numberOfDimensions;
680 std::fill_n(framesToSet.begin(), fillUpTo, selectedFrame);
681
682 try {
683 // Set the MDFrames for each axes
684 Algorithm_sptr setMDFrameAlg = this->createChildAlgorithm("SetMDFrame");
685 int axesCounter = 0;
686 for (auto &frame : framesToSet) {
687 setMDFrameAlg->setProperty("InputWorkspace", ws);
688 setMDFrameAlg->setProperty("MDFrame", frame);
689 setMDFrameAlg->setProperty("Axes", std::vector<int>(1, axesCounter));
690 ++axesCounter;
691 setMDFrameAlg->executeAsChildAlg();
692 }
693 } catch (...) {
694 g_log.warning() << "LoadMD: An issue occured while trying to correct "
695 "MDFrames. Trying to revert to original.\n";
696 // Revert to the old frames.
697 Algorithm_sptr setMDFrameAlg = this->createChildAlgorithm("SetMDFrame");
698 int axesCounter = 0;
699 for (auto &oldFrame : oldFrames) {
700 setMDFrameAlg->setProperty("InputWorkspace", ws);
701 setMDFrameAlg->setProperty("MDFrame", oldFrame);
702 setMDFrameAlg->setProperty("Axes", std::vector<int>(1, axesCounter));
703 ++axesCounter;
704 setMDFrameAlg->executeAsChildAlg();
705 }
706 }
707}
708
715 // Check if the special coordinate is not none
716 auto isQBasedSpecialCoordinateSystem = true;
718 isQBasedSpecialCoordinateSystem = false;
719 }
720
721 // Check if all MDFrames are of type Unknown frame
722 auto containsOnlyUnkownFrames = true;
723 for (size_t index = 0; index < ws->getNumDims(); ++index) {
724 if (ws->getDimension(index)->getMDFrame().name() != Mantid::Geometry::UnknownFrame::UnknownFrameName) {
725 containsOnlyUnkownFrames = false;
726 break;
727 }
728 }
729
730 // Check if a fix up is required
731 if (isQBasedSpecialCoordinateSystem && containsOnlyUnkownFrames) {
733 }
734}
735
739std::vector<double> LoadMD::qDimensions(const API::IMDWorkspace_sptr &ws) {
740 std::vector<double> scaling(m_numDims);
741 for (size_t d = 0; d < m_numDims; d++) {
742 std::string dimd = ws->getDimension(d)->getName();
743
744 // Assume the Q dimensions are those that have names starting with [
745 // such as [H,0.5H,0], or Q_ such as Q_sample_x.
746 // The change in sign should apply only to those.
747 boost::regex re("\\[.*|Q_");
748 if (boost::regex_search(dimd.begin(), dimd.begin() + 2, re))
749 scaling[d] = -1.0;
750 else
751 scaling[d] = 1.0;
752 }
753 return scaling;
754}
755const std::string LoadMD::VISUAL_NORMALIZATION_KEY = "visual_normalization";
756const std::string LoadMD::VISUAL_NORMALIZATION_KEY_HISTO = "visual_normalization_histo";
757
758} // namespace Mantid::MDAlgorithms
std::string name
Definition Run.cpp:60
gsl_vector * tmp
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.
Unique SingleValueParameter Declaration for InputNDimensions.
@ 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.
Definition Workspace.h:83
virtual void setTitle(const std::string &)
Set the title of the workspace.
Definition Workspace.cpp:27
The class responsible for saving events into nexus file using generic box controller interface Expect...
Generic class to transform from M input dimensions to N output dimensions.
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 &currentGroup, 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".
Definition MDBox.h:45
void reserveMemoryForLoad(uint64_t) override
Reserve all the memory required for loading in one step.
Definition MDBox.hxx:876
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,...
Definition MDLeanEvent.h:60
static std::string getTypeName()
static const std::string GeneralFrameName
static const std::string HKLName
Definition HKL.h:26
Input argument type for MDFrameFactory chainable factory.
static const std::string QLabName
Definition QLab.h:34
static const std::string QSampleName
Definition QSample.h:22
static const std::string UnknownFrameName
CPUTimer : Timer that uses the CPU time, rather than wall-clock time to measure execution time.
Definition CPUTimer.h:24
Records the filename and the description of failure.
Definition Exception.h:98
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.
Definition Logger.cpp:145
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
Numerical Matrix class.
Definition Matrix.h:42
The concrete, templated class for properties.
Load a .nxs file into a MDEventWorkspace.
Definition LoadMD.h:28
std::vector< double > qDimensions(const API::IMDWorkspace_sptr &ws)
Negative scaling for Q dimensions.
Definition LoadMD.cpp:739
void loadDimensions()
Load all the dimensions into this->m_dims.
Definition LoadMD.cpp:350
boost::scoped_ptr< Nexus::File > m_file
Open file handle.
Definition LoadMD.h:89
void checkForRequiredLegacyFixup(const API::IMDWorkspace_sptr &ws)
Checks if a worspace is a certain type of legacy file.
Definition LoadMD.cpp:714
std::vector< Mantid::Geometry::IMDDimension_sptr > m_dims
Each dimension object loaded.
Definition LoadMD.h:98
API::CoordTransform * loadAffineMatrix(const std::string &entry_name)
Load a given affine matrix.
Definition LoadMD.cpp:612
Kernel::SpecialCoordinateSystem m_coordSystem
Coordinate system.
Definition LoadMD.h:100
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.
Definition LoadMD.cpp:254
void doLoad(typename DataObjects::MDEventWorkspace< MDE, nd >::sptr ws)
Helper method.
Definition LoadMD.cpp:462
void loadVisualNormalization(const std::string &key, std::optional< Mantid::API::MDNormalization > &normalization)
Definition LoadMD.cpp:410
void init() override
Initialise the properties.
Definition LoadMD.cpp:80
bool m_requiresMDFrameCorrection
MDFrame correction flag.
Definition LoadMD.h:118
void loadCoordinateSystem()
Load the coordinate system.
Definition LoadMD.cpp:423
std::string m_QConvention
QConvention.
Definition LoadMD.h:102
std::string m_filename
Name of that file.
Definition LoadMD.h:92
int confidence(Nexus::NexusDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
Definition LoadMD.cpp:63
std::optional< Mantid::API::MDNormalization > m_visualNormalizationHisto
Definition LoadMD.h:111
void loadHisto()
Perform loading for a MDHistoWorkspace.
Definition LoadMD.cpp:285
int m_saveMDVersion
Version of SaveMD used to save the file.
Definition LoadMD.h:107
void loadAffineMatricies(const API::IMDWorkspace_sptr &ws)
Load all the affine matricies.
Definition LoadMD.cpp:591
bool m_BoxStructureAndMethadata
load only the box structure with empty boxes but do not tload boxes events
Definition LoadMD.h:104
std::optional< Mantid::API::MDNormalization > m_visualNormalization
Visual normalization.
Definition LoadMD.h:110
static const std::string VISUAL_NORMALIZATION_KEY_HISTO
Definition LoadMD.h:115
static const std::string VISUAL_NORMALIZATION_KEY
Named entry.
Definition LoadMD.h:114
void loadDimensions2()
Load all the dimensions into this->m_dims The dimensions are stored as an nxData array.
Definition LoadMD.cpp:370
void execLoader() override
Run the algorithm.
Definition LoadMD.cpp:111
void setMDFrameOnWorkspaceFromLegacyFile(const API::IMDWorkspace_sptr &ws)
Sets MDFrames for workspaces from legacy files.
Definition LoadMD.cpp:642
const std::string name() const override
Algorithm's name for identification.
Definition LoadMD.h:33
size_t m_numDims
Number of dimensions in loaded file.
Definition LoadMD.h:95
void loadQConvention()
Load the convention for Q
Definition LoadMD.cpp:447
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.
Definition IMDIterator.h:25
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
Definition Algorithm.h:52
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
Definition MDFrame.h:37
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,...
Definition MDTypes.h:27
@ Output
An output workspace.
Definition Property.h:54