Mantid
Loading...
Searching...
No Matches
LoadNexusProcessed.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 +
14#include "MantidAPI/Run.h"
15#include "MantidAPI/TextAxis.h"
38
39#include <boost/algorithm/string/trim.hpp>
40#include <boost/regex.hpp>
41#include <nexus/NeXusException.hpp>
42
43#include <map>
44#include <memory>
45#include <string>
46#include <vector>
47
48namespace Mantid::DataHandling {
49
50// Register the algorithm into the algorithm factory
51DECLARE_NEXUS_FILELOADER_ALGORITHM(LoadNexusProcessed)
52
53using namespace Mantid::NeXus;
54using namespace DataObjects;
55using namespace Kernel;
56using namespace API;
58using Mantid::Types::Event::TofEvent;
59using Types::Core::DateAndTime;
60
61namespace {
62
63// Helper typedef
64using IntArray = std::vector<int>;
65
66// Struct to contain spectrum information.
67struct SpectraInfo {
68 // Number of spectra
69 int nSpectra{0};
70 // Do we have any spectra
71 bool hasSpectra{false};
72 // Contains spectrum numbers for each workspace index
74 // Index of the detector in the workspace.
75 IntArray detectorIndex;
76 // Number of detectors associated with each spectra
77 IntArray detectorCount;
78 // Detector list contains a list of all of the detector numbers
79 IntArray detectorList;
80};
81
82// Helper typdef.
83using SpectraInfo_optional = boost::optional<SpectraInfo>;
84
92SpectraInfo extractMappingInfo(const NXEntry &mtd_entry, Logger &logger) {
93 SpectraInfo spectraInfo;
94 // Instrument information
95
96 if (!mtd_entry.containsGroup("instrument")) {
97 logger.information() << "No NXinstrument group called `instrument` under "
98 "NXEntry. The workspace will not "
99 "contain any detector information.\n";
100 return spectraInfo;
101 }
102 NXInstrument inst = mtd_entry.openNXInstrument("instrument");
103 if (!inst.containsGroup("detector")) {
104 logger.information() << "Detector block not found. The workspace will not "
105 "contain any detector information.\n";
106 return spectraInfo;
107 }
108
109 // Populate the spectra-detector map
110 NXDetector detgroup = inst.openNXDetector("detector");
111
112 // Spectra block - Contains spectrum numbers for each workspace index
113 // This might not exist so wrap and check. If it doesn't exist create a
114 // default mapping
115 try {
116 NXInt spectra_block = detgroup.openNXInt("spectra");
117 spectra_block.load();
118 spectraInfo.spectraNumbers = spectra_block.vecBuffer();
119 spectraInfo.nSpectra = spectra_block.dim0();
120 spectraInfo.hasSpectra = true;
121 } catch (std::runtime_error &) {
122 spectraInfo.hasSpectra = false;
123 }
124
125 // Read necessary arrays from the file
126 // Detector list contains a list of all of the detector numbers. If it not
127 // present then we can't update the spectra
128 // map
129 try {
130 NXInt detlist_group = detgroup.openNXInt("detector_list");
131 detlist_group.load();
132 spectraInfo.detectorList = detlist_group.vecBuffer();
133 } catch (std::runtime_error &) {
134 logger.information() << "detector_list block not found. The workspace will "
135 "not contain any detector information.\n";
136 return spectraInfo;
137 }
138
139 // Detector count contains the number of detectors associated with each
140 // spectra
141 NXInt det_count = detgroup.openNXInt("detector_count");
142 det_count.load();
143 spectraInfo.detectorCount = det_count.vecBuffer();
144 // Detector index - contains the index of the detector in the workspace
145 NXInt det_index = detgroup.openNXInt("detector_index");
146 det_index.load();
147 spectraInfo.nSpectra = det_index.dim0();
148 spectraInfo.detectorIndex = det_index.vecBuffer();
149
150 return spectraInfo;
151}
152
160bool isMultiPeriodFile(int nWorkspaceEntries, const Workspace_sptr &sampleWS, Logger &log) {
161 bool isMultiPeriod = false;
162 if (ExperimentInfo_sptr expInfo = std::dynamic_pointer_cast<ExperimentInfo>(sampleWS)) {
163 const std::string nPeriodsLogEntryName = "nperiods";
164 const Run &run = expInfo->run();
165 if (run.hasProperty(nPeriodsLogEntryName)) {
166 const auto nPeriods = run.getPropertyValueAsType<int>(nPeriodsLogEntryName);
167 if (nPeriods == nWorkspaceEntries) {
168 isMultiPeriod = true;
169 log.information("Loading as MultiPeriod group workspace.");
170 }
171 }
172 }
173 return isMultiPeriod;
174}
175
176} // namespace
177
180 : m_shared_bins(false), m_xbins(0), m_axis1vals(), m_list(false), m_interval(false), m_spec_min(0),
181 m_spec_max(Mantid::EMPTY_INT()), m_spec_list(), m_filtered_spec_idxs(), m_nexusFile() {}
182
186
194 if (descriptor.pathExists("/mantid_workspace_1"))
195 return 80;
196 else
197 return 0;
198}
199
201 readInstrumentGroup(mtd_entry, ws);
202}
203
208 // Declare required input parameters for algorithm
209 const std::vector<std::string> exts{".nxs", ".nx5", ".xml"};
210 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, exts),
211 "The name of the Nexus file to read, as a full or relative path.");
212 declareProperty(std::make_unique<WorkspaceProperty<Workspace>>("OutputWorkspace", "", Direction::Output),
213 "The name of the workspace to be created as the output of "
214 "the algorithm. A workspace of this name will be created "
215 "and stored in the Analysis Data Service. For multiperiod "
216 "files, one workspace may be generated for each period. "
217 "Currently only one workspace can be saved at a time so "
218 "multiperiod Mantid files are not generated.");
219
220 // optional
221 auto mustBePositive = std::make_shared<BoundedValidator<int>>();
222 mustBePositive->setLower(0);
223
224 // Use a static cast as MSVC sometimes gets confused and casts as int64
225 declareProperty("SpectrumMin", static_cast<int>(1), mustBePositive, "Number of first spectrum to read.");
226 declareProperty("SpectrumMax", static_cast<int>(Mantid::EMPTY_INT()), mustBePositive,
227 "Number of last spectrum to read.");
228 declareProperty(std::make_unique<ArrayProperty<int>>("SpectrumList"), "List of spectrum numbers to read.");
229 declareProperty("EntryNumber", static_cast<int>(0), mustBePositive,
230 "0 indicates that every entry is loaded, into a separate "
231 "workspace within a group. "
232 "A positive number identifies one entry to be loaded, into "
233 "one workspace");
234 declareProperty("LoadHistory", true, "If true, the workspace history will be loaded");
235 declareProperty(std::make_unique<PropertyWithValue<bool>>("FastMultiPeriod", true, Direction::Input),
236 "For multiperiod workspaces. Copy instrument, parameter and x-data "
237 "rather than loading it directly for each workspace. Y, E and log "
238 "information is always loaded.");
239}
240
252 MatrixWorkspace_sptr &tempMatrixWorkspace,
253 const size_t nWorkspaceEntries, const size_t p) {
254
255 MatrixWorkspace_sptr periodWorkspace = WorkspaceFactory::Instance().create(tempMatrixWorkspace);
256
257 const size_t nHistograms = periodWorkspace->getNumberHistograms();
258 for (size_t i = 0; i < nHistograms; ++i) {
259 periodWorkspace->setSharedX(i, tempMatrixWorkspace->sharedX(i));
260 }
261
262 // We avoid using `openEntry` or similar here because they're just wrappers
263 // around `open`. `open` is slow for large multiperiod datasets, because it
264 // does a search upon the entire HDF5 tree. `openLocal` is *much* quicker, as
265 // it only searches the current group. It does, however, require that the
266 // parent group is currently open.
267 // Words of Warning: While the openLocal construct is an optimization,
268 // it is very dangerous. Forgetting to close an entry of an NXEntry in a
269 // completely unrelated part of the code can result in us opening the
270 // wrong NXEntry here!
271 NXEntry mtdEntry(root, entryName);
272 mtdEntry.openLocal();
273
274 NXData wsEntry(mtdEntry, "workspace");
275 if (!wsEntry.openLocal()) {
276 std::stringstream buffer;
277 buffer << "Group entry " << p - 1
278 << " is not a workspace 2D. Retry with "
279 "FastMultiPeriod option set off.\n";
280 throw std::runtime_error(buffer.str());
281 }
282
283 if (wsEntry.isValid("frac_area")) {
284 std::stringstream buffer;
285 buffer << "Group entry " << p - 1
286 << " has fractional area present. Try "
287 "reloading with FastMultiPeriod set "
288 "off.\n";
289 throw std::runtime_error(buffer.str());
290 }
291
292 NXDataSetTyped<double> data(wsEntry, "values");
293 data.openLocal();
294 NXDataSetTyped<double> errors(wsEntry, "errors");
295 errors.openLocal();
296
297 const int nChannels = data.dim1();
298
299 int blockSize = 8; // Read block size. Set to 8 for efficiency. i.e. read
300 // 8 histograms at a time.
301 int nFullBlocks =
302 static_cast<int>(nHistograms) / blockSize; // Truncated number of full blocks to read. Remainder removed
303 const int readOptimumStop = (nFullBlocks * blockSize);
304 const int readStop = m_spec_max - 1;
305 const int finalBlockSize = readStop - readOptimumStop;
306
307 int wsIndex = 0;
308 int histIndex = m_spec_min - 1;
309
310 for (; histIndex < readStop;) {
311 if (histIndex >= readOptimumStop) {
312 blockSize = finalBlockSize;
313 }
314
315 data.load(blockSize, histIndex);
316 errors.load(blockSize, histIndex);
317
318 double *dataStart = data();
319 double *dataEnd = dataStart + nChannels;
320
321 double *errorStart = errors();
322 double *errorEnd = errorStart + nChannels;
323
324 int final(histIndex + blockSize);
325 while (histIndex < final) {
326 auto &Y = periodWorkspace->mutableY(wsIndex);
327 Y.assign(dataStart, dataEnd);
328 dataStart += nChannels;
329 dataEnd += nChannels;
330 auto &E = periodWorkspace->mutableE(wsIndex);
331 E.assign(errorStart, errorEnd);
332 errorStart += nChannels;
333 errorEnd += nChannels;
334
335 ++wsIndex;
336 ++histIndex;
337 }
338 }
339
340 // We always start one layer too deep
341 // go from /workspace_{n}/{something} -> /workspace_{n}
342 m_nexusFile->closeGroup();
343
344 // Now move to the correct period group
345 // /workspace_{n} -> /workspace_{n+1}
346 m_nexusFile->closeGroup();
347 m_nexusFile->openGroup(entryName, "NXentry");
348
349 try {
350 // This loads logs, sample, and instrument.
351 periodWorkspace->loadSampleAndLogInfoNexus(m_nexusFile.get());
352 } catch (std::exception &e) {
353 g_log.information("Error loading Instrument section of nxs file");
354 g_log.information(e.what());
355 }
356
357 // We make sure to close the current entries. Failing to do this can cause
358 // strange off-by-one errors when loading the spectra.
359 wsEntry.close();
360 mtdEntry.close();
361
362 const double fractionComplete = double(p - 1) / double(nWorkspaceEntries);
363 progress(fractionComplete, "Loading multiperiod entry");
364 return periodWorkspace;
365}
366
367//-------------------------------------------------------------------------------------------------
374
375 API::Workspace_sptr tempWS;
376 int nWorkspaceEntries = 0;
377 // Start scoped block
378 {
379 progress(0, "Opening file...");
380
381 // Throws an approriate exception if there is a problem with file access
382 const std::string filename = getPropertyValue("Filename");
383 NXRoot root(filename);
384
385 // "Open" the same file but with the C++ interface
386 m_nexusFile = std::make_unique<::NeXus::File>(root.m_fileID);
387
388 // Find out how many first level entries there are
389 // Cast down to int as another property later on is an int
390 nWorkspaceEntries = static_cast<int>((root.groups().size()));
391
392 // Check for an entry number property
393 int entrynumber = getProperty("EntryNumber");
394 Property const *const entryNumberProperty = this->getProperty("EntryNumber");
395 bool bDefaultEntryNumber = entryNumberProperty->isDefault();
396
397 if (!bDefaultEntryNumber && entrynumber > nWorkspaceEntries) {
398 g_log.error() << "Invalid entry number specified. File only contains " << nWorkspaceEntries << " entries.\n";
399 throw std::invalid_argument("Invalid entry number specified.");
400 }
401
402 const std::string basename = "mantid_workspace_";
403
404 std::ostringstream os;
405 if (bDefaultEntryNumber) {
406 // Set the entry number to 1 if not provided.
407 entrynumber = 1;
408 }
409 os << basename << entrynumber;
410 const std::string targetEntryName = os.str();
411
412 // Take the first real workspace obtainable. We need it even if loading
413 // groups.
414 tempWS = loadEntry(root, targetEntryName, 0, 1);
415
416 if (nWorkspaceEntries == 1 || !bDefaultEntryNumber) {
417 // We have what we need.
418 applyLogFiltering(tempWS);
419 setProperty("OutputWorkspace", tempWS);
420 } else {
421 // We already know that this is a group workspace. Is it a true
422 // multiperiod workspace.
423 const bool bFastMultiPeriod = this->getProperty("FastMultiPeriod");
424 const bool bIsMultiPeriod = isMultiPeriodFile(nWorkspaceEntries, tempWS, g_log);
425 Property *specListProp = this->getProperty("SpectrumList");
426 m_list = !specListProp->isDefault();
427
428 // Load all first level entries
429 auto wksp_group = std::make_shared<WorkspaceGroup>();
430 // This forms the name of the group
431 std::string base_name = getPropertyValue("OutputWorkspace");
432 // First member of group should be the group itself, for some reason!
433
434 // load names of each of the workspaces. Note that if we have duplicate
435 // names then we don't select them
436 auto names = extractWorkspaceNames(root, static_cast<size_t>(nWorkspaceEntries));
437
438 // remove existing workspace and replace with the one being loaded
439 bool wsExists = AnalysisDataService::Instance().doesExist(base_name);
440 if (wsExists) {
441 Algorithm_sptr alg = AlgorithmManager::Instance().createUnmanaged("DeleteWorkspace");
442 alg->initialize();
443 alg->setChild(true);
444 alg->setProperty("Workspace", base_name);
445 alg->execute();
446 }
447
448 base_name += "_";
449 const std::string prop_name = "OutputWorkspace_";
450
451 MatrixWorkspace_sptr tempMatrixWorkspace = std::dynamic_pointer_cast<Workspace2D>(tempWS);
452 bool bAccelleratedMultiPeriodLoading = false;
453 if (tempMatrixWorkspace) {
454 // We only accelerate for simple scenarios for now. Spectrum lists are
455 // too complicated to bother with.
456 bAccelleratedMultiPeriodLoading = bIsMultiPeriod && bFastMultiPeriod && !m_list;
457 // Strip out any loaded logs. That way we don't pay for copying that
458 // information around.
459 tempMatrixWorkspace->mutableRun().clearLogs();
460 }
461
462 if (bAccelleratedMultiPeriodLoading) {
463 g_log.information("Accelerated multiperiod loading");
464 } else {
465 g_log.information("Individual group loading");
466 }
467
468 for (int p = 1; p <= nWorkspaceEntries; ++p) {
469 const auto indexStr = std::to_string(p);
470
471 // decide what the workspace should be called
472 std::string wsName = buildWorkspaceName(names[p], base_name, p);
473
474 Workspace_sptr local_workspace;
475
476 /*
477 For multiperiod workspaces we can accelerate the loading by making
478 resonable assumptions about the differences between the workspaces
479 Only Y, E and log data entries should vary. Therefore we can clone our
480 temp workspace, and overwrite those things we are interested in.
481 */
482 if (bAccelleratedMultiPeriodLoading) {
483 local_workspace =
484 doAccelleratedMultiPeriodLoading(root, basename + indexStr, tempMatrixWorkspace, nWorkspaceEntries, p);
485 } else // Fall-back for generic loading
486 {
487 const auto nWorkspaceEntries_d = static_cast<double>(nWorkspaceEntries);
488 local_workspace = loadEntry(root, basename + indexStr, static_cast<double>(p - 1) / nWorkspaceEntries_d,
489 1. / nWorkspaceEntries_d);
490 }
491
492 applyLogFiltering(local_workspace);
494 std::make_unique<WorkspaceProperty<API::Workspace>>(prop_name + indexStr, wsName, Direction::Output));
495 wksp_group->addWorkspace(local_workspace);
496 setProperty(prop_name + indexStr, local_workspace);
497 }
498
499 // The group is the root property value
500 setProperty("OutputWorkspace", std::static_pointer_cast<Workspace>(wksp_group));
501 }
502
503 root.close();
504 } // All file resources should be scoped to here. All previous file handles
505 // must be cleared to release locks
506 loadNexusGeometry(*tempWS, nWorkspaceEntries, g_log, std::string(getProperty("Filename")));
507
508 m_axis1vals.clear();
509} // namespace DataHandling
510
524std::string LoadNexusProcessed::buildWorkspaceName(const std::string &name, const std::string &baseName,
525 size_t wsIndex) {
526 std::string wsName;
527 std::string index = std::to_string(wsIndex);
528
529 if (!name.empty()) {
530 wsName = name;
531 } else {
532 // we have a common stem so rename accordingly
533 boost::smatch results;
534 const boost::regex exp(".*_(\\d+$)");
535 // if we have a common name stem then name is <OutputWorkspaceName>_n
536 if (boost::regex_search(name, results, exp)) {
537 wsName = baseName + std::string(results[1].first, results[1].second);
538 } else {
539 // if the name property wasn't defined just use <OutputWorkspaceName>_n
540 wsName = baseName + index;
541 }
542 }
543
545
546 return wsName;
547}
548
555 bool noClash(false);
556
557 for (int i = 0; !noClash; ++i) {
558 std::string wsIndex; // dont use an index if there is no other
559 // workspace
560 if (i > 0) {
561 wsIndex = "_" + std::to_string(i);
562 }
563
564 bool wsExists = AnalysisDataService::Instance().doesExist(wsName + wsIndex);
565 if (!wsExists) {
566 wsName += wsIndex;
567 noClash = true;
568 }
569 }
570}
571
578std::vector<std::string> LoadNexusProcessed::extractWorkspaceNames(NXRoot &root, size_t nWorkspaceEntries) {
579 std::vector<std::string> names(nWorkspaceEntries + 1);
580 for (size_t p = 1; p <= nWorkspaceEntries; ++p) {
581 auto period = std::to_string(p);
582 names[p] = loadWorkspaceName(root, "mantid_workspace_" + period);
583 }
584
585 // Check that there are no duplicates in the workspace name
586 // This can cause severe problems
587 auto it = std::unique(names.begin(), names.end());
588 if (it != names.end()) {
589 auto size = names.size();
590 names.clear();
591 names.resize(size);
592 }
593 return names;
594}
595
603std::string LoadNexusProcessed::loadWorkspaceName(NXRoot &root, const std::string &entry_name) {
604 NXEntry mtd_entry = root.openEntry(entry_name);
605 std::string workspaceName = std::string();
606 try {
607 workspaceName = mtd_entry.getString("workspace_name");
608 } catch (std::runtime_error &) {
609 }
610 mtd_entry.close();
611 return workspaceName;
612}
613
614//-------------------------------------------------------------------------------------------------
626 const double &progressStart, const double &progressRange) {
627 NXDataSetTyped<int64_t> indices_data = wksp_cls.openNXDataSet<int64_t>("indices");
628 indices_data.load();
629 size_t numspec = indices_data.dim0() - 1;
630
631 // process optional spectrum parameters, if set
633 // Actual number of spectra in output workspace (if only a user-specified
634 // range and/or list was going to be loaded)
635 numspec = calculateWorkspaceSize(numspec, true);
636
637 int num_xbins = xbins.dim0();
638 if (xbins.rank() == 2) {
639 num_xbins = xbins.dim1();
640 }
641 if (num_xbins < 2)
642 num_xbins = 2;
643 EventWorkspace_sptr ws = std::dynamic_pointer_cast<EventWorkspace>(
644 WorkspaceFactory::Instance().create("EventWorkspace", numspec, num_xbins, num_xbins - 1));
645
646 // Set the YUnit label
647 ws->setYUnit(indices_data.attributes("units"));
648 std::string unitLabel = indices_data.attributes("unit_label");
649 if (unitLabel.empty())
650 unitLabel = indices_data.attributes("units");
651 ws->setYUnitLabel(unitLabel);
652
653 // Handle optional fields.
654 // TODO: Handle inconsistent sizes
655 std::vector<int64_t> pulsetimes;
656 if (wksp_cls.isValid("pulsetime")) {
657 NXDataSetTyped<int64_t> pulsetime = wksp_cls.openNXDataSet<int64_t>("pulsetime");
658 pulsetime.load();
659 pulsetimes = pulsetime.vecBuffer();
660 }
661
662 std::vector<double> tofs;
663 if (wksp_cls.isValid("tof")) {
664 NXDouble tof = wksp_cls.openNXDouble("tof");
665 tof.load();
666 tofs = tof.vecBuffer();
667 }
668
669 std::vector<float> error_squareds;
670 if (wksp_cls.isValid("error_squared")) {
671 NXFloat error_squared = wksp_cls.openNXFloat("error_squared");
672 error_squared.load();
673 error_squareds = error_squared.vecBuffer();
674 }
675
676 std::vector<float> weights;
677 if (wksp_cls.isValid("weight")) {
678 NXFloat weight = wksp_cls.openNXFloat("weight");
679 weight.load();
680 weights = weight.vecBuffer();
681 }
682
683 // What type of event lists?
684 EventType type = TOF;
685 if (!tofs.empty() && !pulsetimes.empty() && !weights.empty() && !error_squareds.empty())
686 type = WEIGHTED;
687 else if ((!tofs.empty() && !weights.empty() && !error_squareds.empty()))
688 type = WEIGHTED_NOTIME;
689 else if (!pulsetimes.empty() && !tofs.empty())
690 type = TOF;
691 else
692 throw std::runtime_error("Could not figure out the type of event list!");
693
694 // indices of events
695 std::vector<int64_t> indices = indices_data.vecBuffer();
696 // Create all the event lists
697 auto max = static_cast<int64_t>(m_filtered_spec_idxs.size());
698 Progress progress(this, progressStart, progressStart + progressRange, max);
700 for (int64_t j = 0; j < max; ++j) {
702 size_t wi = m_filtered_spec_idxs[j] - 1;
703 int64_t index_start = indices[wi];
704 int64_t index_end = indices[wi + 1];
705 if (index_end >= index_start) {
706 EventList &el = ws->getSpectrum(j);
707 el.switchTo(type);
708
709 // Allocate all the required memory
710 el.reserve(index_end - index_start);
711 el.clearDetectorIDs();
712
713 for (int64_t i = index_start; i < index_end; i++)
714 switch (type) {
715 case TOF:
716 el.addEventQuickly(TofEvent(tofs[i], DateAndTime(pulsetimes[i])));
717 break;
718 case WEIGHTED:
719 el.addEventQuickly(WeightedEvent(tofs[i], DateAndTime(pulsetimes[i]), weights[i], error_squareds[i]));
720 break;
721 case WEIGHTED_NOTIME:
722 el.addEventQuickly(WeightedEventNoTime(tofs[i], weights[i], error_squareds[i]));
723 break;
724 }
725
726 // Set the X axis
727 if (this->m_shared_bins)
728 el.setHistogram(this->m_xbins);
729 else {
730 MantidVec x(xbins.dim1());
731
732 for (int i = 0; i < xbins.dim1(); i++)
733 x[i] = xbins(static_cast<int>(wi), i);
734 // Workspace and el was just created, so we can just set a new histogram
735 // We can move x as it is not longer used after this point
736 el.setHistogram(HistogramData::BinEdges(std::move(x)));
737 }
738 }
739 progress.report();
741 }
743
744 return ws;
745}
746
747//-------------------------------------------------------------------------------------------------
755template <typename ColumnType, typename NexusType>
756void LoadNexusProcessed::loadNumericColumn(const Mantid::NeXus::NXData &tableData, const std::string &dataSetName,
757 const API::ITableWorkspace_sptr &tableWs, const std::string &columnType) {
758 NXDataSetTyped<NexusType> data = tableData.openNXDataSet<NexusType>(dataSetName);
759 std::string columnTitle = data.attributes("name");
760 if (!columnTitle.empty()) {
761 data.load();
762 auto length = static_cast<size_t>(data.dim0());
763 auto rowCount = tableWs->rowCount();
764 // check that the row count is OK
765 if (rowCount == 0) {
766 tableWs->setRowCount(length);
767 } else if (rowCount != length) {
768 throw std::runtime_error("Columns have different sizes.");
769 }
770 // copy the data
771 auto column = tableWs->addColumn(columnType, columnTitle);
772 for (size_t i = 0; i < length; i++) {
773 column->cell<ColumnType>(i) = static_cast<ColumnType>(*(data() + i));
774 }
775 }
776}
777
778//-------------------------------------------------------------------------------------------------
784 workspace = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace");
785
786 NXData nx_tw = entry.openNXData("table_workspace");
787
788 int columnNumber = 1;
789 do {
790 std::string dataSetName = "column_" + std::to_string(columnNumber);
791
792 NXInfo info = nx_tw.getDataSetInfo(dataSetName);
793 if (info.stat == NX_ERROR) {
794 // Assume we done last column of table
795 break;
796 }
797
798 if (info.rank == 1) {
799 if (info.type == NX_FLOAT64) {
800 loadNumericColumn<double, double>(nx_tw, dataSetName, workspace, "double");
801 } else if (info.type == NX_INT32) {
802 loadNumericColumn<int, int32_t>(nx_tw, dataSetName, workspace, "int");
803 } else if (info.type == NX_UINT32) {
804 loadNumericColumn<uint32_t, uint32_t>(nx_tw, dataSetName, workspace, "uint");
805 } else if (info.type == NX_INT64) {
806 loadNumericColumn<int64_t, int64_t>(nx_tw, dataSetName, workspace, "long64");
807 } else if (info.type == NX_UINT64) {
808 loadNumericColumn<size_t, uint64_t>(nx_tw, dataSetName, workspace, "size_t");
809 } else if (info.type == NX_FLOAT32) {
810 loadNumericColumn<float, float>(nx_tw, dataSetName, workspace, "float");
811 } else if (info.type == NX_UINT8) {
812 loadNumericColumn<bool, bool>(nx_tw, dataSetName, workspace, "bool");
813 } else {
814 throw std::logic_error("Column with Nexus data type " + std::to_string(info.type) + " cannot be loaded.");
815 }
816 } else if (info.rank == 2) {
817 if (info.type == NX_CHAR) {
818 NXChar data = nx_tw.openNXChar(dataSetName);
819 std::string columnTitle = data.attributes("name");
820 if (!columnTitle.empty()) {
821 workspace->addColumn("str", columnTitle);
822 int nRows = info.dims[0];
823 workspace->setRowCount(nRows);
824
825 const int maxStr = info.dims[1];
826 data.load();
827 for (int iR = 0; iR < nRows; ++iR) {
828 auto &cellContents = workspace->cell<std::string>(iR, columnNumber - 1);
829 auto startPoint = data() + maxStr * iR;
830 cellContents.assign(startPoint, startPoint + maxStr);
831 boost::trim_right(cellContents);
832 }
833 }
834 } else if (info.type == NX_INT32) {
835 loadVectorColumn<int>(nx_tw, dataSetName, workspace, "vector_int");
836 } else if (info.type == NX_FLOAT64) {
837 auto data = nx_tw.openNXDouble(dataSetName);
838 if (data.attributes("interpret_as") == "V3D") {
840 } else {
841 loadVectorColumn<double>(nx_tw, dataSetName, workspace, "vector_double");
842 }
843 }
844 }
845
846 columnNumber++;
847
848 } while (true);
849
850 return std::static_pointer_cast<API::Workspace>(workspace);
851}
852
860template <typename Type>
861void LoadNexusProcessed::loadVectorColumn(const NXData &tableData, const std::string &dataSetName,
862 const ITableWorkspace_sptr &tableWs, const std::string &columnType) {
863 NXDataSetTyped<Type> data = tableData.openNXDataSet<Type>(dataSetName);
864 std::string columnTitle = data.attributes("name");
865 if (!columnTitle.empty()) {
866 tableWs->addColumn(columnType, columnTitle);
867
868 NXInfo info = tableData.getDataSetInfo(dataSetName);
869 const size_t rowCount = info.dims[0];
870 const size_t blockSize = info.dims[1];
871
872 // This might've been done already, but doing it twice should't do any harm
873 tableWs->setRowCount(rowCount);
874
875 data.load();
876
877 for (size_t i = 0; i < rowCount; ++i) {
878 auto &cell = tableWs->cell<std::vector<Type>>(i, tableWs->columnCount() - 1);
879
880 Type *from = data() + blockSize * i;
881
882 cell.assign(from, from + blockSize);
883
884 std::ostringstream rowSizeAttrName;
885 rowSizeAttrName << "row_size_" << i;
886
887 // This is ugly, but I can only get attribute as a string using the API
888 std::istringstream rowSizeStr(data.attributes(rowSizeAttrName.str()));
889
890 int rowSize;
891 rowSizeStr >> rowSize;
892
893 cell.resize(rowSize);
894 }
895 }
896}
897
904 std::string columnTitle = data.attributes("name");
905 if (!columnTitle.empty()) {
906 ColumnVector<V3D> col = tableWs->addColumn("V3D", columnTitle);
907
908 const int rowCount = data.dim0();
909
910 // This might've been done already, but doing it twice should't do any harm
911 tableWs->setRowCount(rowCount);
912
913 data.load();
914
915 for (int i = 0; i < rowCount; ++i) {
916 auto &cell = col[i];
917 cell(data(i, 0), data(i, 1), data(i, 2));
918 }
919 }
920}
921
929 g_log.notice("Load as LeanElasticPeaks");
930
931 // API::IPeaksWorkspace_sptr workspace;
932 API::ITableWorkspace_sptr tWorkspace;
933 // PeaksWorkspace_sptr workspace;
934 tWorkspace = Mantid::API::WorkspaceFactory::Instance().createTable("LeanElasticPeaksWorkspace");
935
936 IPeaksWorkspace_sptr peakWS = std::dynamic_pointer_cast<LeanElasticPeaksWorkspace>(tWorkspace);
937
938 NXData nx_tw = entry.openNXData("peaks_workspace");
939
940 int columnNumber = 1;
941 int numberPeaks = 0;
942 std::vector<std::string> columnNames;
943 do {
944 std::string str = "column_" + std::to_string(columnNumber);
945
946 NXInfo info = nx_tw.getDataSetInfo(str);
947 if (info.stat == NX_ERROR) {
948 // Assume we done last column of table
949 break;
950 }
951
952 // store column names
953 columnNames.emplace_back(str);
954
955 // determine number of peaks
956 // here we assume that a peaks_table has always one column of doubles
957
958 if (info.type == NX_FLOAT64) {
959 NXDouble nxDouble = nx_tw.openNXDouble(str);
960 std::string columnTitle = nxDouble.attributes("name");
961 if (!columnTitle.empty() && numberPeaks == 0) {
962 numberPeaks = nxDouble.dim0();
963 }
964 }
965
966 columnNumber++;
967
968 } while (true);
969
970 // Get information from all but data group
971 std::string parameterStr;
972 // Hop to the right point /mantid_workspace_1
973 try {
974 m_nexusFile->openPath(entry.path()); // This is
975 } catch (std::runtime_error &re) {
976 throw std::runtime_error("Error while opening a path in a Peaks entry in a "
977 "Nexus processed file. "
978 "This path is wrong: " +
979 entry.path() + ". Lower level error description: " + re.what());
980 }
981 try {
982 // This loads logs, sample, and instrument.
983 peakWS->loadExperimentInfoNexus(getPropertyValue("Filename"), m_nexusFile.get(), parameterStr);
984 // Populate the instrument parameters in this workspace
985 peakWS->readParameterMap(parameterStr);
986 } catch (std::exception &e) {
987 g_log.information("Error loading Instrument section of nxs file");
988 g_log.information(e.what());
989 }
990
991 // Coordinates - Older versions did not have the separate field but used a log
992 // value
993 const std::string peaksWSName = "peaks_workspace";
994 try {
995 m_nexusFile->openGroup(peaksWSName, "NXentry");
996 } catch (std::runtime_error &re) {
997 throw std::runtime_error("Error while opening a peaks workspace in a Nexus processed file. "
998 "Cannot open gropu " +
999 peaksWSName + ". Lower level error description: " + re.what());
1000 }
1001 try {
1002 uint32_t loadCoord(0);
1003 m_nexusFile->readData("coordinate_system", loadCoord);
1004 peakWS->setCoordinateSystem(static_cast<Kernel::SpecialCoordinateSystem>(loadCoord));
1005 } catch (::NeXus::Exception &) {
1006 // Check for a log value
1007 auto logs = peakWS->logs();
1008 if (logs->hasProperty("CoordinateSystem")) {
1009 auto *prop = dynamic_cast<PropertyWithValue<int> *>(logs->getProperty("CoordinateSystem"));
1010 if (prop) {
1011 int value((*prop)());
1012 peakWS->setCoordinateSystem(static_cast<Kernel::SpecialCoordinateSystem>(value));
1013 }
1014 }
1015 }
1016
1017 std::string m_QConvention = "Inelastic";
1018 try {
1019 m_nexusFile->getAttr("QConvention", m_QConvention);
1020 } catch (std::exception &) {
1021 }
1022
1023 // peaks_workspace
1024 m_nexusFile->closeGroup();
1025
1026 // Change convention of loaded file to that in Preferen
1027 double qSign = 1.0;
1028 std::string convention = ConfigService::Instance().getString("Q.convention");
1029 if (convention != m_QConvention)
1030 qSign = -1.0;
1031
1032 for (int r = 0; r < numberPeaks; r++) {
1033 // Create individual LeanElasticPeak
1034 const auto goniometer = peakWS->run().getGoniometer();
1035 LeanElasticPeak peak;
1036 peak.setGoniometerMatrix(goniometer.getR());
1037 peak.setRunNumber(peakWS->getRunNumber());
1038 peakWS->addPeak(peak);
1039 }
1040
1041 for (const auto &str : columnNames) {
1042 if (str == "column_1") {
1043 NXDouble nxDouble = nx_tw.openNXDouble(str);
1044 nxDouble.load();
1045
1046 for (int r = 0; r < numberPeaks; r++) {
1047 double val = qSign * nxDouble[r];
1048 peakWS->getPeak(r).setH(val);
1049 }
1050 } else if (str == "column_2") {
1051 NXDouble nxDouble = nx_tw.openNXDouble(str);
1052 nxDouble.load();
1053
1054 for (int r = 0; r < numberPeaks; r++) {
1055 double val = qSign * nxDouble[r];
1056 peakWS->getPeak(r).setK(val);
1057 }
1058 } else if (str == "column_3") {
1059 NXDouble nxDouble = nx_tw.openNXDouble(str);
1060 nxDouble.load();
1061
1062 for (int r = 0; r < numberPeaks; r++) {
1063 double val = qSign * nxDouble[r];
1064 peakWS->getPeak(r).setL(val);
1065 }
1066 } else if (str == "column_4") {
1067 NXDouble nxDouble = nx_tw.openNXDouble(str);
1068 nxDouble.load();
1069
1070 for (int r = 0; r < numberPeaks; r++) {
1071 double val = nxDouble[r];
1072 peakWS->getPeak(r).setIntensity(val);
1073 }
1074 } else if (str == "column_5") {
1075 NXDouble nxDouble = nx_tw.openNXDouble(str);
1076 nxDouble.load();
1077
1078 for (int r = 0; r < numberPeaks; r++) {
1079 double val = nxDouble[r];
1080 peakWS->getPeak(r).setSigmaIntensity(val);
1081 }
1082 } else if (str == "column_6") {
1083 NXDouble nxDouble = nx_tw.openNXDouble(str);
1084 nxDouble.load();
1085
1086 for (int r = 0; r < numberPeaks; r++) {
1087 double val = nxDouble[r];
1088 peakWS->getPeak(r).setBinCount(val);
1089 }
1090 } else if (str == "column_7") {
1091 NXDouble nxDouble = nx_tw.openNXDouble(str);
1092 nxDouble.load();
1093
1094 for (int r = 0; r < numberPeaks; r++) {
1095 double val = nxDouble[r];
1096 peakWS->getPeak(r).setWavelength(val);
1097 }
1098 } else if (str == "column_10") {
1099 NXInt nxInt = nx_tw.openNXInt(str);
1100 nxInt.load();
1101
1102 for (int r = 0; r < numberPeaks; r++) {
1103 int ival = nxInt[r];
1104 if (ival != -1)
1105 peakWS->getPeak(r).setRunNumber(ival);
1106 }
1107 } else if (str == "column_11") {
1108 NXInt nxInt = nx_tw.openNXInt(str);
1109 nxInt.load();
1110
1111 for (int r = 0; r < numberPeaks; r++) {
1112 int ival = nxInt[r];
1113 peakWS->getPeak(r).setPeakNumber(ival);
1114 }
1115 } else if (str == "column_12") {
1116 NXDouble nxDouble = nx_tw.openNXDouble(str);
1117 nxDouble.load();
1118
1119 for (int r = 0; r < numberPeaks; r++) {
1120 double val = nxDouble[r];
1121 peakWS->getPeak(r).setAbsorptionWeightedPathLength(val);
1122 }
1123 } else if (str == "column_13") {
1124 NXDouble nxDouble = nx_tw.openNXDouble(str);
1125 nxDouble.load();
1126 Kernel::Matrix<double> gm(3, 3, false);
1127 int k = 0;
1128 for (int r = 0; r < numberPeaks; r++) {
1129 for (int j = 0; j < 9; j++) {
1130 double val = nxDouble[k];
1131 k++;
1132 gm[j % 3][j / 3] = val;
1133 }
1134 peakWS->getPeak(r).setGoniometerMatrix(gm);
1135 }
1136 } else if (str == "column_15") {
1137 NXDouble nxDouble = nx_tw.openNXDouble(str);
1138 nxDouble.load();
1139 V3D qlab;
1140 for (int r = 0; r < numberPeaks; ++r) {
1141 qlab = V3D(nxDouble[r * 3], nxDouble[r * 3 + 1], nxDouble[r * 3 + 2]);
1142 peakWS->getPeak(r).setQLabFrame(qlab, 0.0);
1143 }
1144 }
1145
1146 // After all columns read set IntHKL
1147 for (int r = 0; r < numberPeaks; r++) {
1148 V3D intHKL = V3D(peakWS->getPeak(r).getH(), peakWS->getPeak(r).getK(), peakWS->getPeak(r).getL());
1149 peakWS->getPeak(r).setIntHKL(intHKL);
1150 }
1151 }
1152
1153 return std::static_pointer_cast<API::Workspace>(peakWS);
1154}
1155
1156//-------------------------------------------------------------------------------------------------
1161 // API::IPeaksWorkspace_sptr workspace;
1162 API::ITableWorkspace_sptr tWorkspace;
1163 // PeaksWorkspace_sptr workspace;
1164 tWorkspace = Mantid::API::WorkspaceFactory::Instance().createTable("PeaksWorkspace");
1165
1166 PeaksWorkspace_sptr peakWS = std::dynamic_pointer_cast<PeaksWorkspace>(tWorkspace);
1167
1168 NXData nx_tw = entry.openNXData("peaks_workspace");
1169
1170 int columnNumber = 1;
1171 int numberPeaks = 0;
1172 std::vector<std::string> columnNames;
1173 do {
1174 std::string str = "column_" + std::to_string(columnNumber);
1175
1176 NXInfo info = nx_tw.getDataSetInfo(str);
1177 if (info.stat == NX_ERROR) {
1178 // Assume we done last column of table
1179 break;
1180 }
1181
1182 // store column names
1183 columnNames.emplace_back(str);
1184
1185 // determine number of peaks
1186 // here we assume that a peaks_table has always one column of doubles
1187
1188 if (info.type == NX_FLOAT64) {
1189 NXDouble nxDouble = nx_tw.openNXDouble(str);
1190 std::string columnTitle = nxDouble.attributes("name");
1191 if (!columnTitle.empty() && numberPeaks == 0) {
1192 numberPeaks = nxDouble.dim0();
1193 }
1194 }
1195
1196 columnNumber++;
1197
1198 } while (true);
1199
1200 // Get information from all but data group
1201 std::string parameterStr;
1202 // Hop to the right point /mantid_workspace_1
1203 try {
1204 m_nexusFile->openPath(entry.path()); // This is
1205 } catch (std::runtime_error &re) {
1206 throw std::runtime_error("Error while opening a path in a Peaks entry in a "
1207 "Nexus processed file. "
1208 "This path is wrong: " +
1209 entry.path() + ". Lower level error description: " + re.what());
1210 }
1211 try {
1212 // This loads logs, sample, and instrument.
1213 peakWS->loadExperimentInfoNexus(getPropertyValue("Filename"), m_nexusFile.get(), parameterStr);
1214 // Populate the instrument parameters in this workspace
1215 peakWS->readParameterMap(parameterStr);
1216 } catch (std::exception &e) {
1217 g_log.information("Error loading Instrument section of nxs file");
1218 g_log.information(e.what());
1219 }
1220
1221 // Coordinates - Older versions did not have the separate field but used a log
1222 // value
1223 const std::string peaksWSName = "peaks_workspace";
1224 try {
1225 m_nexusFile->openGroup(peaksWSName, "NXentry");
1226 } catch (std::runtime_error &re) {
1227 throw std::runtime_error("Error while opening a peaks workspace in a Nexus processed file. "
1228 "Cannot open gropu " +
1229 peaksWSName + ". Lower level error description: " + re.what());
1230 }
1231 try {
1232 uint32_t loadCoord(0);
1233 m_nexusFile->readData("coordinate_system", loadCoord);
1234 peakWS->setCoordinateSystem(static_cast<Kernel::SpecialCoordinateSystem>(loadCoord));
1235 } catch (::NeXus::Exception &) {
1236 // Check for a log value
1237 auto logs = peakWS->logs();
1238 if (logs->hasProperty("CoordinateSystem")) {
1239 auto *prop = dynamic_cast<PropertyWithValue<int> *>(logs->getProperty("CoordinateSystem"));
1240 if (prop) {
1241 int value((*prop)());
1242 peakWS->setCoordinateSystem(static_cast<Kernel::SpecialCoordinateSystem>(value));
1243 }
1244 }
1245 }
1246
1247 std::string m_QConvention = "Inelastic";
1248 try {
1249 m_nexusFile->getAttr("QConvention", m_QConvention);
1250 } catch (std::exception &) {
1251 }
1252
1253 // peaks_workspace
1254 m_nexusFile->closeGroup();
1255
1256 // Change convention of loaded file to that in Preferen
1257 double qSign = 1.0;
1258 std::string convention = ConfigService::Instance().getString("Q.convention");
1259 if (convention != m_QConvention)
1260 qSign = -1.0;
1261
1262 for (int r = 0; r < numberPeaks; r++) {
1263 // Warning! Do not use anything other than the default constructor here
1264 // It is currently important (10/05/17) that the DetID (set in the loop
1265 // below this one) is set before QLabFrame as this causes Peak to ray trace
1266 // to find the location of the detector, which significantly increases
1267 // loading times.
1268 const auto goniometer = peakWS->run().getGoniometer();
1269 Peak peak;
1270 peak.setInstrument(peakWS->getInstrument());
1271 peak.setGoniometerMatrix(goniometer.getR());
1272 peak.setRunNumber(peakWS->getRunNumber());
1273 peakWS->addPeak(std::move(peak));
1274 }
1275
1276 for (const auto &str : columnNames) {
1277 if (str == "column_1") {
1278 NXInt nxInt = nx_tw.openNXInt(str);
1279 nxInt.load();
1280
1281 for (int r = 0; r < numberPeaks; r++) {
1282 int ival = nxInt[r];
1283 if (ival != -1)
1284 peakWS->getPeak(r).setDetectorID(ival);
1285 }
1286 } else if (str == "column_2") {
1287 NXDouble nxDouble = nx_tw.openNXDouble(str);
1288 nxDouble.load();
1289
1290 for (int r = 0; r < numberPeaks; r++) {
1291 double val = qSign * nxDouble[r];
1292 peakWS->getPeak(r).setH(val);
1293 }
1294 } else if (str == "column_3") {
1295 NXDouble nxDouble = nx_tw.openNXDouble(str);
1296 nxDouble.load();
1297
1298 for (int r = 0; r < numberPeaks; r++) {
1299 double val = qSign * nxDouble[r];
1300 peakWS->getPeak(r).setK(val);
1301 }
1302 } else if (str == "column_4") {
1303 NXDouble nxDouble = nx_tw.openNXDouble(str);
1304 nxDouble.load();
1305
1306 for (int r = 0; r < numberPeaks; r++) {
1307 double val = qSign * nxDouble[r];
1308 peakWS->getPeak(r).setL(val);
1309 }
1310 } else if (str == "column_5") {
1311 NXDouble nxDouble = nx_tw.openNXDouble(str);
1312 nxDouble.load();
1313
1314 for (int r = 0; r < numberPeaks; r++) {
1315 double val = nxDouble[r];
1316 peakWS->getPeak(r).setIntensity(val);
1317 }
1318 } else if (str == "column_6") {
1319 NXDouble nxDouble = nx_tw.openNXDouble(str);
1320 nxDouble.load();
1321
1322 for (int r = 0; r < numberPeaks; r++) {
1323 double val = nxDouble[r];
1324 peakWS->getPeak(r).setSigmaIntensity(val);
1325 }
1326 } else if (str == "column_7") {
1327 NXDouble nxDouble = nx_tw.openNXDouble(str);
1328 nxDouble.load();
1329
1330 for (int r = 0; r < numberPeaks; r++) {
1331 double val = nxDouble[r];
1332 peakWS->getPeak(r).setBinCount(val);
1333 }
1334 } else if (str == "column_10") {
1335 NXDouble nxDouble = nx_tw.openNXDouble(str);
1336 nxDouble.load();
1337
1338 for (int r = 0; r < numberPeaks; r++) {
1339 double val = nxDouble[r];
1340 peakWS->getPeak(r).setWavelength(val);
1341 }
1342 } else if (str == "column_14") {
1343 NXInt nxInt = nx_tw.openNXInt(str);
1344 nxInt.load();
1345
1346 for (int r = 0; r < numberPeaks; r++) {
1347 int ival = nxInt[r];
1348 if (ival != -1)
1349 peakWS->getPeak(r).setRunNumber(ival);
1350 }
1351 } else if (str == "column_17") {
1352 NXInt nxInt = nx_tw.openNXInt(str);
1353 nxInt.load();
1354
1355 for (int r = 0; r < numberPeaks; r++) {
1356 int ival = nxInt[r];
1357 peakWS->getPeak(r).setPeakNumber(ival);
1358 }
1359 } else if (str == "column_18") {
1360 NXDouble nxDouble = nx_tw.openNXDouble(str);
1361 nxDouble.load();
1362
1363 for (int r = 0; r < numberPeaks; r++) {
1364 double val = nxDouble[r];
1365 peakWS->getPeak(r).setAbsorptionWeightedPathLength(val);
1366 }
1367 } else if (str == "column_15") {
1368 NXDouble nxDouble = nx_tw.openNXDouble(str);
1369 nxDouble.load();
1370 Kernel::Matrix<double> gm(3, 3, false);
1371 int k = 0;
1372 for (int r = 0; r < numberPeaks; r++) {
1373 for (int j = 0; j < 9; j++) {
1374 double val = nxDouble[k];
1375 k++;
1376 gm[j % 3][j / 3] = val;
1377 }
1378 peakWS->getPeak(r).setGoniometerMatrix(gm);
1379 }
1380 } else if (str == "column_16") {
1381 // Read shape information
1382 using namespace Mantid::DataObjects;
1383
1384 PeakShapeFactory_sptr peakFactoryEllipsoid = std::make_shared<PeakShapeEllipsoidFactory>();
1385 PeakShapeFactory_sptr peakFactorySphere = std::make_shared<PeakShapeSphericalFactory>();
1386 PeakShapeFactory_sptr peakFactoryNone = std::make_shared<PeakNoShapeFactory>();
1387
1388 peakFactoryEllipsoid->setSuccessor(peakFactorySphere);
1389 peakFactorySphere->setSuccessor(peakFactoryNone);
1390
1391 NXInfo info = nx_tw.getDataSetInfo(str);
1392 NXChar data = nx_tw.openNXChar(str);
1393
1394 const int maxShapeJSONLength = info.dims[1];
1395 data.load();
1396 for (int i = 0; i < numberPeaks; ++i) {
1397
1398 // iR = peak row number
1399 auto startPoint = data() + (maxShapeJSONLength * i);
1400 std::string shapeJSON(startPoint, startPoint + maxShapeJSONLength);
1401 boost::trim_right(shapeJSON);
1402
1403 // Make the shape
1404 Mantid::Geometry::PeakShape *peakShape = peakFactoryEllipsoid->create(shapeJSON);
1405
1406 // Set the shape
1407 peakWS->getPeak(i).setPeakShape(peakShape);
1408 }
1409 }
1410 // After all columns read set IntHKL
1411 for (int r = 0; r < numberPeaks; r++) {
1412 V3D intHKL = V3D(peakWS->getPeak(r).getH(), peakWS->getPeak(r).getK(), peakWS->getPeak(r).getL());
1413 peakWS->getPeak(r).setIntHKL(intHKL);
1414 }
1415 }
1416
1417 return std::static_pointer_cast<API::Workspace>(peakWS);
1418}
1419
1420//-------------------------------------------------------------------------------------------------
1436 const double &progressStart,
1437 const double &progressRange, const NXEntry &mtd_entry,
1438 const int xlength, std::string &workspaceType) {
1439 // Filter the list of spectra to process, applying min/max/list options
1440 NXDataSetTyped<double> data = wksp_cls.openDoubleData();
1441 int nchannels = data.dim1();
1442 size_t nspectra = data.dim0();
1443 // process optional spectrum parameters, if set
1444 checkOptionalProperties(nspectra);
1445 // Actual number of spectra in output workspace (if only a range was going to be loaded)
1446 size_t total_specs = calculateWorkspaceSize(nspectra);
1447
1448 if (nchannels == 1 && nspectra == 1) {
1449 // if there is only one value of channels and nspectra, it may be a WorkspaceSingleValue
1450 // check for instrument
1451 bool hasInstrument = mtd_entry.containsGroup("instrument");
1452 if (hasInstrument) {
1453 std::string inst_name = mtd_entry.getString("instrument/name");
1454 boost::algorithm::trim(inst_name);
1455 if (inst_name == "")
1456 hasInstrument = false;
1457 } else {
1458 // data saved with SaveNexusESS will have the instrument in a directory named after it
1459 // check for special types of instrument: "basic_rect" and "unspecified_instrument":
1460 if (mtd_entry.containsGroup("basic_rect") || mtd_entry.containsGroup("unspecified_instrument")) {
1461 hasInstrument = true;
1462 } else {
1463 // check for other possible instruments
1464 for (auto facility : ConfigService::Instance().getFacilities()) {
1465 for (auto instrumentName : facility->instruments()) {
1466 if (instrumentName.name() != "" && mtd_entry.containsGroup(instrumentName.name())) {
1467 hasInstrument = true;
1468 break;
1469 }
1470 }
1471 }
1472 }
1473 }
1474 // check for metadata
1475 bool hasMetadata = mtd_entry.containsGroup("logs");
1476 if (hasMetadata) {
1477 // if there is more than one log (called "goniometer") then it's not a single-valued ws
1478 const auto nLogs = mtd_entry.openNXGroup("logs").groups().size();
1479 if (nLogs <= 1) { // only "goniometer" group is present, thus it's a single-valued ws
1480 hasMetadata = false;
1481 }
1482 }
1483 // a workspace with no instrument and no metadata, and only one entry is a single-valued ws
1484 if (!hasInstrument && !hasMetadata)
1485 workspaceType = "WorkspaceSingleValue";
1486 }
1487 bool hasFracArea = false;
1488 if (wksp_cls.isValid("frac_area")) {
1489 // frac_area entry is the signal for a RebinnedOutput workspace
1490 hasFracArea = true;
1491 workspaceType = "RebinnedOutput";
1492 }
1493
1494 API::MatrixWorkspace_sptr local_workspace = std::dynamic_pointer_cast<API::MatrixWorkspace>(
1495 WorkspaceFactory::Instance().create(workspaceType, total_specs, xlength, nchannels));
1496 try {
1497 local_workspace->setTitle(mtd_entry.getString("title"));
1498 } catch (std::runtime_error &) {
1499 g_log.debug() << "No title was found in the input file, " << getPropertyValue("Filename") << '\n';
1500 }
1501
1502 // Set the YUnit label
1503 local_workspace->setYUnit(data.attributes("units"));
1504 std::string unitLabel = data.attributes("unit_label");
1505 if (unitLabel.empty())
1506 unitLabel = data.attributes("units");
1507 local_workspace->setYUnitLabel(unitLabel);
1508
1509 readBinMasking(wksp_cls, local_workspace);
1510 NXDataSetTyped<double> errors = wksp_cls.openNXDouble("errors");
1511 NXDataSetTyped<double> fracarea = errors;
1512 if (hasFracArea) {
1513 fracarea = wksp_cls.openNXDouble("frac_area");
1514
1515 // Set the fractional area attributes, default values consistent with
1516 // previous assumptions: finalized = true, sqrdErrs = false
1517 auto rbWS = std::dynamic_pointer_cast<RebinnedOutput>(local_workspace);
1518 auto finalizedValue = fracarea.attributes("finalized");
1519 auto finalized = (finalizedValue.empty() ? true : finalizedValue == "1");
1520 rbWS->setFinalized(finalized);
1521 auto sqrdErrsValue = fracarea.attributes("sqrd_errors");
1522 auto sqrdErrs = (sqrdErrsValue.empty() ? false : sqrdErrsValue == "1");
1523 rbWS->setSqrdErrors(sqrdErrs);
1524 }
1525
1526 // Check for x errors; as with fracArea we set it to xbins
1527 // although in this case it would never be used.
1528 auto hasXErrors = wksp_cls.isValid("xerrors");
1529 auto xErrors = hasXErrors ? wksp_cls.openNXDouble("xerrors") : errors;
1530 if (hasXErrors) {
1531 if (xErrors.dim1() == nchannels + 1)
1532 g_log.warning() << "Legacy X uncertainty found in input file, i.e., "
1533 "delta-Q for each BIN EDGE. Uncertainties will be "
1534 "re-interpreted as delta-Q of the BIN CENTRE and the "
1535 "last value will be dropped.\n";
1536 }
1537
1538 int blocksize = 8;
1539 // const int fullblocks = nspectra / blocksize;
1540 // size of the workspace
1541 // have to cast down to int as later functions require ints
1542 int fullblocks = static_cast<int>(total_specs) / blocksize;
1543 int read_stop = (fullblocks * blocksize);
1544 const double progressBegin = progressStart + 0.25 * progressRange;
1545 const double progressScaler = 0.75 * progressRange;
1546 int hist_index = 0;
1547 int wsIndex = 0;
1548 if (m_shared_bins) {
1549 // if spectrum min,max,list properties are set
1550 if (m_interval || m_list) {
1551 // if spectrum max,min properties are set read the data as a
1552 // block(multiple of 8) and
1553 // then read the remaining data as finalblock
1554 if (m_interval) {
1555 // specs at the min-max interval
1556 int interval_specs = m_spec_max - m_spec_min;
1557 fullblocks = (interval_specs) / blocksize;
1558 read_stop = (fullblocks * blocksize) + m_spec_min - 1;
1559
1560 if (interval_specs < blocksize) {
1561 blocksize = static_cast<int>(total_specs);
1562 read_stop = m_spec_max - 1;
1563 }
1564 hist_index = m_spec_min - 1;
1565
1566 for (; hist_index < read_stop;) {
1567 progress(progressBegin + progressScaler * static_cast<double>(hist_index) / static_cast<double>(read_stop),
1568 "Reading workspace data...");
1569 loadBlock(data, errors, fracarea, hasFracArea, xErrors, hasXErrors, blocksize, nchannels, hist_index, wsIndex,
1570 local_workspace);
1571 }
1572 size_t finalblock = m_spec_max - 1 - read_stop;
1573 if (finalblock > 0) {
1574 loadBlock(data, errors, fracarea, hasFracArea, xErrors, hasXErrors, static_cast<int>(finalblock), nchannels,
1575 hist_index, wsIndex, local_workspace);
1576 }
1577 }
1578 // if spectrum list property is set read each spectrum separately by
1579 // setting blocksize=1
1580 if (m_list) {
1581 for (const auto itr : m_spec_list) {
1582 int specIndex = itr - 1;
1583 progress(progressBegin +
1584 progressScaler * static_cast<double>(specIndex) / static_cast<double>(m_spec_list.size()),
1585 "Reading workspace data...");
1586 loadBlock(data, errors, fracarea, hasFracArea, xErrors, hasXErrors, 1, nchannels, specIndex, wsIndex,
1587 local_workspace);
1588 }
1589 }
1590 } else {
1591 for (; hist_index < read_stop;) {
1592 progress(progressBegin + progressScaler * static_cast<double>(hist_index) / static_cast<double>(read_stop),
1593 "Reading workspace data...");
1594 loadBlock(data, errors, fracarea, hasFracArea, xErrors, hasXErrors, blocksize, nchannels, hist_index, wsIndex,
1595 local_workspace);
1596 }
1597 size_t finalblock = total_specs - read_stop;
1598 if (finalblock > 0) {
1599 loadBlock(data, errors, fracarea, hasFracArea, xErrors, hasXErrors, static_cast<int>(finalblock), nchannels,
1600 hist_index, wsIndex, local_workspace);
1601 }
1602 }
1603
1604 } else {
1605 if (m_interval || m_list) {
1606 if (m_interval) {
1607 int interval_specs = m_spec_max - m_spec_min;
1608 fullblocks = (interval_specs) / blocksize;
1609 read_stop = (fullblocks * blocksize) + m_spec_min - 1;
1610
1611 if (interval_specs < blocksize) {
1612 blocksize = interval_specs;
1613 read_stop = m_spec_max - 1;
1614 }
1615 hist_index = m_spec_min - 1;
1616
1617 for (; hist_index < read_stop;) {
1618 progress(progressBegin + progressScaler * static_cast<double>(hist_index) / static_cast<double>(read_stop),
1619 "Reading workspace data...");
1620 loadBlock(data, errors, fracarea, hasFracArea, xErrors, hasXErrors, xbins, blocksize, nchannels, hist_index,
1621 wsIndex, local_workspace);
1622 }
1623 size_t finalblock = m_spec_max - 1 - read_stop;
1624 if (finalblock > 0) {
1625 loadBlock(data, errors, fracarea, hasFracArea, xErrors, hasXErrors, xbins, static_cast<int>(finalblock),
1626 nchannels, hist_index, wsIndex, local_workspace);
1627 }
1628 }
1629 //
1630 if (m_list) {
1631 for (const auto itr : m_spec_list) {
1632 int specIndex = itr - 1;
1633 progress(progressBegin + progressScaler * static_cast<double>(specIndex) / static_cast<double>(read_stop),
1634 "Reading workspace data...");
1635 loadBlock(data, errors, fracarea, hasFracArea, xErrors, hasXErrors, xbins, 1, nchannels, specIndex, wsIndex,
1636 local_workspace);
1637 }
1638 }
1639 } else {
1640 for (; hist_index < read_stop;) {
1641 progress(progressBegin + progressScaler * static_cast<double>(hist_index) / static_cast<double>(read_stop),
1642 "Reading workspace data...");
1643 loadBlock(data, errors, fracarea, hasFracArea, xErrors, hasXErrors, xbins, blocksize, nchannels, hist_index,
1644 wsIndex, local_workspace);
1645 }
1646 size_t finalblock = total_specs - read_stop;
1647 if (finalblock > 0) {
1648 loadBlock(data, errors, fracarea, hasFracArea, xErrors, hasXErrors, xbins, static_cast<int>(finalblock),
1649 nchannels, hist_index, wsIndex, local_workspace);
1650 }
1651 }
1652 }
1653 return local_workspace;
1654}
1655
1656//-------------------------------------------------------------------------------------------------
1669API::Workspace_sptr LoadNexusProcessed::loadEntry(NXRoot &root, const std::string &entry_name,
1670 const double &progressStart, const double &progressRange) {
1671 progress(progressStart, "Opening entry " + entry_name + "...");
1672
1673 NXEntry mtd_entry = root.openEntry(entry_name);
1674
1675 if (mtd_entry.containsGroup("table_workspace")) {
1676 return loadTableEntry(mtd_entry);
1677 }
1678
1679 if (mtd_entry.containsGroup("peaks_workspace")) {
1680 try {
1681 // try standard PeakWorkspace first
1682 return loadPeaksEntry(mtd_entry);
1683 } catch (std::exception &) {
1684 return loadLeanElasticPeaksEntry(mtd_entry);
1685 }
1686 }
1687
1688 // Determine workspace type and name of group containing workspace
1689 // characteristics
1690 bool isEvent = false;
1691 std::string workspaceType = "Workspace2D";
1692 std::string group_name = "workspace";
1693 if (mtd_entry.containsGroup("event_workspace")) {
1694 isEvent = true;
1695 group_name = "event_workspace";
1696 } else if (mtd_entry.containsGroup("offsets_workspace")) {
1697 workspaceType = "OffsetsWorkspace";
1698 group_name = "offsets_workspace";
1699 } else if (mtd_entry.containsGroup("mask_workspace")) {
1700 workspaceType = "MaskWorkspace";
1701 group_name = "mask_workspace";
1702 }
1703
1704 // Get workspace characteristics
1705 NXData wksp_cls = mtd_entry.openNXData(group_name);
1706
1707 // Axis information
1708 // "X" axis
1709
1710 NXDouble xbins = wksp_cls.openNXDouble("axis1");
1711 xbins.load();
1712 std::string unit1 = xbins.attributes("units");
1713 // Non-uniform x bins get saved as a 2D 'axis1' dataset
1714 int xlength(-1);
1715 if (xbins.rank() == 2) {
1716 xlength = xbins.dim1();
1717 m_shared_bins = false;
1718 } else if (xbins.rank() == 1) {
1719 xlength = xbins.dim0();
1720 m_shared_bins = true;
1721 xbins.load();
1722 m_xbins = HistogramData::HistogramX(xbins(), xbins() + xlength);
1723 } else {
1724 throw std::runtime_error("Unknown axis1 dimension encountered.");
1725 }
1726
1727 // MatrixWorkspace axis 1
1728 NXDouble axis2 = wksp_cls.openNXDouble("axis2");
1729 std::string unit2 = axis2.attributes("units");
1730
1731 // --- Load workspace (as event_workspace or workspace2d) ---
1732 API::MatrixWorkspace_sptr local_workspace;
1733 if (isEvent) {
1734 local_workspace = loadEventEntry(wksp_cls, xbins, progressStart, progressRange);
1735 } else {
1736 local_workspace =
1737 loadNonEventEntry(wksp_cls, xbins, progressStart, progressRange, mtd_entry, xlength, workspaceType);
1738 }
1739 size_t nspectra = local_workspace->getNumberHistograms();
1740
1741 // Units
1742 bool verticalHistogram(false);
1743 try {
1744 local_workspace->getAxis(0)->unit() = UnitFactory::Instance().create(unit1);
1745 if (unit1 == "Label") {
1746 auto label = std::dynamic_pointer_cast<Mantid::Kernel::Units::Label>(local_workspace->getAxis(0)->unit());
1747 auto ax = wksp_cls.openNXDouble("axis1");
1748 label->setLabel(ax.attributes("caption"), ax.attributes("label"));
1749 }
1750
1751 // If this doesn't throw then it is a numeric access so grab the data so
1752 // we
1753 // can set it later
1754 axis2.load();
1755 if (static_cast<size_t>(axis2.size()) == nspectra + 1)
1756 verticalHistogram = true;
1757 m_axis1vals = MantidVec(axis2(), axis2() + axis2.dim0());
1758 } catch (std::runtime_error &) {
1759 g_log.information() << "Axis 0 set to unitless quantity \"" << unit1 << "\"\n";
1760 }
1761
1762 // Setting a unit onto a TextAxis makes no sense.
1763 if (unit2 == "TextAxis") {
1764 auto newAxis = std::make_unique<Mantid::API::TextAxis>(nspectra);
1765 local_workspace->replaceAxis(1, std::move(newAxis));
1766 } else if (unit2 != "spectraNumber") {
1767 try {
1768 auto newAxis = (verticalHistogram) ? std::make_unique<API::BinEdgeAxis>(nspectra + 1)
1769 : std::make_unique<API::NumericAxis>(nspectra);
1770 auto newAxisRaw = newAxis.get();
1771 local_workspace->replaceAxis(1, std::move(newAxis));
1772 newAxisRaw->unit() = UnitFactory::Instance().create(unit2);
1773 if (unit2 == "Label") {
1774 auto label = std::dynamic_pointer_cast<Mantid::Kernel::Units::Label>(newAxisRaw->unit());
1775 auto ax = wksp_cls.openNXDouble("axis2");
1776 label->setLabel(ax.attributes("caption"), ax.attributes("label"));
1777 }
1778 } catch (std::runtime_error &) {
1779 g_log.information() << "Axis 1 set to unitless quantity \"" << unit2 << "\"\n";
1780 }
1781 }
1782
1783 // Are we a distribution
1784 std::string dist = xbins.attributes("distribution");
1785 if (dist == "1") {
1786 local_workspace->setDistribution(true);
1787 } else {
1788 local_workspace->setDistribution(false);
1789 }
1790
1791 // Get information from all but data group
1792 std::string parameterStr;
1793
1794 progress(progressStart + 0.05 * progressRange, "Reading the sample details...");
1795
1796 // Hop to the right point
1797 m_nexusFile->openPath(mtd_entry.path());
1798 try {
1799 // This loads logs, sample, and instrument.
1800 local_workspace->loadExperimentInfoNexus(getPropertyValue("Filename"), m_nexusFile.get(),
1801 parameterStr); // REQUIRED PER PERIOD
1802
1803 // Parameter map parsing only if instrument loaded OK.
1804 progress(progressStart + 0.11 * progressRange, "Reading the parameter maps...");
1805 local_workspace->readParameterMap(parameterStr);
1806 } catch (std::exception &e) {
1807 // TODO. For workspaces saved via SaveNexusESS, these warnings are not
1808 // relevant. Unfortunately we need to close all file handles before we can
1809 // attempt loading the new way see loadNexusGeometry function . A better
1810 // solution should be found
1811 g_log.warning("Error loading Instrument section of nxs file");
1812 g_log.warning(e.what());
1813 g_log.warning("Try running LoadInstrument Algorithm on the Workspace to "
1814 "update the geometry");
1815 }
1816
1817 readSpectraToDetectorMapping(mtd_entry, *local_workspace);
1818
1819 if (!local_workspace->getAxis(1)->isSpectra()) { // If not a spectra axis, load the axis data into
1820 // the workspace. (MW 25/11/10)
1821 loadNonSpectraAxis(local_workspace, wksp_cls);
1822 }
1823
1824 progress(progressStart + 0.15 * progressRange, "Reading the workspace history...");
1825 m_nexusFile->openPath(mtd_entry.path());
1826 try {
1827 bool load_history = getProperty("LoadHistory");
1828 if (load_history)
1829 local_workspace->history().loadNexus(m_nexusFile.get());
1830 } catch (std::out_of_range &) {
1831 g_log.warning() << "Error in the workspaces algorithm list, its processing "
1832 "history is incomplete\n";
1833 }
1834
1835 progress(progressStart + 0.2 * progressRange, "Reading the workspace history...");
1836
1837 try {
1838 if (local_workspace->getTitle().empty())
1839 local_workspace->setTitle(mtd_entry.getString("title"));
1840 } catch (std::runtime_error &) {
1841 g_log.debug() << "No title was found in the input file, " << getPropertyValue("Filename") << '\n';
1842 }
1843
1844 return std::static_pointer_cast<API::Workspace>(local_workspace);
1845}
1846
1847//-------------------------------------------------------------------------------------------------
1854 // Get spectrum information for the current entry.
1855
1856 SpectraInfo spectraInfo = extractMappingInfo(mtd_entry, this->g_log);
1857
1858 // Now build the spectra list
1859 int index = 0;
1860 bool haveSpectraAxis = local_workspace.getAxis(1)->isSpectra();
1861
1862 for (int i = 1; i <= spectraInfo.nSpectra; ++i) {
1863 int spectrum;
1864 // prefer the spectra number from the instrument section
1865 // over anything else. If not there then use a spectra axis
1866 // number if we have one, else make one up as nothing was
1867 // written to the file. We should always set it so that
1868 // CompareWorkspaces gives the expected answer on a Save/Load
1869 // round trip.
1870 if (spectraInfo.hasSpectra) {
1871 spectrum = spectraInfo.spectraNumbers[i - 1];
1872 } else if (haveSpectraAxis && !m_axis1vals.empty()) {
1873 spectrum = static_cast<specnum_t>(m_axis1vals[i - 1]);
1874 } else {
1875 spectrum = i + 1;
1876 }
1877
1878 if ((i >= m_spec_min && i < m_spec_max) ||
1879 (m_list && find(m_spec_list.begin(), m_spec_list.end(), i) != m_spec_list.end())) {
1880 auto &spec = local_workspace.getSpectrum(index);
1881 spec.setSpectrumNo(spectrum);
1882 ++index;
1883
1884 if (!spectraInfo.detectorIndex.empty()) {
1885 const int start = spectraInfo.detectorIndex[i - 1];
1886 const int end = start + spectraInfo.detectorCount[i - 1];
1887 spec.setDetectorIDs(
1888 std::set<detid_t>(spectraInfo.detectorList.data() + start, spectraInfo.detectorList.data() + end));
1889 }
1890 }
1891 }
1892}
1893
1898std::map<std::string, std::string> LoadNexusProcessed::validateInputs() {
1899 using namespace std;
1900 map<string, string> errorList;
1901
1902 int specMin = getProperty("SpectrumMin");
1903 int specMax = getProperty("SpectrumMax");
1904
1905 // Check our range is not reversed
1906 if (specMax < specMin) {
1907 errorList["SpectrumMin"] = "SpectrumMin must be smaller than SpectrumMax";
1908 errorList["SpectrumMax"] = "SpectrumMax must be larger than SpectrumMin";
1909 }
1910
1911 // Finished testing return any errors
1912 return errorList;
1913}
1914
1915//-------------------------------------------------------------------------------------------------
1925 Axis *axis = local_workspace->getAxis(1);
1926
1927 if (axis->isNumeric()) {
1928 NXDouble axisData = data.openNXDouble("axis2");
1929 axisData.load();
1930 for (int i = 0; i < static_cast<int>(axis->length()); i++) {
1931 axis->setValue(i, axisData[i]);
1932 }
1933 } else if (axis->isText()) {
1934 NXChar axisData = data.openNXChar("axis2");
1935 std::string axisLabels;
1936 try {
1937 axisData.load();
1938 axisLabels = std::string(axisData(), axisData.dim0());
1939 } catch (std::runtime_error &) {
1940 axisLabels = "";
1941 }
1942 // Use boost::tokenizer to split up the input
1944 // We must cast the axis object to TextAxis so we may use ->setLabel
1945 auto *textAxis = static_cast<TextAxis *>(axis);
1946 int i = 0;
1947 for (const auto &tokIter : tokenizer) {
1948 textAxis->setLabel(i, tokIter);
1949 i++;
1950 }
1951 }
1952}
1953
1960bool UDlesserExecCount(const NXClassInfo &elem1, const NXClassInfo &elem2) {
1961 std::string::size_type index1, index2;
1962 std::string num1, num2;
1963 // find the number after "_" in algorithm name ( eg:MantidAlogorthm_1)
1964 index1 = elem1.nxname.find('_');
1965 if (index1 != std::string::npos) {
1966 num1 = elem1.nxname.substr(index1 + 1, elem1.nxname.length() - index1);
1967 }
1968 index2 = elem2.nxname.find('_');
1969 if (index2 != std::string::npos) {
1970 num2 = elem2.nxname.substr(index2 + 1, elem2.nxname.length() - index2);
1971 }
1972 std::stringstream is1, is2;
1973 is1 << num1;
1974 is2 << num2;
1975
1976 int execNum1 = -1;
1977 int execNum2 = -1;
1978 is1 >> execNum1;
1979 is2 >> execNum2;
1980
1981 return execNum1 < execNum2;
1982}
1983
1984//-------------------------------------------------------------------------------------------------
1994void LoadNexusProcessed::getWordsInString(const std::string &words3, std::string &w1, std::string &w2,
1995 std::string &w3) {
1997 if (data.count() != 3) {
1998 g_log.warning() << "Algorithm list line " + words3 + " is not of the correct format\n";
1999 throw std::out_of_range(words3);
2000 }
2001
2002 w1 = data[0];
2003 w2 = data[1];
2004 w3 = data[2];
2005}
2006
2007//-------------------------------------------------------------------------------------------------
2018void LoadNexusProcessed::getWordsInString(const std::string &words4, std::string &w1, std::string &w2, std::string &w3,
2019 std::string &w4) {
2021 if (data.count() != 4) {
2022 g_log.warning() << "Algorithm list line " + words4 + " is not of the correct format\n";
2023 throw std::out_of_range(words4);
2024 }
2025
2026 w1 = data[0];
2027 w2 = data[1];
2028 w3 = data[2];
2029 w4 = data[3];
2030}
2031
2032//-------------------------------------------------------------------------------------------------
2039void LoadNexusProcessed::readBinMasking(const NXData &wksp_cls, const API::MatrixWorkspace_sptr &local_workspace) {
2040 if (wksp_cls.getDataSetInfo("masked_spectra").stat == NX_ERROR) {
2041 return;
2042 }
2043 NXInt spec = wksp_cls.openNXInt("masked_spectra");
2044 spec.load();
2045 NXSize bins = wksp_cls.openNXSize("masked_bins");
2046 bins.load();
2047 NXDouble weights = wksp_cls.openNXDouble("mask_weights");
2048 weights.load();
2049 const int n = spec.dim0();
2050 const int n1 = n - 1;
2051 for (int i = 0; i < n; ++i) {
2052 int si = spec(i, 0);
2053 int j0 = spec(i, 1);
2054 int j1 = i < n1 ? spec(i + 1, 1) : bins.dim0();
2055 for (int j = j0; j < j1; ++j) {
2056 local_workspace->flagMasked(si, bins[j], weights[j]);
2057 }
2058 }
2059}
2060
2078 NXDataSetTyped<double> &farea, bool hasFArea, NXDouble &xErrors, bool hasXErrors,
2079 int blocksize, int nchannels, int &hist,
2080 const API::MatrixWorkspace_sptr &local_workspace) {
2081 data.load(blocksize, hist);
2082 errors.load(blocksize, hist);
2083 double *data_start = data();
2084 double *data_end = data_start + nchannels;
2085 double *err_start = errors();
2086 double *err_end = err_start + nchannels;
2087 double *farea_start = nullptr;
2088 double *farea_end = nullptr;
2089 double *xErrors_start = nullptr;
2090 double *xErrors_end = nullptr;
2091 size_t dx_increment = nchannels;
2092 // NexusFileIO stores Dx data for all spectra (sharing not preserved) so dim0
2093 // is the histograms, dim1 is Dx length. For old files this is nchannels+1,
2094 // otherwise nchannels. See #16298.
2095 // WARNING: We are dropping the last Dx value for old files!
2096 size_t dx_input_increment = xErrors.dim1();
2097 RebinnedOutput_sptr rb_workspace;
2098 if (hasFArea) {
2099 farea.load(blocksize, hist);
2100 farea_start = farea();
2101 farea_end = farea_start + nchannels;
2102 rb_workspace = std::dynamic_pointer_cast<RebinnedOutput>(local_workspace);
2103 }
2104 if (hasXErrors) {
2105 xErrors.load(blocksize, hist);
2106 xErrors_start = xErrors();
2107 xErrors_end = xErrors_start + dx_increment;
2108 }
2109
2110 int final(hist + blocksize);
2111 while (hist < final) {
2112 auto &Y = local_workspace->mutableY(hist);
2113 Y.assign(data_start, data_end);
2114 data_start += nchannels;
2115 data_end += nchannels;
2116 auto &E = local_workspace->mutableE(hist);
2117 E.assign(err_start, err_end);
2118 err_start += nchannels;
2119 err_end += nchannels;
2120 if (hasFArea) {
2121 MantidVec &F = rb_workspace->dataF(hist);
2122 F.assign(farea_start, farea_end);
2123 farea_start += nchannels;
2124 farea_end += nchannels;
2125 }
2126 if (hasXErrors) {
2127 local_workspace->setSharedDx(hist, Kernel::make_cow<HistogramData::HistogramDx>(xErrors_start, xErrors_end));
2128 xErrors_start += dx_input_increment;
2129 xErrors_end += dx_input_increment;
2130 }
2131
2132 local_workspace->setSharedX(hist, m_xbins.cowData());
2133 ++hist;
2134 }
2135}
2136
2156 NXDataSetTyped<double> &farea, bool hasFArea, NXDouble &xErrors, bool hasXErrors,
2157 int blocksize, int nchannels, int &hist, int &wsIndex,
2158 const API::MatrixWorkspace_sptr &local_workspace) {
2159 data.load(blocksize, hist);
2160 errors.load(blocksize, hist);
2161 double *data_start = data();
2162 double *data_end = data_start + nchannels;
2163 double *err_start = errors();
2164 double *err_end = err_start + nchannels;
2165 double *farea_start = nullptr;
2166 double *farea_end = nullptr;
2167 double *xErrors_start = nullptr;
2168 double *xErrors_end = nullptr;
2169 size_t dx_increment = nchannels;
2170 // NexusFileIO stores Dx data for all spectra (sharing not preserved) so dim0
2171 // is the histograms, dim1 is Dx length. For old files this is nchannels+1,
2172 // otherwise nchannels. See #16298.
2173 // WARNING: We are dropping the last Dx value for old files!
2174 size_t dx_input_increment = xErrors.dim1();
2175 RebinnedOutput_sptr rb_workspace;
2176 if (hasFArea) {
2177 farea.load(blocksize, hist);
2178 farea_start = farea();
2179 farea_end = farea_start + nchannels;
2180 rb_workspace = std::dynamic_pointer_cast<RebinnedOutput>(local_workspace);
2181 }
2182 if (hasXErrors) {
2183 xErrors.load(blocksize, hist);
2184 xErrors_start = xErrors();
2185 xErrors_end = xErrors_start + dx_increment;
2186 }
2187
2188 int final(hist + blocksize);
2189 while (hist < final) {
2190 auto &Y = local_workspace->mutableY(wsIndex);
2191 Y.assign(data_start, data_end);
2192 data_start += nchannels;
2193 data_end += nchannels;
2194 auto &E = local_workspace->mutableE(wsIndex);
2195 E.assign(err_start, err_end);
2196 err_start += nchannels;
2197 err_end += nchannels;
2198 if (hasFArea) {
2199 MantidVec &F = rb_workspace->dataF(wsIndex);
2200 F.assign(farea_start, farea_end);
2201 farea_start += nchannels;
2202 farea_end += nchannels;
2203 }
2204 if (hasXErrors) {
2205 local_workspace->setSharedDx(wsIndex, Kernel::make_cow<HistogramData::HistogramDx>(xErrors_start, xErrors_end));
2206 xErrors_start += dx_input_increment;
2207 xErrors_end += dx_input_increment;
2208 }
2209 local_workspace->setSharedX(wsIndex, m_xbins.cowData());
2210 ++hist;
2211 ++wsIndex;
2212 }
2213}
2214
2234 NXDataSetTyped<double> &farea, bool hasFArea, NXDouble &xErrors, bool hasXErrors,
2235 NXDouble &xbins, int blocksize, int nchannels, int &hist, int &wsIndex,
2236 const API::MatrixWorkspace_sptr &local_workspace) {
2237 data.load(blocksize, hist);
2238 double *data_start = data();
2239 double *data_end = data_start + nchannels;
2240 errors.load(blocksize, hist);
2241 double *err_start = errors();
2242 double *err_end = err_start + nchannels;
2243 double *farea_start = nullptr;
2244 double *farea_end = nullptr;
2245 double *xErrors_start = nullptr;
2246 double *xErrors_end = nullptr;
2247 size_t dx_increment = nchannels;
2248 // NexusFileIO stores Dx data for all spectra (sharing not preserved) so dim0
2249 // is the histograms, dim1 is Dx length. For old files this is nchannels+1,
2250 // otherwise nchannels. See #16298.
2251 // WARNING: We are dropping the last Dx value for old files!
2252 size_t dx_input_increment = xErrors.dim1();
2253 RebinnedOutput_sptr rb_workspace;
2254 if (hasFArea) {
2255 farea.load(blocksize, hist);
2256 farea_start = farea();
2257 farea_end = farea_start + nchannels;
2258 rb_workspace = std::dynamic_pointer_cast<RebinnedOutput>(local_workspace);
2259 }
2260 xbins.load(blocksize, hist);
2261 const int nxbins(xbins.dim1());
2262 double *xbin_start = xbins();
2263 double *xbin_end = xbin_start + nxbins;
2264 int final(hist + blocksize);
2265
2266 if (hasXErrors) {
2267 xErrors.load(blocksize, hist);
2268 xErrors_start = xErrors();
2269 xErrors_end = xErrors_start + dx_increment;
2270 }
2271
2272 while (hist < final) {
2273 auto &Y = local_workspace->mutableY(wsIndex);
2274 Y.assign(data_start, data_end);
2275 data_start += nchannels;
2276 data_end += nchannels;
2277 auto &E = local_workspace->mutableE(wsIndex);
2278 E.assign(err_start, err_end);
2279 err_start += nchannels;
2280 err_end += nchannels;
2281 if (hasFArea) {
2282 MantidVec &F = rb_workspace->dataF(wsIndex);
2283 F.assign(farea_start, farea_end);
2284 farea_start += nchannels;
2285 farea_end += nchannels;
2286 }
2287 if (hasXErrors) {
2288 local_workspace->setSharedDx(wsIndex, Kernel::make_cow<HistogramData::HistogramDx>(xErrors_start, xErrors_end));
2289 xErrors_start += dx_input_increment;
2290 xErrors_end += dx_input_increment;
2291 }
2292 auto &X = local_workspace->mutableX(wsIndex);
2293 X.assign(xbin_start, xbin_end);
2294 xbin_start += nxbins;
2295 xbin_end += nxbins;
2296 ++hist;
2297 ++wsIndex;
2298 }
2299}
2300
2305void LoadNexusProcessed::checkOptionalProperties(const std::size_t numberofspectra) {
2306 // read in the settings passed to the algorithm
2307 m_spec_list = getProperty("SpectrumList");
2308 m_spec_max = getProperty("SpectrumMax");
2309 m_spec_min = getProperty("SpectrumMin");
2310 // Are we using a list of spectra or all the spectra in a range?
2311 m_list = !m_spec_list.empty();
2314 m_spec_max = 1;
2315
2316 // Check validity of spectra list property, if set
2317 if (m_list) {
2318 const int minlist = *min_element(m_spec_list.begin(), m_spec_list.end());
2319 const int maxlist = *max_element(m_spec_list.begin(), m_spec_list.end());
2320 // Need to check before casting
2321 if (maxlist < 0) {
2322 g_log.error("Invalid list of spectra");
2323 throw std::invalid_argument("Spectra max is less than 0");
2324 }
2325
2326 if (maxlist > static_cast<int>(numberofspectra) || minlist == 0) {
2327 g_log.error("Invalid list of spectra");
2328 throw std::invalid_argument("Inconsistent properties defined");
2329 }
2330 }
2331
2332 // Check validity of spectra range, if set
2333 if (m_interval) {
2334 m_interval = true;
2335 m_spec_min = getProperty("SpectrumMin");
2336 if (m_spec_min != 1 && m_spec_max == 1) {
2337 m_spec_max = static_cast<int>(numberofspectra);
2338 }
2339 if (m_spec_max < m_spec_min || m_spec_max > static_cast<int>(numberofspectra)) {
2340 g_log.error("Invalid Spectrum min/max properties");
2341 throw std::invalid_argument("Inconsistent properties defined");
2342 }
2343 }
2344}
2345
2359size_t LoadNexusProcessed::calculateWorkspaceSize(const std::size_t numberofspectra, bool gen_filtered_list) {
2360 // Calculate the size of a workspace, given its number of spectra to read
2361 size_t total_specs;
2362 if (m_interval || m_list) {
2363 if (m_interval) {
2364 if (m_spec_min != 1 && m_spec_max == 1) {
2365 m_spec_max = static_cast<int>(numberofspectra);
2366 }
2367 total_specs = m_spec_max - m_spec_min + 1;
2368 m_spec_max += 1;
2369
2370 if (gen_filtered_list) {
2371 m_filtered_spec_idxs.resize(total_specs);
2372 size_t j = 0;
2373 for (int si = m_spec_min; si < m_spec_max; si++, j++)
2374 m_filtered_spec_idxs[j] = si;
2375 }
2376 } else {
2377 total_specs = 0;
2378 }
2379
2380 if (m_list) {
2381 if (m_interval) {
2382 for (auto it = m_spec_list.begin(); it != m_spec_list.end();)
2383 if (*it >= m_spec_min && *it < m_spec_max) {
2384 it = m_spec_list.erase(it);
2385 } else
2386 ++it;
2387 }
2388 if (m_spec_list.empty())
2389 m_list = false;
2390 total_specs += m_spec_list.size();
2391
2392 if (gen_filtered_list) {
2393 // range list + spare indices from list
2394 // example: min: 2, max: 8, list: 3,4,5,10,12;
2395 // result: 2,3,...,7,8,10,12
2397 }
2398 }
2399 } else {
2400 total_specs = numberofspectra;
2401 m_spec_min = 1;
2402 m_spec_max = static_cast<int>(numberofspectra) + 1;
2403
2404 if (gen_filtered_list) {
2405 m_filtered_spec_idxs.resize(total_specs, 0);
2406 for (int j = 0; j < static_cast<int>(total_specs); j++)
2408 }
2409 }
2410 return total_specs;
2411}
2412
2419 auto mWorkspace = std::dynamic_pointer_cast<MatrixWorkspace>(local_workspace);
2420 if (mWorkspace) {
2421 auto run = mWorkspace->run();
2422 // check for presence of filterable logs that suggest this is ISIS data
2424 ISISRunLogs::applyLogFiltering(mWorkspace->mutableRun());
2425 }
2426 }
2427}
2428
2429} // namespace Mantid::DataHandling
double value
The value of the point.
Definition: FitMW.cpp:51
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
bool hasSpectra
IntArray detectorCount
IntArray detectorIndex
IntArray detectorList
IntArray spectraNumbers
int nSpectra
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
Definition: MultiThreaded.h:94
#define PARALLEL_FOR_NO_WSP_CHECK()
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
#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.
Definition: Algorithm.cpp:1913
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
Class to represent the axis of a workspace.
Definition: Axis.h:30
virtual bool isText() const
Returns true if the axis is Text.
Definition: Axis.h:54
virtual std::size_t length() const =0
Get the length of the axis.
virtual void setValue(const std::size_t &index, const double &value)=0
Sets the value at the specified index.
virtual bool isNumeric() const
Returns true if the axis is numeric.
Definition: Axis.h:52
virtual bool isSpectra() const
Returns true is the axis is a Spectra axis.
Definition: Axis.h:50
ColumnVector gives access to the column elements without alowing its resizing.
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
void setHistogram(T &&...data)
Sets the Histogram associated with this spectrum.
Definition: ISpectrum.h:97
void clearDetectorIDs()
Clear the detector IDs set.
Definition: ISpectrum.cpp:117
void setSpectrumNo(specnum_t num)
Sets the the spectrum number of this spectrum.
Definition: ISpectrum.cpp:127
bool hasProperty(const std::string &name) const
Does the property exist on the object.
Definition: LogManager.cpp:265
HeldType getPropertyValueAsType(const std::string &name) const
Get the value of a property as the given TYPE.
Definition: LogManager.cpp:332
Base MatrixWorkspace Abstract Class.
virtual ISpectrum & getSpectrum(const size_t index)=0
Return the underlying ISpectrum ptr at the given workspace index.
virtual Axis * getAxis(const std::size_t &axisIndex) const
Get a non owning pointer to a workspace axis.
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
This class stores information regarding an experimental run as a series of log entries.
Definition: Run.h:38
Class to represent a text axis of a workspace.
Definition: TextAxis.h:36
void setLabel(const std::size_t &index, const std::string &lbl)
Set the label at the given index.
Definition: TextAxis.cpp:104
A property class for workspaces.
static void applyLogFiltering(Mantid::API::Run &exptRun)
applies log filtering for a run
Definition: ISISRunLogs.cpp:72
API::Workspace_sptr loadTableEntry(const Mantid::NeXus::NXEntry &entry)
Load a table.
int m_spec_min
The value of the spectrum_min property.
void loadBlock(Mantid::NeXus::NXDataSetTyped< double > &data, Mantid::NeXus::NXDataSetTyped< double > &errors, Mantid::NeXus::NXDataSetTyped< double > &farea, bool hasFArea, Mantid::NeXus::NXDouble &xErrors, bool hasXErrors, int blocksize, int nchannels, int &hist, const API::MatrixWorkspace_sptr &local_workspace)
Load a block of data into the workspace where it is assumed that the x bins have already been cached.
bool m_interval
Flag set if interval of spectra to write is set.
API::MatrixWorkspace_sptr loadNonEventEntry(Mantid::NeXus::NXData &wksp_cls, Mantid::NeXus::NXDouble &xbins, const double &progressStart, const double &progressRange, const Mantid::NeXus::NXEntry &mtd_entry, const int xlength, std::string &workspaceType)
Load a Workspace2D.
int confidence(Kernel::NexusDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
void exec() override
Overwrites Algorithm method.
~LoadNexusProcessed() override
Destructor.
HistogramData::BinEdges m_xbins
The cached x binning if we have bins.
void loadNumericColumn(const Mantid::NeXus::NXData &tableData, const std::string &dataSetName, const API::ITableWorkspace_sptr &tableWs, const std::string &columnType)
Load a numeric column to the TableWorkspace.
void checkOptionalProperties(const std::size_t numberofspectra)
Validates the optional 'spectra to read' properties, if they have been set.
void correctForWorkspaceNameClash(std::string &wsName)
Add an index to the name if it already exists in the workspace.
virtual void readSpectraToDetectorMapping(Mantid::NeXus::NXEntry &mtd_entry, Mantid::API::MatrixWorkspace &ws)
std::string loadWorkspaceName(Mantid::NeXus::NXRoot &root, const std::string &entry_name)
Load the workspace name attribute if it exists.
API::Workspace_sptr loadLeanElasticPeaksEntry(Mantid::NeXus::NXEntry &entry)
Load LeanElasticPeakWorkspace.
void readInstrumentGroup(Mantid::NeXus::NXEntry &mtd_entry, API::MatrixWorkspace &local_workspace)
Read the spectra.
std::vector< std::string > extractWorkspaceNames(Mantid::NeXus::NXRoot &root, size_t nWorkspaceEntries)
Extract the workspace name.
int m_spec_max
The value of the spectrum_max property.
void loadV3DColumn(Mantid::NeXus::NXDouble &data, const API::ITableWorkspace_sptr &tableWs)
Loads a V3D column to the TableWorkspace.
bool m_list
Flag set if list of spectra to save is specifed.
void getWordsInString(const std::string &words3, std::string &w1, std::string &w2, std::string &w3)
Splits a string of exactly three words into the separate words.
virtual bool loadNexusGeometry(Mantid::API::Workspace &, const int, Kernel::Logger &, const std::string &)
Load nexus geometry and apply to workspace.
API::Workspace_sptr loadEntry(Mantid::NeXus::NXRoot &root, const std::string &entry_name, const double &progressStart, const double &progressRange)
Load a single entry.
std::vector< int > m_filtered_spec_idxs
list of spectra filtered by min/max/list, currently used only when loading data into event_workspace
void readBinMasking(const Mantid::NeXus::NXData &wksp_cls, const API::MatrixWorkspace_sptr &local_workspace)
Read the bin masking information.
bool m_shared_bins
Does the current workspace have uniform binning.
std::vector< int > m_spec_list
The value of the spectrum_list property.
Mantid::API::Workspace_sptr doAccelleratedMultiPeriodLoading(Mantid::NeXus::NXRoot &root, const std::string &entryName, Mantid::API::MatrixWorkspace_sptr &tempMatrixWorkspace, const size_t nWorkspaceEntries, const size_t p)
Accellerated multiperiod loading.
std::map< std::string, std::string > validateInputs() override
Validates the input Min < Max and Max < Maximum_Int.
API::MatrixWorkspace_sptr loadEventEntry(Mantid::NeXus::NXData &wksp_cls, Mantid::NeXus::NXDouble &xbins, const double &progressStart, const double &progressRange)
Load an event_workspace field.
std::string buildWorkspaceName(const std::string &name, const std::string &baseName, size_t wsIndex)
Create the workspace name if it's part of a group workspace.
void init() override
Overwrites Algorithm method.
MantidVec m_axis1vals
Numeric values for the second axis, if applicable.
void loadNonSpectraAxis(const API::MatrixWorkspace_sptr &local_workspace, Mantid::NeXus::NXData &data)
Load the data from a non-spectra axis (Numeric/Text) into the workspace.
API::Workspace_sptr loadPeaksEntry(Mantid::NeXus::NXEntry &entry)
Load peaks.
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
std::unique_ptr<::NeXus::File > m_nexusFile
void loadVectorColumn(const Mantid::NeXus::NXData &tableData, const std::string &dataSetName, const API::ITableWorkspace_sptr &tableWs, const std::string &columnType)
Loads a vector column to the TableWorkspace.
std::size_t calculateWorkspaceSize(const std::size_t numberofspectra, bool gen_filtered_list=false)
calculates the workspace size
void applyLogFiltering(const Mantid::API::Workspace_sptr &local_workspace)
applies log filtering of the loaded logs if required
void setRunNumber(int m_runNumber) override
Set the run number that measured this peak.
Definition: BasePeak.cpp:82
void setGoniometerMatrix(const Mantid::Kernel::Matrix< double > &goniometerMatrix) override
Set the goniometer rotation matrix at which this peak was measured.
Definition: BasePeak.cpp:220
A class for holding :
Definition: EventList.h:56
void reserve(size_t num) override
Reserve a certain number of entries in event list of the specified eventType.
Definition: EventList.cpp:895
void switchTo(Mantid::API::EventType newType) override
Switch the EventList to use the given EventType (TOF, WEIGHTED, or WEIGHTED_NOTIME)
Definition: EventList.cpp:649
void addEventQuickly(const Types::Event::TofEvent &event)
Append an event to the histogram, without clearing the cache, to make it faster.
Definition: EventList.h:104
Structure describing a single-crystal peak.
Structure describing a single-crystal peak.
Definition: Peak.h:34
void setInstrument(const Geometry::Instrument_const_sptr &inst)
Set the instrument (and save the source/sample pos).
Definition: Peak.cpp:300
Info about a single neutron detection event, including a weight and error value, but excluding the pu...
Definition: Events.h:91
Info about a single neutron detection event, including a weight and error value:
Definition: Events.h:39
PeakShape : Abstract type to describes the shape of a peak.
Definition: PeakShape.h:20
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
static const std::string statusLogName()
Returns the name of the log created that defines the status during a run.
Definition: LogParser.h:46
static const std::string periodsLogName()
Returns the name of the log that contains all of the periods.
Definition: LogParser.h:50
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition: Logger.h:52
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void notice(const std::string &msg)
Logs at notice level.
Definition: Logger.cpp:95
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
Numerical Matrix class.
Definition: Matrix.h:42
Defines a wrapper around a file whose internal structure can be accessed using the NeXus API.
bool pathExists(const std::string &path) const
Query if a path exists.
The concrete, templated class for properties.
Base class for properties.
Definition: Property.h:94
virtual bool isDefault() const =0
Overriden function that returns if property has the same value that it was initialised with,...
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
@ TOK_IGNORE_EMPTY
ignore empty tokens
@ TOK_TRIM
remove leading and trailing whitespace from tokens
std::size_t count() const
Get the total number of tokens.
Class for 3D vectors.
Definition: V3D.h:34
bool openLocal(const std::string &nxclass="")
Opens this NXClass using NXopengroup.
NXSize openNXSize(const std::string &name) const
Creates and opens a size_t dataset.
Definition: NexusClasses.h:566
NXInt openNXInt(const std::string &name) const
Creates and opens an integer dataset.
Definition: NexusClasses.h:546
NXDouble openNXDouble(const std::string &name) const
Creates and opens a double dataset.
Definition: NexusClasses.h:556
void close()
Close this class.
NXClass openNXGroup(const std::string &name) const
Creates and opens an arbitrary (non-standard) class (group).
Definition: NexusClasses.h:529
bool containsGroup(const std::string &query) const
Returns whether an individual group (or group) is present.
std::vector< NXClassInfo > & groups() const
Returns a list of all classes (or groups) in this NXClass.
Definition: NexusClasses.h:589
NXInfo getDataSetInfo(const std::string &name) const
Returns NXInfo for a dataset.
NXDataSetTyped< T > openNXDataSet(const std::string &name) const
Templated method for creating datasets.
Definition: NexusClasses.h:536
NXFloat openNXFloat(const std::string &name) const
Creates and opens a float dataset.
Definition: NexusClasses.h:551
bool isValid(const std::string &path) const
Check if a path exists relative to the current class path.
NXChar openNXChar(const std::string &name) const
Creates and opens a char dataset.
Definition: NexusClasses.h:561
std::string getString(const std::string &name) const
Returns a string.
Templated class implementation of NXDataSet.
Definition: NexusClasses.h:203
container_T< T > & vecBuffer()
Returns a the internal buffer.
Definition: NexusClasses.h:265
void load(const int blocksize=1, int i=-1, int j=-1, int k=-1, int l=-1) override
Implementation of the virtual NXDataSet::load(...) method.
Definition: NexusClasses.h:289
int size() const
Returns the size of the data buffer.
Definition: NexusClasses.h:267
int dim0() const
Returns the number of elements along the first dimension.
int rank() const
Returns the rank (number of dimensions) of the data. The maximum is 4.
Definition: NexusClasses.h:147
void openLocal()
Opens datasets faster but the parent group must be already open.
int dim1() const
Returns the number of elements along the second dimension.
Implements NXdata Nexus class.
Definition: NexusClasses.h:795
NXDouble openDoubleData()
Opens data of double type.
Definition: NexusClasses.h:824
Implements NXdetector Nexus class.
Definition: NexusClasses.h:837
Implements NXentry Nexus class.
Definition: NexusClasses.h:898
NXData openNXData(const std::string &name) const
Opens a NXData.
Definition: NexusClasses.h:912
NXInstrument openNXInstrument(const std::string &name) const
Opens a NXInstrument.
Definition: NexusClasses.h:917
Implements NXinstrument Nexus class.
Definition: NexusClasses.h:873
NXDetector openNXDetector(const std::string &name)
Opens a NXDetector.
Definition: NexusClasses.h:887
NXhandle m_fileID
Nexus file id.
Definition: NexusClasses.h:113
std::string path() const
Returns the absolute path to the object.
Definition: NexusClasses.h:107
NXAttributes attributes
Attributes.
Definition: NexusClasses.h:111
Implements NXroot Nexus class.
Definition: NexusClasses.h:922
NXEntry openEntry(const std::string &name)
Opens an entry – a topmost Nexus class.
Definition: NexusClasses.h:939
std::shared_ptr< IPeaksWorkspace > IPeaksWorkspace_sptr
shared pointer to Mantid::API::IPeaksWorkspace
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Definition: Workspace_fwd.h:20
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< ExperimentInfo > ExperimentInfo_sptr
Shared pointer to ExperimentInfo.
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
Definition: Algorithm.h:61
Mantid::Kernel::StringTokenizer tokenizer
Definition: Expression.cpp:17
EventType
What kind of event list is being stored.
Definition: IEventList.h:18
@ WEIGHTED_NOTIME
Definition: IEventList.h:18
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
bool UDlesserExecCount(const Mantid::NeXus::NXClassInfo &elem1, const Mantid::NeXus::NXClassInfo &elem2)
to sort the algorithmhistory vector
std::shared_ptr< RebinnedOutput > RebinnedOutput_sptr
shared pointer to the RebinnedOutput class
std::shared_ptr< PeakShapeFactory > PeakShapeFactory_sptr
Helper typedef.
std::shared_ptr< PeaksWorkspace > PeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
SpecialCoordinateSystem
Special coordinate systems for Q3D.
Helper class which provides the Collimation Length for SANS instruments.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition: EmptyValues.h:25
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
Definition: cow_ptr.h:172
int32_t specnum_t
Typedef for a spectrum Number.
Definition: IDTypes.h:16
Eigen::Array< IntT, static_cast< int >(ND), 1 > IntArray
Definition: Types.h:27
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54
Information about a Nexus class.
Definition: NexusClasses.h:53
std::string nxname
name of the object
Definition: NexusClasses.h:55
C++ implementation of NeXus classes.
Definition: NexusClasses.h:41
NXstatus stat
return status
Definition: NexusClasses.h:47
int rank
number of dimensions of the data
Definition: NexusClasses.h:44
int type
type of the data, e.g. NX_CHAR, NX_FLOAT32, see napi.h
Definition: NexusClasses.h:46
int dims[4]
sizes along each dimension
Definition: NexusClasses.h:45