Mantid
Loading...
Searching...
No Matches
LoadNexusMonitors2.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 +
8
9#include "MantidAPI/Axis.h"
11#include "MantidAPI/Sample.h"
19#include "MantidKernel/Unit.h"
22
23#include <Poco/File.h>
24#include <Poco/Path.h>
25#include <boost/lexical_cast.hpp>
26
27#include <algorithm>
28#include <cmath>
29#include <map>
30#include <vector>
31
38using Mantid::HistogramData::BinEdges;
39using Mantid::HistogramData::Counts;
40using Mantid::HistogramData::Histogram;
43
44namespace Mantid::DataHandling {
45
46// Register the algorithm into the AlgorithmFactory
48
49namespace {
50void loadSampleDataISIScompatibilityInfo(::NeXus::File &file, Mantid::API::MatrixWorkspace_sptr const &WS) {
51 try {
52 file.openGroup("isis_vms_compat", "IXvms");
53 } catch (::NeXus::Exception &) {
54 // No problem, it just means that this entry does not exist
55 return;
56 }
57
58 // read the data
59 try {
60 std::vector<int32_t> spb;
61 std::vector<float> rspb;
62 file.readData("SPB", spb);
63 file.readData("RSPB", rspb);
64
65 WS->mutableSample().setGeometryFlag(spb[2]); // the flag is in the third value
66 WS->mutableSample().setThickness(rspb[3]);
67 WS->mutableSample().setHeight(rspb[4]);
68 WS->mutableSample().setWidth(rspb[5]);
69 } catch (::NeXus::Exception &ex) {
70 // it means that the data was not as expected, report the problem
71 std::stringstream s;
72 s << "Wrong definition found in isis_vms_compat :> " << ex.what();
73 file.closeGroup();
74 throw std::runtime_error(s.str());
75 }
76
77 file.closeGroup();
78}
79
80const std::string LOAD_EVENTS("Events");
81const std::string LOAD_HISTO("Histogram");
82
83namespace PropertyNames {
84const std::string LOGS_ALLOW("AllowList");
85const std::string LOGS_BLOCK("BlockList");
86} // namespace PropertyNames
87
88// collection of static methods to inspect monitors to determine type
89bool keyExists(std::string const &key, std::map<std::string, std::string> const &entries) {
90 return entries.find(key) != entries.cend();
91}
92
93// returns true if all of the entries necessary for a histogram exist monitor in
94// the currently open group
95bool isHistoMonitor(::NeXus::File &monitorFileHandle) {
96 const auto fields = monitorFileHandle.getEntries();
97 return keyExists("data", fields) && keyExists("time_of_flight", fields);
98}
99
100std::size_t sizeOfUnopenedSDS(::NeXus::File &file, const std::string &fieldName) {
101 file.openData(fieldName);
102 auto size = static_cast<std::size_t>(file.getInfo().dims[0]);
103 file.closeData();
104 return size;
105}
106
107bool eventIdNotEmptyIfExists(::NeXus::File &file, std::map<std::string, std::string> const &fields) {
108 if (keyExists("event_id", fields))
109 return sizeOfUnopenedSDS(file, "event_id") > 1;
110 else
111 return true;
112}
113
114// returns true if all of the entries necessary for an event monitor exist in
115// the currently open group
116bool isEventMonitor(::NeXus::File &file) {
117 const auto fields = file.getEntries();
118 return keyExists("event_index", fields) && keyExists("event_time_offset", fields) &&
119 keyExists("event_time_zero", fields) && eventIdNotEmptyIfExists(file, fields);
120}
121} // anonymous namespace
122
123//------------------------------------------------------------------------------
126 declareProperty(std::make_unique<API::FileProperty>("Filename", "", API::FileProperty::Load, ".nxs"),
127 "The name (including its full or relative path) of the NeXus file to "
128 "attempt to load. The file extension must either be .nxs or .NXS");
129
131 std::make_unique<API::WorkspaceProperty<API::Workspace>>("OutputWorkspace", "", Kernel::Direction::Output),
132 "The name of the output workspace in which to load the NeXus monitors.");
133
135 "Optional: Name of the NXentry to load if it's not the default.");
136
137 std::vector<std::string> options{"", LOAD_EVENTS, LOAD_HISTO};
138 declareProperty("LoadOnly", "", std::make_shared<Kernel::StringListValidator>(options),
139 "If multiple repesentations exist, which one to load. "
140 "Default is to load the one that is present, and Histogram "
141 "if both are present.");
142
143 declareProperty(std::make_unique<PropertyWithValue<std::vector<std::string>>>(
144 PropertyNames::LOGS_ALLOW, std::vector<std::string>(), Direction::Input),
145 "If specified, only these logs will be loaded from the file (each "
146 "separated by a comma).");
147 declareProperty(std::make_unique<PropertyWithValue<std::vector<std::string>>>(
148 PropertyNames::LOGS_BLOCK, std::vector<std::string>(), Direction::Input),
149 "If specified, these logs will NOT be loaded from the file (each "
150 "separated by a comma).");
151}
152
153//------------------------------------------------------------------------------
159 // Retrieve the filename from the properties
160 m_filename = this->getPropertyValue("Filename");
161
162 API::Progress prog1(this, 0.0, 0.2, 2);
163
165 throw std::runtime_error("Failed to recognize this file as a NeXus file, cannot continue.");
166 }
167
168 m_top_entry_name = this->getPropertyValue("NXentryName");
169 // must be done here before the NeXus::File, HDF5 files can't have 2
170 // simultaneous handlers
172
173 // top level file information
174 ::NeXus::File file(m_filename);
175
176 // open the correct entry
177 using string_map_t = std::map<std::string, std::string>;
178 string_map_t::const_iterator it;
179 string_map_t entries = file.getEntries();
180
181 if (m_top_entry_name.empty()) {
182 for (it = entries.begin(); it != entries.end(); ++it) {
183 if (((it->first == "entry") || (it->first == "raw_data_1")) && (it->second == "NXentry")) {
184 file.openGroup(it->first, it->second);
185 m_top_entry_name = it->first;
186 break;
187 }
188 }
189 } else {
190 if (!keyExists(m_top_entry_name, entries)) {
191 throw std::invalid_argument(m_filename + " does not contain an entry named " + m_top_entry_name);
192 }
193 file.openGroup(m_top_entry_name, "NXentry"); // Open as will need to be
194 // open for subsequent operations
195 }
196 prog1.report();
197
198 size_t numPeriods = 0;
199 m_monitor_count = getMonitorInfo(file, numPeriods);
200 // Fix the detector numbers if the defaults above are not correct
201 // fixUDets(detector_numbers, file, spectra_numbers, m_monitor_count);
202 // a temporary place to put the spectra/detector numbers
203 // this gets the ids from the "isis_vms_compat" group
204 fixUDets(file);
205
206 if (numPeriods > 1) {
209 }
210
211 // Nothing to do
212 if (0 == m_monitor_count) {
213 // previous version just used to return, but that
214 // threw an error when the OutputWorkspace property was not set.
215 // and the error message was confusing.
216 // This has changed to throw a specific error.
217 throw std::invalid_argument(m_filename + " does not contain any monitors");
218 }
219
220 // only used if using event monitors
221 // EventWorkspace_sptr eventWS;
222 // Create the output workspace
223 std::vector<bool> loadMonitorFlags;
224 bool useEventMon = createOutputWorkspace(loadMonitorFlags);
225
226 API::Progress prog3(this, 0.6, 1.0, m_monitor_count);
227
228 // TODO-NEXT: load event monitor if it is required to do so
229 // load histogram monitor if it is required to do so
230 // Require a tuple: monitorNames[i], loadAsEvent[i], loadAsHistogram[i]
231 for (std::size_t ws_index = 0; ws_index < m_monitor_count; ++ws_index) {
232 // already know spectrum and detector numbers
233 g_log.debug() << "monIndex = " << m_monitorInfo[ws_index].detNum << '\n';
234 g_log.debug() << "spectrumNo = " << m_monitorInfo[ws_index].specNum << '\n';
235 m_workspace->getSpectrum(ws_index).setSpectrumNo(m_monitorInfo[ws_index].specNum);
236 m_workspace->getSpectrum(ws_index).setDetectorID(m_monitorInfo[ws_index].detNum);
237
238 // Don't actually read all of the monitors
239 g_log.information() << "Loading " << m_monitorInfo[ws_index].name;
240 if (loadMonitorFlags[ws_index]) {
241 g_log.information() << "\n";
242 file.openGroup(m_monitorInfo[ws_index].name, "NXmonitor");
243 if (useEventMon) {
244 // load as an event monitor
245 readEventMonitorEntry(file, ws_index);
246 } else {
247 // load as a histogram monitor
248 readHistoMonitorEntry(file, ws_index, numPeriods);
249 }
250 file.closeGroup(); // NXmonitor
251 } else {
252 g_log.information() << " is skipped.\n";
253 }
254
255 prog3.report();
256 }
257
258 if (useEventMon) // set the x-range to be the range for min/max events
259 {
260 EventWorkspace_sptr eventWS = std::dynamic_pointer_cast<EventWorkspace>(m_workspace);
261 double xmin, xmax;
262 eventWS->getEventXMinMax(xmin, xmax);
263
264 auto axis = HistogramData::BinEdges{xmin - 1, xmax + 1};
265 eventWS->setAllX(axis); // Set the binning axis using this.
266
267 // a certain generation of ISIS files modify the time-of-flight
268 const std::string currentPath = file.getPath();
269 adjustTimeOfFlightISISLegacy(file, eventWS, m_top_entry_name, "NXmonitor");
270 file.openPath(currentPath); // reset to where it was earlier
271 }
272
273 // Check for and ISIS compat block to get the detector IDs for the loaded
274 // spectrum numbers
275 // @todo: Find out if there is a better (i.e. more generic) way to do this
276 try {
277 g_log.debug() << "Load Sample data isis\n";
278 loadSampleDataISIScompatibilityInfo(file, m_workspace);
279 } catch (::NeXus::Exception &) {
280 }
281
282 // Need to get the instrument name from the file
283 std::string instrumentName;
284 file.openGroup("instrument", "NXinstrument");
285 try {
286 file.openData("name");
287 instrumentName = file.getStrData();
288 // Now let's close the file as we don't need it anymore to load the
289 // instrument.
290 file.closeData();
291 file.closeGroup(); // Close the NXentry
292 file.close();
293
294 } catch (std::runtime_error &) // no correct instrument definition (old ISIS
295 // file, fall back to isis_vms_compat)
296 {
297 file.closeGroup(); // Close the instrument NXentry
299 file.close();
300 }
301
302 g_log.debug() << "Instrument name read from NeXus file is " << instrumentName << '\n';
303
304 m_workspace->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("TOF");
305 m_workspace->setYUnit("Counts");
306
307 // Load the logs
309
310 // Old SNS files don't have this
311 try {
312 // The run_start will be loaded from the pulse times.
313 Types::Core::DateAndTime run_start(0, 0);
314 run_start = m_workspace->getFirstPulseTime();
315 m_workspace->mutableRun().addProperty("run_start", run_start.toISO8601String(), true);
316 } catch (...) {
317 // Old files have the start_time defined, so all SHOULD be good.
318 // The start_time, however, has been known to be wrong in old files.
319 }
320 // Load the instrument
322
323 // Load the meta data, but don't stop on errors
324 g_log.debug() << "Loading metadata\n";
325 try {
326 LoadEventNexus::loadEntryMetadata<API::MatrixWorkspace_sptr>(m_filename, m_workspace, m_top_entry_name, descriptor);
327 } catch (std::exception &e) {
328 g_log.warning() << "Error while loading meta data: " << e.what() << '\n';
329 }
330
331 // add filename
332 m_workspace->mutableRun().addProperty("Filename", m_filename);
333
334 // if multiperiod histogram data
335 if ((numPeriods > 1) && (!useEventMon)) {
337 } else {
338 this->setProperty("OutputWorkspace", m_workspace);
339 }
340}
341
342//------------------------------------------------------------------------------
349void LoadNexusMonitors2::fixUDets(::NeXus::File &file) {
350 const size_t nmonitors = m_monitorInfo.size();
351 boost::scoped_array<detid_t> det_ids(new detid_t[nmonitors]);
352 boost::scoped_array<specnum_t> spec_ids(new specnum_t[nmonitors]);
353 // convert the monitor info into two arrays for resorting
354 for (size_t i = 0; i < nmonitors; ++i) {
355 spec_ids[i] = m_monitorInfo[i].specNum;
356 det_ids[i] = m_monitorInfo[i].detNum;
357 }
358
359 try {
360 file.openGroup("isis_vms_compat", "IXvms");
361 } catch (::NeXus::Exception &) {
362 return;
363 }
364 // UDET
365 file.openData("UDET");
366 std::vector<int32_t> udet;
367 file.getData(udet);
368 file.closeData();
369 // SPEC
370 file.openData("SPEC");
371 std::vector<int32_t> spec;
372 file.getData(spec);
373 file.closeData();
374
375 // This is a little complicated: Each value in the spec_id array is a value
376 // found in the
377 // SPEC block of isis_vms_compat. The index that this value is found at then
378 // corresponds
379 // to the index within the UDET block that holds the detector ID
380 std::vector<int32_t>::const_iterator beg = spec.begin();
381 for (size_t mon_index = 0; mon_index < nmonitors; ++mon_index) {
382 std::vector<int32_t>::const_iterator itr = std::find(spec.begin(), spec.end(), spec_ids[mon_index]);
383 if (itr == spec.end()) {
384 det_ids[mon_index] = -1;
385 continue;
386 }
387 std::vector<int32_t>::difference_type udet_index = std::distance(beg, itr);
388 det_ids[mon_index] = udet[udet_index];
389 }
390 file.closeGroup();
391
392 // copy the information back into the monitorinfo
393 for (size_t i = 0; i < nmonitors; ++i) {
394 m_monitorInfo[i].specNum = spec_ids[i];
395 m_monitorInfo[i].detNum = det_ids[i];
396 }
397}
398
399void LoadNexusMonitors2::runLoadLogs(const std::string &filename, const API::MatrixWorkspace_sptr &localWorkspace) {
400 // get the properties for which logs to use
401 const std::vector<std::string> allow_list = getProperty(PropertyNames::LOGS_ALLOW);
402 const std::vector<std::string> block_list = getProperty(PropertyNames::LOGS_BLOCK);
403
404 // do the actual work
405 auto loadLogs = createChildAlgorithm("LoadNexusLogs");
406
407 // Now execute the Child Algorithm. Catch and log any error, but don't stop.
408 try {
409 g_log.information() << "Loading logs from NeXus file...\n";
410 loadLogs->setPropertyValue("Filename", filename);
411 loadLogs->setProperty<API::MatrixWorkspace_sptr>("Workspace", localWorkspace);
412 // copy properties for which logs to use/not use
413 loadLogs->setProperty<std::vector<std::string>>(PropertyNames::LOGS_ALLOW, allow_list);
414 loadLogs->setProperty<std::vector<std::string>>(PropertyNames::LOGS_BLOCK, block_list);
415 loadLogs->execute();
416 } catch (...) {
417 g_log.error() << "Error while loading Logs from Nexus. Some sample logs "
418 "may be missing.\n";
419 }
420}
421
422//------------------------------------------------------------------------------
429bool LoadNexusMonitors2::canOpenAsNeXus(const std::string &fname) {
430 bool res = true;
431 std::unique_ptr<::NeXus::File> filePointer;
432 try {
433 filePointer = std::make_unique<::NeXus::File>(fname);
434 if (filePointer)
435 filePointer->getEntries();
436 } catch (::NeXus::Exception &e) {
437 g_log.error() << "Failed to open as a NeXus file: '" << fname << "', error description: " << e.what() << '\n';
438 res = false;
439 }
440 return res;
441}
442
443//------------------------------------------------------------------------------
451 // protection - we should not have entered the routine if these are not true
452 // More than 1 period
453 if (numPeriods < 2) {
454 g_log.warning() << "Attempted to split multiperiod histogram workspace with " << numPeriods
455 << "periods, aborted.\n";
456 return;
457 }
458
459 // Y array should be divisible by the number of periods
460 if (m_multiPeriodCounts[0].size() % numPeriods != 0) {
461 g_log.warning() << "Attempted to split multiperiod histogram workspace with " << m_multiPeriodCounts[0].size()
462 << "data entries, into " << numPeriods
463 << "periods."
464 " Aborted.\n";
465 return;
466 }
467
469 size_t yLength = m_multiPeriodCounts[0].size() / numPeriods;
470 size_t xLength = yLength + 1;
471 size_t numSpectra = m_workspace->getNumberHistograms();
472 ISISRunLogs monLogCreator(m_workspace->run());
473
474 BinEdges edges = m_multiPeriodBinEdges[0];
475
476 for (size_t i = 0; i < numPeriods; i++) {
477 // create the period workspace
479 API::WorkspaceFactory::Instance().create(m_workspace, numSpectra, xLength, yLength);
480
481 auto offset = yLength * i;
482
483 for (size_t wsIndex = 0; wsIndex < numSpectra; wsIndex++) {
484 auto inYBegin = m_multiPeriodCounts[wsIndex].cbegin() + offset;
485
486 wsPeriod->setHistogram(wsIndex, edges, Counts(inYBegin, inYBegin + yLength));
487 }
488 // add period logs
489 monLogCreator.addStatusLog(wsPeriod->mutableRun());
490 monLogCreator.addPeriodLogs(static_cast<int>(i + 1), wsPeriod->mutableRun());
491
492 // add to workspace group
493 wsGroup->addWorkspace(wsPeriod);
494 }
495
496 // set the output workspace
497 this->setProperty("OutputWorkspace", wsGroup);
498}
499
500size_t LoadNexusMonitors2::getMonitorInfo(::NeXus::File &file, size_t &numPeriods) {
501 // should already be open to the correct NXentry
502
503 m_monitorInfo.clear();
504
505 using string_map_t = std::map<std::string, std::string>;
506
507 // Now we want to go through and find the monitors
508 string_map_t entries = file.getEntries();
509 numPeriods = 0;
510 // we want to sort monitors by monitor_number if they are present
511
512 API::Progress prog2(this, 0.2, 0.6, entries.size());
513
514 string_map_t::const_iterator it = entries.begin();
515 for (; it != entries.end(); ++it) {
516 std::string entry_name(it->first);
517 std::string entry_class(it->second);
518 if ((entry_class == "NXmonitor")) {
519 MonitorInfo info;
520
521 // check for event/histogram monitor
522 // -> This will prefer event monitors over histogram
523 // if they are found in the same group.
524 file.openGroup(entry_name, "NXmonitor");
525 info.name = entry_name;
526 info.hasEvent = isEventMonitor(file);
527 info.hasHisto = isHistoMonitor(file);
528
529 // get the detector number
530 string_map_t inner_entries = file.getEntries(); // get list of entries
531 if (inner_entries.find("monitor_number") != inner_entries.end()) {
532 // get monitor number from field in file
533 const auto detNum = NeXus::NeXusIOHelper::readNexusValue<int64_t>(file, "monitor_number");
534 if (detNum > std::numeric_limits<detid_t>::max()) {
535 throw std::runtime_error("Monitor number too larger to represent");
536 }
537 info.detNum = static_cast<detid_t>(detNum);
538 } else {
539 // default creates it from monitor name
540 Poco::Path monPath(entry_name);
541 std::string monitorName = monPath.getBaseName();
542
543 // check for monitor name - in our case will be of the form either
544 // monitor1
545 // or monitor_1
546 std::string::size_type loc = monitorName.rfind('_');
547 if (loc == std::string::npos) {
548 loc = monitorName.rfind('r');
549 }
550
551 info.detNum = -1 * boost::lexical_cast<int>(monitorName.substr(loc + 1)); // SNS default
552 }
553
554 // get the spectrum number
555 if (inner_entries.find("spectrum_index") != inner_entries.end()) {
556 file.openData("spectrum_index");
557 file.getData(&info.specNum);
558 file.closeData();
559 } else {
560 // default is to match the detector number
561 info.specNum = std::abs(info.detNum);
562 }
563
564 if (info.hasHisto && (numPeriods == 0) && (inner_entries.find("period_index") != inner_entries.end())) {
565 MantidVec period_data;
566 file.openData("period_index");
567 file.getDataCoerce(period_data);
568 file.closeData();
569 numPeriods = period_data.size();
570 }
571
572 file.closeGroup(); // close NXmonitor
573 m_monitorInfo.emplace_back(info);
574 }
575 prog2.report();
576 }
577
578 // sort based on the absolute value of the monitor number
579 // this takes care of the fact that SNS monitors have negative numbers
580 std::sort(m_monitorInfo.begin(), m_monitorInfo.end(), [](const MonitorInfo &left, const MonitorInfo &right) {
581 return std::abs(left.detNum) < std::abs(right.detNum);
582 });
583
584 return m_monitorInfo.size();
585}
586
587bool LoadNexusMonitors2::createOutputWorkspace(std::vector<bool> &loadMonitorFlags) {
588 loadMonitorFlags.clear();
589
590 size_t numEventMon =
591 std::count_if(m_monitorInfo.begin(), m_monitorInfo.end(), [](const MonitorInfo &info) { return info.hasEvent; });
592 size_t numHistoMon =
593 std::count_if(m_monitorInfo.begin(), m_monitorInfo.end(), [](const MonitorInfo &info) { return info.hasHisto; });
594
595 bool useEventMon; // which type of workspace to create/is created
596 const std::string loadType = getProperty("LoadOnly");
597 if (loadType == LOAD_EVENTS) {
598 useEventMon = true;
599 if (numEventMon == 0) { // make sure there are some
600 throw std::runtime_error("Loading event data. Trying to load event data but failed to "
601 "find event monitors. This file may be corrupted or it may not be "
602 "supported");
603 }
604 } else if (loadType == LOAD_HISTO) {
605 useEventMon = false;
606 if (numHistoMon == 0) { // make sure there are some
607 throw std::runtime_error("Not loading event data. Trying to load histogram data but failed to "
608 "find monitors with histogram data or could not interpret the data. "
609 "This file may be corrupted or it may not be supported");
610 }
611 } else { // only other option is to go with the default
612 if (numEventMon > 0 && numHistoMon > 0) {
613 std::stringstream errmsg;
614 errmsg << "There are " << numHistoMon << " histogram monitors and " << numEventMon
615 << " event monitors. Loading Histogram by default. "
616 << "Use \"LoadOnly\" or \"MonitorLoadOnly\" to specify which to "
617 "load.";
618 m_log.warning(errmsg.str());
619 useEventMon = false;
620 } else {
621 // more than one event monitor means use that since both can't be nonzero
622 useEventMon = (numEventMon > 0);
623 }
624 }
625
626 // set up the flags to load monitor
627 if (useEventMon) {
628 // load event
629 for (size_t i_mon = 0; i_mon < m_monitor_count; ++i_mon) {
630 loadMonitorFlags.emplace_back(m_monitorInfo[i_mon].hasEvent);
631 }
632 } else {
633 // load histogram
634 for (size_t i_mon = 0; i_mon < m_monitor_count; ++i_mon) {
635 loadMonitorFlags.emplace_back(m_monitorInfo[i_mon].hasHisto);
636 }
637 }
638
639 // create workspace
640 if (useEventMon) {
641 // Use event monitors and create event workspace
642
643 // only used if using event monitors
645 eventWS->initialize(m_monitorInfo.size(), 1, 1);
646
647 // Set the units
648 eventWS->getAxis(0)->unit() = Mantid::Kernel::UnitFactory::Instance().create("TOF");
649 eventWS->setYUnit("Counts");
650 m_workspace = eventWS;
651 } else { // only other option is histograms
652 // Use histogram monitors and event monitors' histogram data.
653 // And thus create a Workspace2D.
654
655 m_workspace = API::WorkspaceFactory::Instance().create("Workspace2D", m_monitorInfo.size(), 2, 1);
656 }
657
658 return useEventMon;
659}
660
661void LoadNexusMonitors2::readEventMonitorEntry(::NeXus::File &file, size_t ws_index) {
662 // setup local variables
663 EventWorkspace_sptr eventWS = std::dynamic_pointer_cast<EventWorkspace>(m_workspace);
664 std::string tof_units, event_time_zero_units;
665
666 // read in the data
667 auto event_index = NeXus::NeXusIOHelper::readNexusVector<uint64_t>(file, "event_index");
668
669 file.openData("event_time_offset"); // time of flight
670 MantidVec time_of_flight = NeXus::NeXusIOHelper::readNexusVector<double>(file);
671 file.getAttr("units", tof_units);
672 Kernel::Units::timeConversionVector(time_of_flight, tof_units, "microseconds");
673 file.closeData();
674
675 file.openData("event_time_zero"); // pulse time
676 MantidVec seconds = NeXus::NeXusIOHelper::readNexusVector<double>(file);
677 file.getAttr("units", event_time_zero_units);
678 Kernel::Units::timeConversionVector(seconds, event_time_zero_units, "seconds");
679 Mantid::Types::Core::DateAndTime pulsetime_offset;
680 {
681 std::string startTime;
682 file.getAttr("offset", startTime);
683 pulsetime_offset = createFromSanitizedISO8601(startTime);
684 }
685 file.closeData();
686
687 // load up the event list
688 DataObjects::EventList &event_list = eventWS->getSpectrum(ws_index);
689
690 Mantid::Types::Core::DateAndTime pulsetime(0);
691 Mantid::Types::Core::DateAndTime lastpulsetime(0);
692 std::size_t numEvents = time_of_flight.size();
693 bool pulsetimesincreasing = true;
694 size_t pulse_index(0);
695 size_t numPulses = seconds.size();
696 for (std::size_t j = 0; j < numEvents; ++j) {
697 while (!((j >= event_index[pulse_index]) && (j < event_index[pulse_index + 1]))) {
698 pulse_index += 1;
699 if (pulse_index > (numPulses + 1))
700 break;
701 }
702 if (pulse_index >= (numPulses))
703 pulse_index = numPulses - 1; // fix it
704 pulsetime = pulsetime_offset + seconds[pulse_index];
705 if (pulsetime < lastpulsetime)
706 pulsetimesincreasing = false;
707 lastpulsetime = pulsetime;
708 event_list.addEventQuickly(Types::Event::TofEvent(time_of_flight[j], pulsetime));
709 }
710 if (pulsetimesincreasing)
712}
713
714void LoadNexusMonitors2::readHistoMonitorEntry(::NeXus::File &file, size_t ws_index, size_t numPeriods) {
715 // Now, actually retrieve the necessary data
716 file.openData("data");
717 MantidVec data;
718 file.getDataCoerce(data);
719 file.closeData();
720
721 // Get the TOF axis
722 file.openData("time_of_flight");
723 MantidVec tof;
724 file.getDataCoerce(tof);
725 file.closeData();
726
727 if (numPeriods > 1) {
728 m_multiPeriodBinEdges[ws_index] = std::move(tof);
729 m_multiPeriodCounts[ws_index] = std::move(data);
730 } else {
731 m_workspace->setHistogram(ws_index, Histogram(BinEdges(std::move(tof)), Counts(std::move(data))));
732 }
733}
734
735} // namespace Mantid::DataHandling
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
double left
Definition: LineProfile.cpp:80
double right
Definition: LineProfile.cpp:81
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
Kernel::Logger & g_log
Definition: Algorithm.h:451
Kernel::Logger m_log
Logger for this algorithm.
Definition: Algorithm.h:450
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
Class to hold a set of workspaces.
A property class for workspaces.
Defines a class to aid in creating ISIS specific run logs for periods, status etc.
Definition: ISISRunLogs.h:28
void addStatusLog(API::Run &exptRun)
Adds the status log to the this run.
Definition: ISISRunLogs.cpp:47
void addPeriodLogs(const int period, API::Run &exptRun)
Adds period related logs.
Definition: ISISRunLogs.cpp:54
static std::string readInstrumentFromISIS_VMSCompat(::NeXus::File &hFile)
method used to return instrument name for some old ISIS files where it is not written properly within...
static bool loadInstrument(const std::string &nexusfilename, T localWorkspace, const std::string &top_entry_name, Algorithm *alg, const Kernel::NexusHDF5Descriptor *descriptor=nullptr)
Load instrument from Nexus file if possible, else from IDF spacified by Nexus file.
void runLoadLogs(const std::string &filename, const API::MatrixWorkspace_sptr &localWorkspace)
Load the logs.
bool createOutputWorkspace(std::vector< bool > &loadMonitorFlags)
void splitMutiPeriodHistrogramData(const size_t numPeriods)
split multi period histogram workspace into a workspace group
std::vector< LoadNexusMonitorsAlg::MonitorInfo > m_monitorInfo
size_t getMonitorInfo(NeXus::File &file, size_t &numPeriods)
void init() override
Initialise algorithm.
std::string m_filename
The name and path of the input file.
std::vector< HistogramData::BinEdges > m_multiPeriodBinEdges
std::string m_top_entry_name
name of top level NXentry to use
void readHistoMonitorEntry(NeXus::File &file, size_t ws_index, size_t numPeriods)
const std::string name() const override
Algorithm's name for identification.
API::MatrixWorkspace_sptr m_workspace
The workspace being filled out.
void fixUDets(::NeXus::File &file)
Fix the detector numbers if the defaults are not correct.
void exec() override
Execute algorithm.
void readEventMonitorEntry(NeXus::File &file, size_t ws_index)
bool canOpenAsNeXus(const std::string &fname)
is it possible to open the file?
std::vector< HistogramData::Counts > m_multiPeriodCounts
A class for holding :
Definition: EventList.h:56
void setSortOrder(const EventSortType order) const
Manually set the event list sort order value.
Definition: EventList.cpp:943
void addEventQuickly(const Types::Event::TofEvent &event)
Append an event to the histogram, without clearing the cache, to make it faster.
Definition: EventList.h:104
This class is intended to fulfill the design specified in <https://github.com/mantidproject/documents...
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
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
Definition: ProgressBase.h:51
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::size_t numEvents(::NeXus::File &file, bool &hasTotalCounts, bool &oldNeXusFileNames, const std::string &prefix, const NexusHDF5Descriptor &descriptor)
Get the number of events in the currently opened group.
void adjustTimeOfFlightISISLegacy(::NeXus::File &file, T localWorkspace, const std::string &entry_name, const std::string &classType, const Kernel::NexusHDF5Descriptor *descriptor=nullptr)
ISIS specific method for dealing with wide events.
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
MANTID_KERNEL_DLL Types::Core::DateAndTime createFromSanitizedISO8601(const std::string &date)
Creates a DateAndTime object from a date string even if the string does not exactly conform to ISO860...
void timeConversionVector(std::vector< T > &vec, const std::string &input_unit, const std::string &output_unit)
Definition: Unit.h:708
int32_t detid_t
Typedef for a detector ID.
Definition: SpectrumInfo.h:21
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
Definition: cow_ptr.h:172
int32_t specnum_t
Typedef for a spectrum Number.
Definition: IDTypes.h:16
std::string name
name of the group in the nexus file - TODO was
Describes the direction (within an algorithm) of a Property.
Definition: Property.h:50
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54