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