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