Mantid
Loading...
Searching...
No Matches
LoadISISNexus2.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 +
7//----------------------------------------------------------------------
8// Includes
9//----------------------------------------------------------------------
15
16#include "MantidAPI/Axis.h"
29
30// clang-format off
31#include <nexus/NeXusFile.hpp>
32#include <nexus/NeXusException.hpp>
33// clang-format on
34
35#include <algorithm>
36#include <cctype>
37#include <climits>
38#include <cmath>
39#include <functional>
40#include <sstream>
41#include <vector>
42
43namespace {
46 auto dataBlocks = composite.getDataBlocks();
47 auto monitorBlocks = monitors.getDataBlocks();
48 auto matchesMonitorBlock = [&monitorBlocks](Mantid::DataHandling::DataBlock &dataBlock) {
49 return std::find(std::begin(monitorBlocks), std::end(monitorBlocks), dataBlock) != std::end(monitorBlocks);
50 };
51
53 for (auto &dataBlock : dataBlocks) {
54 if (matchesMonitorBlock(dataBlock)) {
55 newComposite.addDataBlock(dataBlock);
56 }
57 }
58
59 return newComposite;
60}
61} // namespace
62
63namespace Mantid::DataHandling {
64
66
67using namespace Kernel;
68using namespace API;
69using namespace NeXus;
70using namespace HistogramData;
71using std::size_t;
72
75 : m_filename(), m_instrument_name(), m_samplename(), m_detBlockInfo(), m_monBlockInfo(), m_loadBlockInfo(),
76 m_have_detector(false), m_hasVMSBlock(false), m_load_selected_spectra(false), m_wsInd2specNum_map(),
77 m_spec2det_map(), m_entrynumber(0), m_tof_data(), m_spec(), m_spec_end(nullptr), m_monitors(), m_logCreator(),
78 m_progress(), m_nexusFile() {}
79
87 if (descriptor.pathOfTypeExists("/raw_data_1", "NXentry")) {
88 // It also could be an Event Nexus file or a TOFRaw file,
89 // so confidence is set to less than 80.
90 return 75;
91 }
92 return 0;
93}
94
97 const std::vector<std::string> exts{".nxs", ".n*"};
98 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, exts),
99 "The name of the Nexus file to load");
100 declareProperty(std::make_unique<WorkspaceProperty<Workspace>>("OutputWorkspace", "", Direction::Output));
101
102 auto mustBePositiveSpectrum = std::make_shared<BoundedValidator<specnum_t>>();
103 mustBePositiveSpectrum->setLower(0);
104 declareProperty("SpectrumMin", static_cast<specnum_t>(0), mustBePositiveSpectrum);
105 declareProperty("SpectrumMax", static_cast<specnum_t>(EMPTY_INT()), mustBePositiveSpectrum);
106 declareProperty(std::make_unique<ArrayProperty<specnum_t>>("SpectrumList"));
107 auto mustBePositive = std::make_shared<BoundedValidator<int64_t>>();
108 declareProperty("EntryNumber", static_cast<int64_t>(0), mustBePositive,
109 "0 indicates that every entry is loaded, into a separate "
110 "workspace within a group. "
111 "A positive number identifies one entry to be loaded, into "
112 "one worskspace");
113
114 std::vector<std::string> monitorOptions{"Include", "Exclude", "Separate"};
115 std::map<std::string, std::string> monitorOptionsAliases;
116 monitorOptionsAliases["1"] = "Separate";
117 monitorOptionsAliases["0"] = "Exclude";
118 declareProperty("LoadMonitors", "Include",
119 std::make_shared<Kernel::StringListValidator>(monitorOptions, monitorOptionsAliases),
120 "Option to control the loading of monitors.\n"
121 "Allowed options are Include,Exclude, Separate.\n"
122 "Include:The default is Include option would load monitors with the "
123 "workspace if monitors spectra are within the range of loaded "
124 "detectors.\n"
125 "If the time binning for the monitors is different from the\n"
126 "binning of the detectors this option is equivalent to the Separate "
127 "option\n"
128 "Exclude:Exclude option excludes monitors from the output workspace.\n"
129 "Separate:Separate option loads monitors into a separate workspace "
130 "called: OutputWorkspace_monitors.\n"
131 "Defined aliases:\n"
132 "1: Equivalent to Separate.\n"
133 "0: Equivalent to Exclude.\n");
134}
135
144
145 //**********************************************************************
146 // process load monitor options request
147 bool bincludeMonitors, bseparateMonitors, bexcludeMonitors;
148 LoadRawHelper::ProcessLoadMonitorOptions(bincludeMonitors, bseparateMonitors, bexcludeMonitors, this);
149
150 //**********************************************************************
151 m_filename = getPropertyValue("Filename");
152 // Create the root Nexus class
153 NXRoot root(m_filename);
154
155 // "Open" the same file but with the C++ interface
156 m_nexusFile.reset(new ::NeXus::File(root.m_fileID));
157
158 // Open the raw data group 'raw_data_1'
159 NXEntry entry = root.openEntry("raw_data_1");
160
161 // Read in the instrument name from the Nexus file
162 m_instrument_name = entry.getString("name");
163
164 // Test if we have a vms block
165 if (entry.containsGroup("isis_vms_compat")) {
166 m_hasVMSBlock = true;
167 }
168
169 // Get number of detectors and spectrum list
170 size_t ndets{0};
171 try {
172 NXClass det_class = entry.openNXGroup("detector_1");
173 NXInt spectrum_index = det_class.openNXInt("spectrum_index");
174 spectrum_index.load();
175 ndets = spectrum_index.dim0();
176 // We assume that this spectrum list increases monotonically
177 m_spec = spectrum_index.vecBuffer();
178 m_spec_end = m_spec.data() + ndets;
179 m_have_detector = true;
180 } catch (std::runtime_error &) {
181 ndets = 0;
182 }
183
184 // Load detector and spectra ids, and number of monitors + detectors?
187
188 // Pull out the monitor blocks, if any exist
189 size_t nmons{0};
190
191 for (auto it = entry.groups().cbegin(); it != entry.groups().cend(); ++it) {
192 if (it->nxclass == "NXmonitor") // Count monitors
193 {
194 NXInt index = entry.openNXInt(std::string(it->nxname) + "/spectrum_index");
195 index.load();
196 specnum_t ind = static_cast<specnum_t>(*index());
197 // Spectrum index of 0 means no spectrum associated with that monitor,
198 // so only count those with index > 0
199 if (ind > 0) {
200 m_monitors[ind] = it->nxname;
201 ++nmons;
202 }
203 }
204 }
205
206 if (ndets == 0 && nmons == 0) {
207 if (bexcludeMonitors) {
208 g_log.warning() << "Nothing to do. No detectors found and no monitor "
209 "loading requested";
210 return;
211 } else {
212 g_log.error() << "Invalid NeXus structure, cannot find detector or monitor blocks.";
213 throw std::runtime_error("Inconsistent NeXus file structure.");
214 }
215 }
216
217 // Determine the the data block for the detectors and monitors
218 bseparateMonitors =
219 findSpectraDetRangeInFile(entry, m_spec, ndets, nsp1, m_monitors, bexcludeMonitors, bseparateMonitors);
220
221 size_t x_length = m_loadBlockInfo.getNumberOfChannels() + 1;
222
223 // Check input is consistent with the file, throwing if not
224 bseparateMonitors = checkOptionalProperties(bseparateMonitors, bexcludeMonitors);
225 // Fill up m_spectraBlocks
226 size_t total_specs = prepareSpectraBlocks(m_monitors, m_loadBlockInfo);
227
228 m_progress = std::make_shared<API::Progress>(this, 0.0, 1.0, total_specs * m_detBlockInfo.getNumberOfPeriods());
229
230 DataObjects::Workspace2D_sptr local_workspace = std::dynamic_pointer_cast<DataObjects::Workspace2D>(
231 WorkspaceFactory::Instance().create("Workspace2D", total_specs, x_length, m_loadBlockInfo.getNumberOfChannels()));
232 // Set the units on the workspace to TOF & Counts
233 local_workspace->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
234 local_workspace->setYUnit("Counts");
235
236 // Load instrument and other data once then copy it later
237 m_progress->report("Loading instrument and run details");
238
239 // load run details
240 loadRunDetails(local_workspace, entry);
241
242 // Test if IDF exists in Nexus otherwise load default instrument
243 bool foundInstrument = LoadEventNexus::runLoadIDFFromNexus(m_filename, local_workspace, "raw_data_1", this);
245 m_spec2det_map = SpectrumDetectorMapping(spec(), udet(), udet.dim0());
246 else if (bseparateMonitors) {
247 m_spec2det_map = SpectrumDetectorMapping(spec(), udet(), udet.dim0());
248 local_workspace->updateSpectraUsing(m_spec2det_map);
249 } else {
250 local_workspace->updateSpectraUsing(SpectrumDetectorMapping(spec(), udet(), udet.dim0()));
251 }
252
253 if (!foundInstrument) {
254 runLoadInstrument(local_workspace);
255 }
256
257 // Load logs and sample information
258 m_nexusFile->openPath(entry.path());
259 local_workspace->loadSampleAndLogInfoNexus(m_nexusFile.get());
260
261 // Load logs and sample information further information... See maintenance
262 // ticket #8697
263 loadSampleData(local_workspace, entry);
264 m_progress->report("Loading logs");
265 loadLogs(local_workspace);
266
267 // Load first period outside loop
268 m_progress->report("Loading data");
269 // Get X Data
270 if (ndets > 0) {
272 }
273
274 int64_t firstentry = (m_entrynumber > 0) ? m_entrynumber : 1;
275 loadPeriodData(firstentry, entry, local_workspace, m_load_selected_spectra);
276
277 // Clone the workspace at this point to provide a base object for future
278 // workspace generation.
279 DataObjects::Workspace2D_sptr period_free_workspace =
280 std::dynamic_pointer_cast<DataObjects::Workspace2D>(WorkspaceFactory::Instance().create(local_workspace));
281
282 createPeriodLogs(firstentry, local_workspace);
283
284 WorkspaceGroup_sptr wksp_group(new WorkspaceGroup);
286 wksp_group->setTitle(local_workspace->getTitle());
287
288 // This forms the name of the group
289 const std::string base_name = getPropertyValue("OutputWorkspace") + "_";
290 const std::string prop_name = "OutputWorkspace_";
291
292 for (int p = 1; p <= m_loadBlockInfo.getNumberOfPeriods(); ++p) {
293 std::ostringstream os;
294 os << p;
295 m_progress->report("Loading period " + os.str());
296 if (p > 1) {
297 local_workspace = std::dynamic_pointer_cast<DataObjects::Workspace2D>(
298 WorkspaceFactory::Instance().create(period_free_workspace));
299 loadPeriodData(p, entry, local_workspace, m_load_selected_spectra);
300 createPeriodLogs(p, local_workspace);
301 // Check consistency of logs data for multi-period workspaces and raise
302 // warnings where necessary.
303 validateMultiPeriodLogs(local_workspace);
304 }
305 declareProperty(std::make_unique<WorkspaceProperty<Workspace>>(prop_name + os.str(), base_name + os.str(),
307 wksp_group->addWorkspace(local_workspace);
308 setProperty(prop_name + os.str(), std::static_pointer_cast<Workspace>(local_workspace));
309 }
310 // The group is the root property value
311 setProperty("OutputWorkspace", std::dynamic_pointer_cast<Workspace>(wksp_group));
312 } else {
313 setProperty("OutputWorkspace", std::dynamic_pointer_cast<Workspace>(local_workspace));
314 }
315
316 //***************************************************************************************************
317 // Workspace or group of workspaces without monitors is loaded. Now we are
318 // loading monitors separately.
319 if (bseparateMonitors) {
320 std::string wsName = getPropertyValue("OutputWorkspace");
322 x_length = m_monBlockInfo.getNumberOfChannels() + 1;
323 // reset the size of the period free workspace to the monitor size
324 period_free_workspace = std::dynamic_pointer_cast<DataObjects::Workspace2D>(WorkspaceFactory::Instance().create(
325 period_free_workspace, m_monBlockInfo.getNumberOfSpectra(), x_length, m_monBlockInfo.getNumberOfChannels()));
326 auto monitor_workspace = std::dynamic_pointer_cast<DataObjects::Workspace2D>(
327 WorkspaceFactory::Instance().create(period_free_workspace));
328
329 m_spectraBlocks.clear();
330 m_wsInd2specNum_map.clear();
331 // at the moment here we clear this map to enable possibility to load
332 // monitors from the spectra block (wiring table bug).
333 // if monitor's spectra present in the detectors block due to this bug
334 // should be read from monitors, this map should be dealt with properly.
335 buildSpectraInd2SpectraNumMap(true /*hasRange*/, false /*hasSpectraList*/, m_monBlockInfo);
336
337 // lo
339
340 firstentry = (m_entrynumber > 0) ? m_entrynumber : 1;
341 loadPeriodData(firstentry, entry, monitor_workspace, true);
342 local_workspace->setMonitorWorkspace(monitor_workspace);
343
344 ISISRunLogs monLogCreator(monitor_workspace->run());
345 monLogCreator.addPeriodLogs(1, monitor_workspace->mutableRun());
346
347 const std::string monitorPropBase = "MonitorWorkspace";
348 const std::string monitorWsNameBase = wsName + "_monitors";
350 WorkspaceGroup_sptr monitor_group(new WorkspaceGroup);
351 monitor_group->setTitle(monitor_workspace->getTitle());
352
353 for (int p = 1; p <= m_detBlockInfo.getNumberOfPeriods(); ++p) {
354 std::ostringstream os;
355 os << "_" << p;
356 m_progress->report("Loading period " + os.str());
357 if (p > 1) {
358 monitor_workspace = std::dynamic_pointer_cast<DataObjects::Workspace2D>(
359 WorkspaceFactory::Instance().create(period_free_workspace));
360 loadPeriodData(p, entry, monitor_workspace, m_load_selected_spectra);
361 monLogCreator.addPeriodLogs(p, monitor_workspace->mutableRun());
362 // Check consistency of logs data for multi-period workspaces and
363 // raise
364 // warnings where necessary.
365 validateMultiPeriodLogs(monitor_workspace);
366 auto data_ws = std::static_pointer_cast<API::MatrixWorkspace>(wksp_group->getItem(p - 1));
367 data_ws->setMonitorWorkspace(monitor_workspace);
368 }
370 monitorPropBase + os.str(), monitorWsNameBase + os.str(), Direction::Output));
371 monitor_group->addWorkspace(monitor_workspace);
372 setProperty(monitorPropBase + os.str(), std::static_pointer_cast<Workspace>(monitor_workspace));
373 }
374 // The group is the root property value
376 std::make_unique<WorkspaceProperty<Workspace>>(monitorPropBase, monitorWsNameBase, Direction::Output));
377 setProperty(monitorPropBase, std::dynamic_pointer_cast<Workspace>(monitor_group));
378
379 } else {
381 std::make_unique<WorkspaceProperty<Workspace>>(monitorPropBase, monitorWsNameBase, Direction::Output));
382 setProperty(monitorPropBase, std::static_pointer_cast<Workspace>(monitor_workspace));
383 }
384 } else {
385 g_log.information() << " no monitors to load for workspace: " << wsName << '\n';
386 }
387 }
388
389 // Clear off the member variable containers
390 m_tof_data.reset();
391 m_spec.clear();
392 m_monitors.clear();
393 m_wsInd2specNum_map.clear();
394}
400 const Run &run = ws->run();
401 if (!run.hasProperty("current_period")) {
402 g_log.warning("Workspace has no current_period log.");
403 }
404 if (!run.hasProperty("nperiods")) {
405 g_log.warning("Workspace has no nperiods log");
406 }
407 if (!run.hasProperty("proton_charge_by_period")) {
408 g_log.warning("Workspace has not proton_charge_by_period log");
409 }
410}
411
419bool LoadISISNexus2::checkOptionalProperties(bool bseparateMonitors, bool bexcludeMonitor) {
420 // optional properties specify that only some spectra have to be loaded
421 bool range_supplied(false);
422
423 // Get the spectrum selection which were specfied by the user
424 specnum_t spec_min = getProperty("SpectrumMin");
425 specnum_t spec_max = getProperty("SpectrumMax");
426
427 // If spearate monitors or excluded monitors is selected then we
428 // need to build up a wsIndex to spectrum number map as well,
429 // since we cannot rely on contiguous blocks of detectors
430 if (bexcludeMonitor || bseparateMonitors) {
432 }
433
434 if (spec_min == 0)
436 else {
437 range_supplied = true;
439 }
440
441 if (spec_max == EMPTY_INT())
443 else {
444 range_supplied = true;
446 }
447
448 // Sanity check for min/max
449 if (spec_min > spec_max) {
450 throw std::invalid_argument("Inconsistent range properties. SpectrumMin is "
451 "larger than SpectrumMax.");
452 }
453
454 if (spec_max > m_loadBlockInfo.getMaxSpectrumID()) {
455 std::string err = "Inconsistent range property. SpectrumMax is larger than number of "
456 "spectra: " +
458 throw std::invalid_argument(err);
459 }
460
461 // Check the entry number
462 m_entrynumber = getProperty("EntryNumber");
463 if (static_cast<int>(m_entrynumber) > m_loadBlockInfo.getNumberOfPeriods() || m_entrynumber < 0) {
464 std::string err = "Invalid entry number entered. File contains " +
466 throw std::invalid_argument(err);
467 }
468
470 m_entrynumber = 1;
471 }
472
473 // Did the user provide a spectrum list
474 std::vector<specnum_t> spec_list = getProperty("SpectrumList");
475 auto hasSpecList = false;
476
477 if (!spec_list.empty()) {
479
480 // Sort the list so that we can check it's range
481 std::sort(spec_list.begin(), spec_list.end());
482
483 // Check if the spectra list entries are outside of the bounds
484 // If we load the monitors separately, then we need to make sure that we
485 // take them into account
486 bool isSpectraListTooLarge;
487 bool isSpectraListTooSmall;
488 auto maxLoadBlock = m_loadBlockInfo.getMaxSpectrumID();
489 auto minLoadBlock = m_loadBlockInfo.getMinSpectrumID();
490 if (bseparateMonitors) {
491 auto maxMonBlock = m_monBlockInfo.getMaxSpectrumID();
492 auto minMonBlock = m_monBlockInfo.getMinSpectrumID();
493 isSpectraListTooLarge = spec_list.back() > std::max(maxMonBlock, maxLoadBlock);
494 isSpectraListTooSmall = spec_list.front() < std::min(minMonBlock, minLoadBlock);
495
496 } else {
497 isSpectraListTooLarge = spec_list.back() > maxLoadBlock;
498 isSpectraListTooSmall = spec_list.front() < minLoadBlock;
499 }
500
501 if (isSpectraListTooLarge) {
502 std::string err = "The specified spectrum list contains a spectrum number which is "
503 "larger "
504 "than the largest loadable spectrum number for your selection of "
505 "excluded/included/separate monitors. The largest loadable "
506 "spectrum number is " +
508 throw std::invalid_argument(err);
509 }
510 if (isSpectraListTooSmall) {
511 std::string err = "The specified spectrum list contains a spectrum number which is "
512 "smaller "
513 "than the smallest loadable spectrum number for your selection of "
514 "excluded/included/separate monitors. The smallest loadable "
515 "spectrum number is " +
517 throw std::invalid_argument(err);
518 }
519
520 // The users can provide a spectrum list and and a spectrum range. Handle
521 // this here.
522 if (range_supplied) {
523 // First remove all entries which are inside of the min and max spectrum,
524 // to avoid duplicates
525 auto isInRange = [&spec_min, &spec_max](specnum_t x) { return (spec_min <= x) && (x <= spec_max); };
526
527 spec_list.erase(remove_if(spec_list.begin(), spec_list.end(), isInRange), spec_list.end());
528
529 // The spec_min - spec_max range needs to be added to the spec list
530 for (auto i = spec_min; i < spec_max + 1; ++i) {
531 spec_list.emplace_back(i);
532 }
533 std::sort(spec_list.begin(), spec_list.end());
534 }
535
536 auto monitorSpectra = m_monBlockInfo.getAllSpectrumNumbers();
537 // Create DataBlocks from the spectrum list
538 DataBlockComposite composite;
539 populateDataBlockCompositeWithContainer(composite, spec_list, spec_list.size(),
541 monitorSpectra);
542
543 // If the monitors are to be loaded separately, then we have
544 // to remove them at this point, but we also have to check if the
545 if (bexcludeMonitor || bseparateMonitors) {
546 auto newMonitors = getMonitorsFromComposite(composite, m_monBlockInfo);
547 composite.removeSpectra(m_monBlockInfo);
548
549 // This is important. If there are no monitors which were specifically
550 // selected,
551 // then we load the full monitor range, else respect the selection.
552 if (!newMonitors.isEmpty()) {
553 m_monBlockInfo = newMonitors;
554 }
555
556 // Handle case where the composite is empty since it only contained
557 // monitors, but we want to load the monitors sepearately. In this case we
558 // should set the loadBlock to the selected monitors.
559 if (bseparateMonitors && composite.isEmpty()) {
560 composite = m_monBlockInfo;
561 bseparateMonitors = false;
562 }
563 }
564
565 m_loadBlockInfo = composite;
566
567 hasSpecList = true;
568 } else {
569 // At this point we don't have a spectrum list but there might have been a
570 // spectrum range which we need to take into account, by truncating
571 // the current range. If we load the monitors separately, we need to
572 // truncate them as well (provided they are affected)
573 if (range_supplied) {
574 m_loadBlockInfo.truncate(spec_min, spec_max);
575
576 auto new_monitors = m_monBlockInfo;
577 new_monitors.truncate(spec_min, spec_max);
578 m_monBlockInfo = new_monitors;
579 }
580 }
581
583 buildSpectraInd2SpectraNumMap(range_supplied, hasSpecList, m_loadBlockInfo);
584 }
585
586 // Check that the load blocks contain anything at all.
587 if (m_loadBlockInfo.isEmpty()) {
588 throw std::invalid_argument("Your spectrum number selection was not valid. "
589 "Make sure that you select spectrum numbers "
590 "and ranges which are compatible with your "
591 "selection of excluded/included/separate monitors. ");
592 }
593
594 return bseparateMonitors;
595}
596
607void LoadISISNexus2::buildSpectraInd2SpectraNumMap(bool range_supplied, bool hasSpectraList,
608 DataBlockComposite &dataBlockComposite) {
609
610 if (range_supplied || hasSpectraList || true) {
611 auto generator = dataBlockComposite.getGenerator();
612 int64_t hist = 0;
613 for (; !generator->isDone(); generator->next()) {
614 auto spec_num = static_cast<specnum_t>(generator->getValue());
615 m_wsInd2specNum_map.emplace(hist, spec_num);
616 ++hist;
617 }
618 }
619}
620
627size_t LoadISISNexus2::prepareSpectraBlocks(std::map<specnum_t, std::string> &monitors, DataBlockComposite &LoadBlock) {
628 std::vector<specnum_t> includedMonitors;
629 // Setup the SpectraBlocks based on the DataBlocks
630 auto dataBlocks = LoadBlock.getDataBlocks();
631 auto isMonitor = [&monitors](specnum_t spectrumNumber) { return monitors.find(spectrumNumber) != monitors.end(); };
632 for (const auto &dataBlock : dataBlocks) {
633 auto min = dataBlock.getMinSpectrumID();
634 if (isMonitor(min)) {
635 m_spectraBlocks.emplace_back(SpectraBlock(min, min, true, monitors.find(min)->second));
636 includedMonitors.emplace_back(min);
637 } else {
638 auto max = dataBlock.getMaxSpectrumID();
639 m_spectraBlocks.emplace_back(min, max, false, "");
640 }
641 }
642
643 // sort and check for overlapping
644 if (m_spectraBlocks.size() > 1) {
645 std::sort(m_spectraBlocks.begin(), m_spectraBlocks.end(),
646 [](const LoadISISNexus2::SpectraBlock &block1, const LoadISISNexus2::SpectraBlock &block2) {
647 return block1.last < block2.first;
648 });
650 }
651
652 // Remove monitors that have been used.
653 auto allMonitorsIncluded = monitors.size() == includedMonitors.size();
654 if (!includedMonitors.empty() && !allMonitorsIncluded) {
655 for (auto it = monitors.begin(); it != monitors.end();) {
656 if (std::find(includedMonitors.begin(), includedMonitors.end(), it->first) != includedMonitors.end()) {
657 auto it1 = it;
658 ++it;
659 monitors.erase(it1);
660 } else {
661 ++it;
662 }
663 }
664 }
665
666 // Count the number of spectra.
667 const auto nSpec = std::accumulate(
668 m_spectraBlocks.cbegin(), m_spectraBlocks.cend(), static_cast<size_t>(0),
669 [](size_t sum, const auto &spectraBlock) { return sum + spectraBlock.last - spectraBlock.first + 1; });
670 return nSpec;
671}
672
681 for (size_t i = 1; i < m_spectraBlocks.size(); ++i) {
682 const auto &block1 = m_spectraBlocks[i - 1];
683 const auto &block2 = m_spectraBlocks[i];
684 if (block1.first > block1.last && block2.first > block2.last)
685 throw std::runtime_error("LoadISISNexus2: inconsistent spectra ranges");
686 if (block1.last >= block2.first) {
687 throw std::runtime_error("LoadISISNexus2: the range of SpectraBlocks must not overlap");
688 }
689 }
690}
691
701void LoadISISNexus2::loadPeriodData(int64_t period, NXEntry &entry, DataObjects::Workspace2D_sptr &local_workspace,
702 bool update_spectra2det_mapping) {
703 int64_t hist_index = 0;
704 int64_t period_index(period - 1);
705
706 for (const auto &spectraBlock : m_spectraBlocks) {
707 if (spectraBlock.isMonitor) {
708 NXData monitor = entry.openNXData(spectraBlock.monName);
709 NXInt mondata = monitor.openIntData();
710 m_progress->report("Loading monitor");
711 mondata.load(1, static_cast<int>(period - 1)); // TODO this is just wrong
712 NXFloat timeBins = monitor.openNXFloat("time_of_flight");
713 timeBins.load();
714 local_workspace->setHistogram(hist_index, BinEdges(timeBins(), timeBins() + timeBins.dim0()),
715 Counts(mondata(), mondata() + m_monBlockInfo.getNumberOfChannels()));
716
717 if (update_spectra2det_mapping) {
718 auto &spec = local_workspace->getSpectrum(hist_index);
719 specnum_t specNum = m_wsInd2specNum_map.at(hist_index);
720 spec.setDetectorIDs(m_spec2det_map.getDetectorIDsForSpectrumNo(specNum));
721 spec.setSpectrumNo(specNum);
722 }
723 hist_index++;
724 } else if (m_have_detector) {
725 NXData nxdata = entry.openNXData("detector_1");
726 NXDataSetTyped<int> data = nxdata.openIntData();
727 data.open();
728 // Start with the list members that are lower than the required spectrum
729 const int *const spec_begin = m_spec.data();
730 // When reading in blocks we need to be careful that the range is exactly
731 // divisible by the block-size
732 // and if not have an extra read of the left overs
733 const int64_t blocksize = 8;
734 const int64_t rangesize = spectraBlock.last - spectraBlock.first + 1;
735 const int64_t fullblocks = rangesize / blocksize;
736 int64_t spectra_no = spectraBlock.first;
737
738 // For this to work correctly, we assume that the spectrum list increases
739 // monotonically
740 int64_t filestart = std::lower_bound(spec_begin, m_spec_end, spectra_no) - spec_begin;
741 if (fullblocks > 0) {
742 for (int64_t i = 0; i < fullblocks; ++i) {
743 loadBlock(data, blocksize, period_index, filestart, hist_index, spectra_no, local_workspace);
744 filestart += blocksize;
745 }
746 }
747 int64_t finalblock = rangesize - (fullblocks * blocksize);
748 if (finalblock > 0) {
749 loadBlock(data, finalblock, period_index, filestart, hist_index, spectra_no, local_workspace);
750 }
751 }
752 }
753
754 try {
755 const std::string title = entry.getString("title");
756 local_workspace->setTitle(title);
757 // write the title into the log file (run object)
758 local_workspace->mutableRun().addProperty("run_title", title, true);
759 } catch (std::runtime_error &) {
760 g_log.debug() << "No title was found in the input file, " << getPropertyValue("Filename") << '\n';
761 }
762}
763
770 m_logCreator->addPeriodLogs(static_cast<int>(period), local_workspace->mutableRun());
771}
772
784void LoadISISNexus2::loadBlock(NXDataSetTyped<int> &data, int64_t blocksize, int64_t period, int64_t start,
785 int64_t &hist, int64_t &spec_num, DataObjects::Workspace2D_sptr &local_workspace) {
786 data.load(static_cast<int>(blocksize), static_cast<int>(period),
787 static_cast<int>(start)); // TODO this is just wrong
788 int *data_start = data();
789 int *data_end = data_start + m_loadBlockInfo.getNumberOfChannels();
790 int64_t final(hist + blocksize);
791 while (hist < final) {
792 m_progress->report("Loading data");
793 local_workspace->setHistogram(hist, BinEdges(m_tof_data), Counts(data_start, data_end));
794 data_start += m_detBlockInfo.getNumberOfChannels();
797 auto &spec = local_workspace->getSpectrum(hist);
798 specnum_t specNum = m_wsInd2specNum_map.at(hist);
799 // set detectors corresponding to spectra Number
800 spec.setDetectorIDs(m_spec2det_map.getDetectorIDsForSpectrumNo(specNum));
801 // set correct spectra Number
802 spec.setSpectrumNo(specNum);
803 }
804
805 ++hist;
806 ++spec_num;
807 }
808}
809
812
813 auto loadInst = createChildAlgorithm("LoadInstrument");
814
815 // Now execute the Child Algorithm. Catch and log any error, but don't stop.
816 bool executionSuccessful(true);
817 try {
818 loadInst->setPropertyValue("InstrumentName", m_instrument_name);
819 loadInst->setProperty<MatrixWorkspace_sptr>("Workspace", localWorkspace);
820 loadInst->setProperty("RewriteSpectraMap", Mantid::Kernel::OptionalBool(false));
821 loadInst->execute();
822 } catch (std::invalid_argument &) {
823 g_log.information("Invalid argument to LoadInstrument Child Algorithm");
824 executionSuccessful = false;
825 } catch (std::runtime_error &) {
826 g_log.information("Unable to successfully run LoadInstrument Child Algorithm");
827 executionSuccessful = false;
828 }
829 if (executionSuccessful) {
830 // If requested update the instrument to positions in the data file
831 const auto &pmap = localWorkspace->constInstrumentParameters();
832 if (pmap.contains(localWorkspace->getInstrument()->getComponentID(), "det-pos-source")) {
833 std::shared_ptr<Geometry::Parameter> updateDets =
834 pmap.get(localWorkspace->getInstrument()->getComponentID(), "det-pos-source");
835 std::string value = updateDets->value<std::string>();
836 if (value.substr(0, 8) == "datafile") {
837 auto updateInst = createChildAlgorithm("UpdateInstrumentFromFile");
838 updateInst->setProperty<MatrixWorkspace_sptr>("Workspace", localWorkspace);
839 updateInst->setPropertyValue("Filename", m_filename);
840 if (value == "datafile-ignore-phi") {
841 updateInst->setProperty("IgnorePhi", true);
842 g_log.information("Detector positions in IDF updated with positions "
843 "in the data file except for the phi values");
844 } else {
845 g_log.information("Detector positions in IDF updated with positions "
846 "in the data file");
847 }
848 // We want this to throw if it fails to warn the user that the
849 // information is not correct.
850 updateInst->execute();
851 }
852 }
853 }
854}
855
862
863 API::Run &runDetails = local_workspace->mutableRun();
864
865 // Data details on run not the workspace
866 runDetails.addProperty("nspectra", static_cast<int>(m_loadBlockInfo.getNumberOfSpectra()));
867 runDetails.addProperty("nchannels", static_cast<int>(m_loadBlockInfo.getNumberOfChannels()));
868 runDetails.addProperty("nperiods", static_cast<int>(m_loadBlockInfo.getNumberOfPeriods()));
869
871}
872
879
880 // load sample geometry - Id and dimensions
881 LoadISISNexusHelper::loadSampleGeometry(local_workspace->mutableSample(), entry, m_hasVMSBlock);
882 g_log.debug() << "Sample geometry - ID: " << local_workspace->mutableSample().getGeometryFlag()
883 << ", thickness: " << local_workspace->mutableSample().getThickness()
884 << ", height: " << local_workspace->mutableSample().getHeight()
885 << ", width: " << local_workspace->mutableSample().getWidth() << "\n";
886}
887
894 auto alg = createChildAlgorithm("LoadNexusLogs", 0.0, 0.5);
895 alg->setPropertyValue("Filename", this->getProperty("Filename"));
896 alg->setProperty<MatrixWorkspace_sptr>("Workspace", ws);
897 try {
898 alg->executeAsChildAlg();
899 } catch (std::runtime_error &) {
900 g_log.warning() << "Unable to load run logs. There will be no log "
901 << "data associated with this workspace\n";
902 return;
903 }
904
905 // Populate the instrument parameters.
906 ws->populateInstrumentParameters();
907
908 // Make log creator object and add the run status log
909 m_logCreator.reset(new ISISRunLogs(ws->run()));
910 m_logCreator->addStatusLog(ws->mutableRun());
911}
912
913double LoadISISNexus2::dblSqrt(double in) { return sqrt(in); }
939bool LoadISISNexus2::findSpectraDetRangeInFile(NXEntry &entry, std::vector<specnum_t> &spectrum_index, int64_t ndets,
940 int64_t n_vms_compat_spectra, std::map<specnum_t, std::string> &monitors,
941 bool excludeMonitors, bool separateMonitors) {
942 size_t nmons = monitors.size();
943
944 if (nmons > 0) {
945 NXInt chans = entry.openNXInt(m_monitors.begin()->second + "/data");
946
947 // Iterate over each monitor and create a data block for each monitor
948 for (const auto &monitor : monitors) {
949 auto monID = monitor.first;
950 auto monTemp = DataBlock(chans);
951 monTemp.setMinSpectrumID(monID);
952 monTemp.setMaxSpectrumID(monID);
954 }
955
956 // at this stage we assume that the only going to load monitors
958 }
959
960 // Check if the there are only monitors in the workspace, in which
961 // case the monitors are loaded as the main workspace, ie not as
962 // a separate workspace.
963 if (ndets == 0) {
964 separateMonitors = false;
965 return separateMonitors;
966 }
967
968 // There are detectors present. The spectrum_index array contains
969 // all available spectra of detectors, but these indices might
970 // not be contiguous.
971 NXData nxData = entry.openNXData("detector_1");
972 NXInt data = nxData.openIntData();
973
974 auto monitorSpectra = m_monBlockInfo.getAllSpectrumNumbers();
975 populateDataBlockCompositeWithContainer(m_detBlockInfo, spectrum_index, ndets, data.dim0() /*Number of Periods*/,
976 data.dim2() /*Number of channels*/, monitorSpectra);
977
978 // We should handle legacy files which include the spectrum number of the
979 // monitors
980 // in the detector group ("raw_data_1/detector_1/spectrum_index")
981 // Simple try to remove the monitors. If they are not included nothing should
982 // happen
984
986
987 // Check what is actually going or can be loaded
988 bool removeMonitors = excludeMonitors || separateMonitors;
989
990 // If the monitors are to be pulled into the same workspace as the detector
991 // information,
992 // then the number of periods and the number of channels has to conincide
995 if (!removeMonitors) {
996 g_log.warning() << " Performing separate loading as can not load spectra "
997 "and monitors in the single workspace:\n";
998 g_log.warning() << " Monitors data contain :" << m_monBlockInfo.getNumberOfChannels()
999 << " time channels and: " << m_monBlockInfo.getNumberOfPeriods() << " period(s)\n";
1000 g_log.warning() << " Spectra data contain :" << m_detBlockInfo.getNumberOfChannels()
1001 << " time channels and: " << m_detBlockInfo.getNumberOfPeriods() << " period(s)\n";
1002 }
1003
1004 // Force the monitors to be removed and separate if the periods and channels
1005 // don't conincide
1006 // between monitors and detectors.
1007 separateMonitors = true;
1008 removeMonitors = true;
1009 }
1010
1011 int64_t spectraID_min = std::min(m_monBlockInfo.getMinSpectrumID(), m_detBlockInfo.getMinSpectrumID());
1012 int64_t spectraID_max = std::max(m_monBlockInfo.getMaxSpectrumID(), m_detBlockInfo.getMaxSpectrumID());
1014
1015 // In case we want to load everything into a one workspace, we should combine
1016 // the
1017 // the data blocks of the monitor and the detector
1018 if (!removeMonitors) {
1020 }
1021
1022 // If the monitors are to be loaded separately, then we set the loadblocks to
1023 // the detblocks,
1024 // since we want to deal with the detectors (the main workspace) first.
1025 if (separateMonitors)
1027
1028 // Perform a sanity check of the spectrum numbers
1029 if ((totNumOfSpectra != static_cast<size_t>(n_vms_compat_spectra)) ||
1030 (spectraID_max - spectraID_min + 1 != static_cast<int64_t>(n_vms_compat_spectra))) {
1031 // At this point we normally throw since there is a mismatch between the
1032 // number
1033 // spectra of the detectors+monitors and the entry in NSP1, but in the
1034 // case of multiple time regimes this comparison is not any longer valid.
1035 // Hence we only throw if the file does not correspond to a multiple time
1036 // regime file.
1037 if (!isMultipleTimeRegimeFile(entry)) {
1038 throw std::runtime_error("LoadISISNexus: There seems to be an "
1039 "inconsistency in the spectrum numbers.");
1040 }
1041 }
1042
1043 return separateMonitors;
1044}
1045
1054 auto hasMultipleTimeRegimes(false);
1055 try {
1056 NXClass instrument = entry.openNXGroup("instrument");
1057 NXClass dae = instrument.openNXGroup("dae");
1058 hasMultipleTimeRegimes = dae.containsGroup("time_channels_3");
1059 } catch (...) {
1060 }
1061 return hasMultipleTimeRegimes;
1062}
1063
1064} // namespace Mantid::DataHandling
double value
The value of the point.
Definition: FitMW.cpp:51
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#define DECLARE_NEXUS_FILELOADER_ALGORITHM(classname)
DECLARE_NEXUS_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro wh...
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
Definition: Algorithm.cpp:842
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
bool hasProperty(const std::string &name) const
Does the property exist on the object.
Definition: LogManager.cpp:265
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
Definition: LogManager.h:79
This class stores information regarding an experimental run as a series of log entries.
Definition: Run.h:38
A minimal class to hold the mapping between the spectrum number and its related detector ID numbers f...
const std::set< detid_t > & getDetectorIDsForSpectrumNo(const specnum_t spectrumNo) const
Class to hold a set of workspaces.
A property class for workspaces.
DataBlockComposite: The DataBlockComposite handles a collection of DataBlocks.
void truncate(specnum_t specMin, specnum_t specMax)
std::vector< specnum_t > getAllSpectrumNumbers()
Provides a container with all spectrum numbers.
std::unique_ptr< DataBlockGenerator > getGenerator() const override
void addDataBlock(const DataBlock &dataBlock)
void removeSpectra(DataBlockComposite &toRemove)
Removes the input data blocks from the current list of data blocks.
DataBlock: The DataBlock class holds information about a contiguous block of spectrum numbers.
Definition: DataBlock.h:26
Defines a class to aid in creating ISIS specific run logs for periods, status etc.
Definition: ISISRunLogs.h:28
void addPeriodLogs(const int period, API::Run &exptRun)
Adds period related logs.
Definition: ISISRunLogs.cpp:54
static bool runLoadIDFFromNexus(const std::string &nexusfilename, T localWorkspace, const std::string &top_entry_name, Algorithm *alg)
Load instrument for Nexus file.
int64_t m_entrynumber
The number of the input entry.
std::string m_filename
The name and path of the input file.
bool findSpectraDetRangeInFile(NeXus::NXEntry &entry, std::vector< specnum_t > &spectrum_index, int64_t ndets, int64_t n_vms_compat_spectra, std::map< specnum_t, std::string > &monitors, bool excludeMonitors, bool separateMonitors)
Method takes input parameters which describe monitor loading and analyze them against spectra/monitor...
boost::scoped_ptr< ISISRunLogs > m_logCreator
A pointer to the ISISRunLogs creator.
void loadSampleData(DataObjects::Workspace2D_sptr &, const Mantid::NeXus::NXEntry &entry)
Load in details about the sample.
void loadRunDetails(DataObjects::Workspace2D_sptr &local_workspace, Mantid::NeXus::NXEntry &entry)
Load in details about the run.
const specnum_t * m_spec_end
Pointer to one-past-the-end of spectrum number array (m_spec)
void createPeriodLogs(int64_t period, DataObjects::Workspace2D_sptr &local_workspace)
Creates period log data in the workspace.
std::map< int64_t, specnum_t > m_wsInd2specNum_map
map of workspace Index to spectra Number (spectraID)
void loadBlock(Mantid::NeXus::NXDataSetTyped< int > &data, int64_t blocksize, int64_t period, int64_t start, int64_t &hist, int64_t &spec_num, DataObjects::Workspace2D_sptr &local_workspace)
Perform a call to nxgetslab, via the NexusClasses wrapped methods for a given block-size.
void loadLogs(DataObjects::Workspace2D_sptr &ws)
Load log data from the nexus file.
void exec() override
Overwrites Algorithm method.
void loadPeriodData(int64_t period, Mantid::NeXus::NXEntry &entry, DataObjects::Workspace2D_sptr &local_workspace, bool update_spectra2det_mapping=false)
Load a given period into the workspace.
void checkOverlappingSpectraRange()
Check if any of the spectra block ranges overlap.
std::map< specnum_t, std::string > m_monitors
Monitors, map spectrum index to monitor group name.
bool isMultipleTimeRegimeFile(const NeXus::NXEntry &entry) const
Check if is the file is a multiple time regime file.
bool m_have_detector
Is there a detector block.
std::shared_ptr< API::Progress > m_progress
Progress reporting object.
int confidence(Kernel::NexusDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
void validateMultiPeriodLogs(const Mantid::API::MatrixWorkspace_sptr &)
Check for a set of synthetic logs associated with multi-period log data.
std::string m_instrument_name
The instrument name from Nexus.
std::shared_ptr< HistogramData::HistogramX > m_tof_data
Time channels.
std::vector< specnum_t > m_spec
Spectra numbers.
void runLoadInstrument(DataObjects::Workspace2D_sptr &)
Run LoadInstrument as a ChildAlgorithm.
boost::scoped_ptr< ::NeXus::File > m_nexusFile
API::SpectrumDetectorMapping m_spec2det_map
spectra Number to detector ID (multi)map
static double dblSqrt(double in)
Personal wrapper for sqrt to allow msvs to compile.
size_t prepareSpectraBlocks(std::map< specnum_t, std::string > &monitors, DataBlockComposite &LoadBlock)
Prepare a vector of SpectraBlock structures to simplify loading.
bool checkOptionalProperties(bool bseparateMonitors, bool bexcludeMonitor)
Check the validity of the optional properties of the algorithm and identify if partial data should be...
void buildSpectraInd2SpectraNumMap(bool range_supplied, bool hasSpectraList, DataBlockComposite &dataBlockComposite)
Build the list of spectra to load and include into spectra-detectors map.
std::vector< SpectraBlock > m_spectraBlocks
List of disjoint data blocks to load.
bool m_load_selected_spectra
if true, a spectra list or range of spectra is supplied
void init() override
Overwrites Algorithm method.
static void ProcessLoadMonitorOptions(bool &bincludeMonitors, bool &bseparateMonitors, bool &bexcludeMonitors, API::Algorithm *const pAlgo)
The method to interpret LoadMonitors property options and convert then into boolean values.
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
Defines a wrapper around a file whose internal structure can be accessed using the NeXus API.
bool pathOfTypeExists(const std::string &path, const std::string &type) const
Query if a path exists of a given type.
OptionalBool : Tri-state bool.
Definition: OptionalBool.h:25
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
The base class for a Nexus class (group).
Definition: NexusClasses.h:487
NXInt openNXInt(const std::string &name) const
Creates and opens an integer dataset.
Definition: NexusClasses.h:546
NXClass openNXGroup(const std::string &name) const
Creates and opens an arbitrary (non-standard) class (group).
Definition: NexusClasses.h:529
bool containsGroup(const std::string &query) const
Returns whether an individual group (or group) is present.
std::vector< NXClassInfo > & groups() const
Returns a list of all classes (or groups) in this NXClass.
Definition: NexusClasses.h:589
NXFloat openNXFloat(const std::string &name) const
Creates and opens a float dataset.
Definition: NexusClasses.h:551
std::string getString(const std::string &name) const
Returns a string.
Templated class implementation of NXDataSet.
Definition: NexusClasses.h:203
container_T< T > & vecBuffer()
Returns a the internal buffer.
Definition: NexusClasses.h:265
void load(const int blocksize=1, int i=-1, int j=-1, int k=-1, int l=-1) override
Implementation of the virtual NXDataSet::load(...) method.
Definition: NexusClasses.h:289
int dim2() const
Returns the number of elements along the third dimension.
int dim0() const
Returns the number of elements along the first dimension.
void open()
Opens the data set.
Implements NXdata Nexus class.
Definition: NexusClasses.h:795
NXInt openIntData()
Opens data of int type.
Definition: NexusClasses.h:828
Implements NXentry Nexus class.
Definition: NexusClasses.h:898
NXData openNXData(const std::string &name) const
Opens a NXData.
Definition: NexusClasses.h:912
NXhandle m_fileID
Nexus file id.
Definition: NexusClasses.h:113
std::string path() const
Returns the absolute path to the object.
Definition: NexusClasses.h:107
Implements NXroot Nexus class.
Definition: NexusClasses.h:922
NXEntry openEntry(const std::string &name)
Opens an entry – a topmost Nexus class.
Definition: NexusClasses.h:939
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
void loadSampleGeometry(API::Sample &sample, const NeXus::NXEntry &entry, const bool hasVMSBlock)
Load geometrical data about the sample from the nexus entry into a workspace.
std::tuple< NeXus::NXInt, NeXus::NXInt > findDetectorIDsAndSpectrumNumber(const NeXus::NXEntry &entry, const bool hasVMSBlock)
find detector ids and spectrum numbers
int64_t findNumberOfSpectra(const NeXus::NXEntry &entry, const bool hasVMSBlock)
find the number of spectra in the nexus file
std::shared_ptr< HistogramData::HistogramX > loadTimeData(const NeXus::NXEntry &entry)
Load the time data from nexus entry.
void loadRunDetails(API::Run &runDetails, const NeXus::NXEntry &entry, const bool hasVMSBlock)
Load data about the run.
void DLLExport populateDataBlockCompositeWithContainer(DataBlockComposite &dataBlockComposite, T &indexContainer, int64_t nArray, int numberOfPeriods, size_t numberOfChannels, std::vector< specnum_t > monitorSpectra)
Populates a DataBlockComposite with DataBlocks which are extracted from a indexable collection (array...
std::shared_ptr< Workspace2D > Workspace2D_sptr
shared pointer to Mantid::DataObjects::Workspace2D
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.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition: EmptyValues.h:25
int32_t specnum_t
Typedef for a spectrum Number.
Definition: IDTypes.h:16
Generate a tableworkspace to store the calibration results.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Output
An output workspace.
Definition: Property.h:54