Mantid
Loading...
Searching...
No Matches
LoadBBY2.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#include <algorithm>
8#include <chrono>
9#include <cmath>
10#include <cstdio>
11#include <map>
12#include <sstream>
13
15#include "MantidAPI/Axis.h"
19#include "MantidAPI/Run.h"
30
31#include <boost/algorithm/string.hpp>
32#include <boost/algorithm/string/trim.hpp>
33#include <boost/math/special_functions/round.hpp>
34
35#include <Poco/AutoPtr.h>
36#include <Poco/DOM/AutoPtr.h>
37#include <Poco/DOM/DOMParser.h>
38#include <Poco/DOM/Document.h>
39#include <Poco/DOM/Element.h>
40#include <Poco/DOM/NodeFilter.h>
41#include <Poco/DOM/NodeIterator.h>
42#include <Poco/DOM/NodeList.h>
43#include <Poco/TemporaryFile.h>
44#include <Poco/Util/PropertyFileConfiguration.h>
45
46namespace Mantid::DataHandling {
47
48using namespace Kernel;
49using namespace API;
50using namespace Nexus;
51
52// register the algorithm
54
55// consts
56static const int LAST_INDEX = -1;
57static const size_t HISTO_BINS_X = 240;
58static const size_t HISTO_BINS_Y = 256;
59// 100 = 40 + 20 + 40
60static const size_t Progress_LoadBinFile = 48;
61static const size_t Progress_ReserveMemory = 4;
63
64static char const *const FilenameStr = "Filename";
65static char const *const MaskStr = "Mask";
66
67static char const *const FilterByTofMinStr = "FilterByTofMin";
68static char const *const FilterByTofMaxStr = "FilterByTofMax";
69
70static char const *const FilterByTimeStartStr = "FilterByTimeStart";
71static char const *const FilterByTimeStopStr = "FilterByTimeStop";
72
73static char const *const UseHMScanTimeStr = "UseHMScanTime";
74
75using namespace ANSTO;
76using ANSTO::EventVector_pt;
77
78static const std::map<std::string, Anxs::ScanLog> ScanLogMap = {
79 {"end", Anxs::ScanLog::End}, {"mean", Anxs::ScanLog::Mean}, {"start", Anxs::ScanLog::Start}};
80
81template <typename T>
82void traceStatistics(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime, uint64_t endTime,
83 Kernel::Logger &log) {
84
85 if (log.isDebug()) {
86
87 std::vector<uint64_t> times;
88 std::vector<T> values;
89 std::string units;
90 auto n = Anxs::extractTimedDataSet<T>(entry, path, startTime, endTime, times, values, units);
91
92 // log stats on the parameter variation
93 if (n > 0) {
94 auto meanX = std::accumulate(values.begin(), values.end(), 0.0) / static_cast<T>(n);
95 T accum{0};
96 std::for_each(values.begin(), values.end(), [&](const double d) { accum += (d - meanX) * (d - meanX); });
97 auto stdX = sqrt(accum / static_cast<T>(n));
98 auto result = std::minmax_element(values.begin(), values.end());
99 log.debug() << "Log parameter " << path << ": " << meanX << " +- " << stdX << ", " << *result.first << " ... "
100 << *result.second << ", pts " << n << std::endl;
101 } else {
102 log.debug() << "Cannot find : " << path << std::endl;
103 return;
104 }
105 }
106}
107
108template <typename TYPE>
109void addSinglePointTimeSeriesProperty(API::LogManager &logManager, const std::string &time, const std::string &name,
110 const TYPE value) {
111 // create time series property and add single value
113 p->addValue(time, value);
114
115 // add to log manager
116 logManager.addProperty(p);
117}
118
119template <typename EP>
120void loadEvents(API::Progress &prog, const char *progMsg, EP &eventProcessor, const Nexus::NXEntry &entry,
121 uint64_t start_nsec, uint64_t end_nsec) {
122
123 using namespace ANSTO;
124
125 prog.doReport(progMsg);
126
127 // for progress notifications
129
130 const std::string neutronPath{"instrument/detector_events"};
131 Anxs::ReadEventData(progTracker, entry, &eventProcessor, start_nsec, end_nsec, neutronPath, HISTO_BINS_Y);
132}
133
136
144
145 static const std::set<std::string> requiredEntries = {"/entry1/program_name",
146 "/entry1/experiment/gumtree_version",
147 "/entry1/instrument/detector_events/event_time_zero",
148 "/entry1/instrument/detector_events/event_id",
149 "/entry1/instrument/L1/value",
150 "/entry1/instrument/L2_curtaind/value",
151 "/entry1/instrument/L2_curtainl/value",
152 "/entry1/instrument/L2_curtainr/value",
153 "/entry1/instrument/L2_curtainu/value",
154 "/entry1/instrument/nvs067/lambda/value",
155 "/entry1/instrument/shutters/fast_shutter",
156 "/entry1/scan_dataset/time",
157 "/entry1/scan_dataset/value"};
158
159 if (std::all_of(requiredEntries.cbegin(), requiredEntries.cend(),
160 [&descriptor](const std::string &entry) { return descriptor.isEntry(entry); })) {
161 return 95;
162 } else {
163 return 0;
164 }
165}
172 // Specify file extensions which can be associated with a specific file.
173 std::vector<std::string> exts;
174
175 // Declare the Filename algorithm property. Mandatory. Sets the path to the
176 // file to load.
177 exts.clear();
178 exts.emplace_back(".nxs");
179 declareProperty(std::make_unique<API::FileProperty>(FilenameStr, "", API::FileProperty::Load, exts),
180 "The input filename of the stored data");
181
182 // mask
183 exts.clear();
184 exts.emplace_back(".xml");
185 declareProperty(std::make_unique<API::FileProperty>(MaskStr, "", API::FileProperty::OptionalLoad, exts),
186 "The input filename of the mask data");
187
188 // OutputWorkspace
190 std::make_unique<API::WorkspaceProperty<API::IEventWorkspace>>("OutputWorkspace", "", Kernel::Direction::Output));
191
192 // FilterByTofMin
194 "Optional: To exclude events that do not fall within a range "
195 "of times-of-flight. "
196 "This is the minimum accepted value in microseconds. Keep "
197 "blank to load all events.");
198
199 // FilterByTofMax
202 "Optional: To exclude events that do not fall within a range "
203 "of times-of-flight. "
204 "This is the maximum accepted value in microseconds. Keep "
205 "blank to load all events.");
206
207 // FilterByTimeStart
210 "Optional: To only include events after the provided start time, in "
211 "seconds (relative to the start of the run).");
212
213 // FilterByTimeStop
216 "Optional: To only include events before the provided stop time, in "
217 "seconds (relative to the start of the run).");
218
219 declareProperty(UseHMScanTimeStr, true, "Use hmscan time rather than scan_dataset.");
220
221 std::string grpOptional = "Filters";
226}
231
232 // Delete the output workspace name if it existed
233 std::string outName = getPropertyValue("OutputWorkspace");
234 if (API::AnalysisDataService::Instance().doesExist(outName))
235 API::AnalysisDataService::Instance().remove(outName);
236
237 // Get the name of the data file.
238 std::string nxsFile = getPropertyValue(FilenameStr);
239
241
242 // get the root entry and time period
243 Nexus::NXRoot root(nxsFile);
244 Nexus::NXEntry nxsEntry = root.openFirstEntry();
245 uint64_t startTime, endTime;
246 if (useHMScanTime)
247 std::tie(startTime, endTime) = Anxs::getHMScanLimits(nxsEntry, 0);
248 else
249 std::tie(startTime, endTime) = Anxs::getTimeScanLimits(nxsEntry, 0);
250 if (startTime >= endTime) {
251 g_log.error() << "Invalid time window from " << (useHMScanTime ? "hmscan" : "scan_dataset") << "\n";
252 throw std::runtime_error("LoadBBY2: invalid or missing scan time range.");
253 }
254
255 // region of intreset
256 std::vector<bool> roi = createRoiVector(getPropertyValue(MaskStr));
257
258 double tofMinBoundary = getProperty(FilterByTofMinStr);
259 double tofMaxBoundary = getProperty(FilterByTofMaxStr);
260
261 double timeMinBoundary = getProperty(FilterByTimeStartStr);
262 double timeMaxBoundary = getProperty(FilterByTimeStopStr);
263
264 if (isEmpty(tofMaxBoundary))
265 tofMaxBoundary = std::numeric_limits<double>::infinity();
266 if (isEmpty(timeMaxBoundary))
267 timeMaxBoundary = std::numeric_limits<double>::infinity();
268
269 API::Progress prog(this, 0.0, 1.0, Progress_Total);
270 prog.doReport("creating instrument");
271
272 // create workspace
273 DataObjects::EventWorkspace_sptr eventWS = std::make_shared<DataObjects::EventWorkspace>();
274
275 eventWS->initialize(HISTO_BINS_Y * HISTO_BINS_X,
276 2, // number of TOF bin boundaries
277 1);
278
279 // create instrument
280 InstrumentInfo instrumentInfo;
281 std::map<std::string, double> logParams;
282 std::map<std::string, std::string> logStrings;
283 std::map<std::string, std::string> allParams;
284 createInstrument(nxsEntry, startTime, endTime, instrumentInfo, logParams, logStrings, allParams);
285
286 // set the units
287 if (instrumentInfo.is_tof)
288 eventWS->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("TOF");
289 else
290 eventWS->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("Wavelength");
291
292 eventWS->setYUnit("Counts");
293 eventWS->setTitle(Anxs::extractWorkspaceTitle(nxsFile));
294
295 // load events
296 size_t numberHistograms = eventWS->getNumberHistograms();
297
298 std::vector<EventVector_pt> eventVectors(numberHistograms, nullptr);
299 std::vector<size_t> eventCounts(numberHistograms, 0);
300
301 // phase correction
302
303 double periodMaster = instrumentInfo.period_master;
304 double periodSlave = instrumentInfo.period_slave;
305 double phaseSlave = instrumentInfo.phase_slave;
306
307 double period = periodSlave;
308 double shift = -1.0 / 6.0 * periodMaster - periodSlave * phaseSlave / 360.0;
309
310 // get the start time from the file
311 Types::Core::DateAndTime startDateTime(instrumentInfo.start_time);
312 auto startInNanosec = startDateTime.totalNanoseconds();
313
314 // count total events per pixel to reserve necessary memory
315 ANSTO::EventCounter eventCounter(roi, HISTO_BINS_Y, period, shift, startInNanosec, tofMinBoundary, tofMaxBoundary,
316 timeMinBoundary, timeMaxBoundary, eventCounts);
317
318 loadEvents<ANSTO::EventCounter>(prog, "loading neutron counts", eventCounter, nxsEntry, startTime, endTime);
319
320 // prepare event storage
321 ANSTO::ProgressTracker progTracker(prog, "creating neutron event lists", numberHistograms, Progress_ReserveMemory);
322
323 for (size_t i = 0; i != numberHistograms; ++i) {
324 DataObjects::EventList &eventList = eventWS->getSpectrum(i);
325
327 eventList.reserve(eventCounts[i]);
328
329 eventList.setDetectorID(static_cast<detid_t>(i));
330 eventList.setSpectrumNo(static_cast<detid_t>(i));
331
332 DataObjects::getEventsFrom(eventList, eventVectors[i]);
333
334 progTracker.update(i);
335 }
336 progTracker.complete();
337
338 if (instrumentInfo.is_tof) {
339 ANSTO::EventAssigner eventAssigner(roi, HISTO_BINS_Y, period, shift, startInNanosec, tofMinBoundary, tofMaxBoundary,
340 timeMinBoundary, timeMaxBoundary, eventVectors);
341
342 loadEvents(prog, "loading neutron events (TOF)", eventAssigner, nxsEntry, startTime, endTime);
343 } else {
344 ANSTO::EventAssignerFixedWavelength eventAssigner(roi, HISTO_BINS_Y, instrumentInfo.wavelength, period, shift,
345 startInNanosec, tofMinBoundary, tofMaxBoundary, timeMinBoundary,
346 timeMaxBoundary, eventVectors);
347
348 loadEvents(prog, "loading neutron events (Wavelength)", eventAssigner, nxsEntry, startTime, endTime);
349 }
350
351 auto getParam = [&allParams](const std::string &tag, double defValue) {
352 try {
353 return std::stod(allParams[tag]);
354 } catch (const std::invalid_argument &) {
355 return defValue;
356 }
357 };
358 if (instrumentInfo.is_tof) {
359 // just to make sure the bins hold it all
360 eventWS->setAllX(HistogramData::BinEdges{std::max(0.0, floor(eventCounter.tofMin())), eventCounter.tofMax() + 1});
361 } else {
362 double lof = getParam("wavelength_extn_lo", 0.95);
363 double hif = getParam("wavelength_extn_hi", 1.05);
364 eventWS->setAllX(HistogramData::BinEdges{instrumentInfo.wavelength * lof, instrumentInfo.wavelength * hif});
365 }
366
367 // count total number of masked bins
368 size_t maskedBins = std::count_if(roi.begin(), roi.end(), [](bool v) { return !v; });
369
370 if (maskedBins > 0) {
371 // create list of masked bins
372 std::vector<size_t> maskIndexList(maskedBins);
373 size_t maskIndex = 0;
374
375 for (size_t i = 0; i != roi.size(); i++)
376 if (!roi[i])
377 maskIndexList[maskIndex++] = i;
378
379 auto maskingAlg = createChildAlgorithm("MaskDetectors");
380 maskingAlg->setProperty("Workspace", eventWS);
381 maskingAlg->setProperty("WorkspaceIndexList", maskIndexList);
382 maskingAlg->executeAsChildAlg();
383 }
384
385 // set log values
386 API::LogManager &logManager = eventWS->mutableRun();
387
388 auto frame_count = static_cast<int>(eventCounter.numFrames());
389
390 logManager.addProperty("filename", nxsFile);
391 logManager.addProperty("att_pos", static_cast<int>(instrumentInfo.att_pos));
392 logManager.addProperty("frame_count", frame_count);
393 logManager.addProperty("period", period);
394
395 // currently beam monitor counts are not available, instead number of frames
396 // times period is used
397 logManager.addProperty("bm_counts", static_cast<double>(frame_count) * period /
398 1.0e6); // static_cast<double>(instrumentInfo.bm_counts)
399
400 Types::Core::time_duration duration =
401 boost::posix_time::microseconds(static_cast<boost::int64_t>(static_cast<double>(frame_count) * period));
402
403 Types::Core::DateAndTime start_time(instrumentInfo.start_time);
404 Types::Core::DateAndTime end_time(start_time + duration);
405
406 logManager.addProperty("start_time", start_time.toISO8601String());
407 logManager.addProperty("run_start", start_time.toISO8601String());
408 logManager.addProperty("end_time", end_time.toISO8601String());
409 logManager.addProperty("is_tof", instrumentInfo.is_tof);
410
411 std::string time_str = start_time.toISO8601String();
412
413 logManager.addProperty("sample_name", instrumentInfo.sample_name);
414 logManager.addProperty("sample_description", instrumentInfo.sample_description);
415 addSinglePointTimeSeriesProperty(logManager, time_str, "wavelength", instrumentInfo.wavelength);
416 addSinglePointTimeSeriesProperty(logManager, time_str, "master1_chopper_id", instrumentInfo.master1_chopper_id);
417 addSinglePointTimeSeriesProperty(logManager, time_str, "master2_chopper_id", instrumentInfo.master2_chopper_id);
418
419 for (auto &x : logStrings) {
420 logManager.addProperty(x.first, x.second);
421 }
422 for (auto &x : logParams) {
423 addSinglePointTimeSeriesProperty(logManager, time_str, x.first, x.second);
424 }
425
426 auto loadInstrumentAlg = createChildAlgorithm("LoadInstrument");
427 loadInstrumentAlg->setProperty("Workspace", eventWS);
428 loadInstrumentAlg->setPropertyValue("InstrumentName", "BILBY");
429 loadInstrumentAlg->setProperty("RewriteSpectraMap", Mantid::Kernel::OptionalBool(false));
430 loadInstrumentAlg->executeAsChildAlg();
431
432 setProperty("OutputWorkspace", eventWS);
433}
434
435// region of intreset
436std::vector<bool> LoadBBY2::createRoiVector(const std::string &maskfile) {
437 std::vector<bool> result(HISTO_BINS_Y * HISTO_BINS_X, true);
438
439 if (maskfile.length() == 0)
440 return result;
441
442 std::ifstream input(maskfile.c_str());
443 if (!input.good())
444 throw std::invalid_argument("invalid mask file");
445
446 std::string line;
447 while (std::getline(input, line)) {
448 auto i0 = line.find("<detids>");
449 auto iN = line.find("</detids>");
450
451 if ((i0 != std::string::npos) && (iN != std::string::npos) && (i0 < iN)) {
452 line = line.substr(i0 + 8, iN - i0 - 8); // 8 = len("<detids>")
453 std::stringstream ss(line);
454
455 std::string item;
456 while (std::getline(ss, item, ',')) {
457 auto k = item.find('-');
458
459 size_t p0, p1;
460 if (k != std::string::npos) {
461 p0 = boost::lexical_cast<size_t>(item.substr(0, k));
462 p1 = boost::lexical_cast<size_t>(item.substr(k + 1, item.size() - k - 1));
463
464 if (p0 > p1)
465 std::swap(p0, p1);
466 } else {
467 p0 = boost::lexical_cast<size_t>(item);
468 p1 = p0;
469 }
470
471 if (p0 < result.size()) {
472 if (p1 >= result.size())
473 p1 = result.size() - 1;
474
475 while (p0 <= p1)
476 result[p0++] = false;
477 }
478 }
479 }
480 }
481
482 return result;
483}
484
485// loading instrument parameters
486void LoadBBY2::loadInstrumentParameters(const Nexus::NXEntry &entry, uint64_t startTime, uint64_t endTime,
487 std::map<std::string, double> &logParams,
488 std::map<std::string, std::string> &logStrings,
489 std::map<std::string, std::string> &allParams) {
490 using namespace Poco::XML;
491 std::string idfDirectory = Mantid::Kernel::ConfigService::Instance().getString("instrumentDefinition.directory");
492
493 try {
494 std::string parameterFilename = idfDirectory + "BILBY_Parameters.xml";
495 // Set up the DOM parser and parse xml file
496 DOMParser pParser;
497 Poco::AutoPtr<Poco::XML::Document> pDoc;
498 try {
499 pDoc = pParser.parse(parameterFilename);
500 } catch (...) {
501 throw Kernel::Exception::FileError("Unable to parse File:", std::move(parameterFilename));
502 }
503 NodeIterator it(pDoc, Poco::XML::NodeFilter::SHOW_ELEMENT);
504 Node *pNode = it.nextNode();
505 while (pNode) {
506 if (pNode->nodeName() == "parameter") {
507 auto pElem = dynamic_cast<Element *>(pNode);
508 std::string paramName = pElem->getAttribute("name");
509 Poco::AutoPtr<NodeList> nodeList = pElem->childNodes();
510 for (unsigned long i = 0; i < nodeList->length(); i++) {
511 auto cNode = nodeList->item(i);
512 if (cNode->nodeName() == "value") {
513 auto cElem = dynamic_cast<Poco::XML::Element *>(cNode);
514 std::string value = cElem->getAttribute("val");
515 allParams[paramName] = std::move(value);
516 }
517 }
518 }
519 pNode = it.nextNode();
520 }
521
522 auto isNumeric = [](const std::string &tag) {
523 try {
524 auto stag = boost::algorithm::trim_copy(tag);
525 size_t sz = 0;
526 auto value = std::stod(stag, &sz);
527 return sz > 0 && stag.size() == sz && std::isfinite(value);
528 } catch (const std::invalid_argument &) {
529 return false;
530 }
531 };
532
533 std::string tmpString;
534 double tmpDouble = 0.0f;
535 uint64_t tmpTimestamp = 0;
536 for (auto &x : allParams) {
537 if (x.first.find("log_") == 0) {
538 auto logTag = boost::algorithm::trim_copy(x.first.substr(4));
539 auto line = x.second;
540
541 // comma separated details
542 std::vector<std::string> details;
543 boost::split(details, line, boost::is_any_of(","));
544 if (details.size() < 3) {
545 g_log.warning() << "Invalid format for BILBY parameter " << x.first << std::endl;
546 continue;
547 }
548 auto hdfTag = boost::algorithm::trim_copy(details[0]);
549 try {
550 // extract the parameter and add it to the parameter dictionary,
551 // check the scale factor for numeric and string
552 auto updateOk = false;
553 if (!hdfTag.empty()) {
554 if (isNumeric(details[1])) {
555 bool baseLoaded = Anxs::loadNXDataSet(entry, hdfTag, tmpDouble, 0);
556 bool timeLoaded = false;
557 if (!baseLoaded) {
558 auto key = (details.size() < 4) ? "mean" : boost::algorithm::trim_copy(details[3]);
559 auto imap = ScanLogMap.find(key);
560 Anxs::ScanLog scanLogMode =
561 (imap != ScanLogMap.end()) ? imap->second : Anxs::ScanLog::Mean; // default value
562 timeLoaded = Anxs::extractTimedDataSet(entry, hdfTag, startTime, endTime, scanLogMode, tmpTimestamp,
563 tmpDouble, tmpString);
564 }
565 if (baseLoaded || timeLoaded) {
566 auto factor = std::stod(details[1]);
567 logParams[logTag] = factor * tmpDouble;
568 updateOk = true;
569 if (timeLoaded) {
570 traceStatistics<double>(entry, hdfTag, startTime, endTime, g_log);
571 }
572 }
573 } else if (Anxs::loadNXString(entry, hdfTag, tmpString)) {
574 logStrings[logTag] = tmpString;
575 updateOk = true;
576 }
577 }
578 if (!updateOk) {
579 // if the hdf is missing the tag then add the default if
580 // it is provided
581 auto defValue = boost::algorithm::trim_copy(details[2]);
582 if (!defValue.empty()) {
583 if (isNumeric(defValue))
584 logParams[logTag] = std::stod(defValue);
585 else
586 logStrings[logTag] = std::move(defValue);
587 if (!hdfTag.empty())
588 g_log.warning() << "Cannot find hdf parameter " << hdfTag << ", using default.\n";
589 }
590 }
591 } catch (const std::invalid_argument &) {
592 g_log.warning() << "Invalid format for BILBY parameter " << x.first << std::endl;
593 }
594 }
595 }
596 } catch (std::exception &ex) {
597 g_log.warning() << "Failed to load instrument with error: " << ex.what()
598 << ". The current facility may not be fully "
599 "supported.\n";
600 }
601}
602
603// instrument creation
604void LoadBBY2::createInstrument(const Nexus::NXEntry &entry, uint64_t startTime, uint64_t endTime,
605 InstrumentInfo &instrumentInfo, std::map<std::string, double> &logParams,
606 std::map<std::string, std::string> &logStrings,
607 std::map<std::string, std::string> &allParams) {
608
609 instrumentInfo.sample_name = "UNKNOWN";
610 instrumentInfo.sample_description = "UNKNOWN";
611 instrumentInfo.start_time = "2000-01-01T00:00:00";
612
613 instrumentInfo.bm_counts = 0;
614 instrumentInfo.att_pos = 0;
615 instrumentInfo.master1_chopper_id = -1;
616 instrumentInfo.master2_chopper_id = -1;
617
618 instrumentInfo.is_tof = true;
619 instrumentInfo.wavelength = 0.0;
620
621 instrumentInfo.period_master = 0.0;
622 instrumentInfo.period_slave = (1.0 / 50.0) * 1.0e6;
623 instrumentInfo.phase_slave = 0.0;
624
625 double tmp_double = 0.0f;
626 int64_t tmp_int64 = 0;
627 uint64_t tmp_timestamp = 0;
628 std::string tmp_str;
629
630 if (Anxs::loadNXDataSet(entry, "monitor/bm1_counts/value", tmp_int64, LAST_INDEX))
631 instrumentInfo.bm_counts = tmp_int64;
632 if (Anxs::loadNXDataSet(entry, "instrument/att_pos/value", tmp_double, LAST_INDEX))
633 instrumentInfo.att_pos = boost::math::iround(tmp_double); // [1.0, 2.0, ..., 5.0]
634
635 if (Anxs::loadNXString(entry, "sample/name", tmp_str))
636 instrumentInfo.sample_name = tmp_str;
637 if (Anxs::loadNXString(entry, "sample/description", tmp_str))
638 instrumentInfo.sample_description = tmp_str;
639
640 uint64_t epochStart{0};
641 auto timeTag = (useHMScanTime ? "hmscan/time" : "scan_dataset/time");
642 if (Anxs::loadNXDataSet(entry, timeTag, epochStart, 0)) {
643 Types::Core::DateAndTime startDateTime(Anxs::epochRelDateTimeBase(epochStart));
644 instrumentInfo.start_time = startDateTime.toISO8601String();
645 }
646
647 if (Anxs::loadNXDataSet(entry, "instrument/master1_chopper_id", tmp_int64, 0))
648 instrumentInfo.master1_chopper_id = tmp_int64;
649 if (Anxs::loadNXDataSet(entry, "instrument/master2_chopper_id", tmp_int64, 0))
650 instrumentInfo.master2_chopper_id = tmp_int64;
651
652 if (Anxs::loadNXString(entry, "instrument/detector/frame_source", tmp_str))
653 instrumentInfo.is_tof = tmp_str == "EXTERNAL";
654
655 if (Anxs::extractTimedDataSet(entry, "instrument/nvs067/lambda", startTime, endTime, Anxs::ScanLog::Mean,
656 tmp_timestamp, tmp_double, tmp_str))
657 instrumentInfo.wavelength = tmp_double;
658
659 if (Anxs::extractTimedDataSet(entry, "instrument/master_chopper_freq", startTime, endTime, Anxs::ScanLog::Mean,
660 tmp_timestamp, tmp_double, tmp_str) &&
661 (tmp_double > 0.0f))
662 instrumentInfo.period_master = 1.0 / tmp_double * 1.0e6;
663
664 if (Anxs::extractTimedDataSet(entry, "instrument/t0_chopper_freq", startTime, endTime, Anxs::ScanLog::Mean,
665 tmp_timestamp, tmp_double, tmp_str) &&
666 (tmp_double > 0.0f))
667 instrumentInfo.period_slave = 1.0 / tmp_double * 1.0e6;
668
669 if (Anxs::extractTimedDataSet(entry, "instrument/t0_chopper_phase", startTime, endTime, Anxs::ScanLog::Mean,
670 tmp_timestamp, tmp_double, tmp_str))
671 instrumentInfo.phase_slave = tmp_double < 999.0 ? tmp_double : 0.0;
672
673 // addnl trace message if needed
674 traceStatistics<double>(entry, "instrument/nvs067/lambda", startTime, endTime, g_log);
675 traceStatistics<double>(entry, "instrument/master_chopper_freq", startTime, endTime, g_log);
676 traceStatistics<double>(entry, "instrument/t0_chopper_freq", startTime, endTime, g_log);
677 traceStatistics<double>(entry, "instrument/t0_chopper_phase", startTime, endTime, g_log);
678
679 loadInstrumentParameters(entry, startTime, endTime, logParams, logStrings, allParams);
680
681 // Ltof_det_value is not present for monochromatic data so check
682 // and replace with default
683 auto findLtof = logParams.find("Ltof_det_value");
684 if (findLtof != logParams.end()) {
685 logParams["L1_chopper_value"] = logParams["Ltof_det_value"] - logParams["L2_det_value"];
686 } else {
687 logParams["L1_chopper_value"] = 18.4726;
688 g_log.warning() << "Cannot recover parameter 'L1_chopper_value'"
689 << ", using default.\n";
690 }
691}
692
693} // namespace Mantid::DataHandling
std::string name
Definition Run.cpp:60
double value
The value of the point.
Definition FitMW.cpp:51
#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.
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
@ OptionalLoad
to specify a file to read but the file doesn't have to exist
@ Load
allowed here which will be passed to the algorithm
void setDetectorID(const detid_t detID)
Clear the list of detector IDs, then add one.
Definition ISpectrum.cpp:84
void setSpectrumNo(specnum_t num)
Sets the spectrum number of this spectrum.
This class contains the information about the log entries.
Definition LogManager.h:44
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
Definition LogManager.h:91
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) override
Create a Child Algorithm.
Helper class for reporting progress from algorithms.
Definition Progress.h:25
void doReport(const std::string &msg="") override
Actually do the reporting, without changing the loop counter.
Definition Progress.cpp:70
A property class for workspaces.
helper class to keep track of progress
int confidence(Nexus::NexusDescriptor &descriptor) const override
Return the confidence value that this algorithm can load the file.
Definition LoadBBY2.cpp:143
LoadBBY2()
Empty default constructor.
Definition LoadBBY2.cpp:135
void loadInstrumentParameters(const Nexus::NXEntry &entry, uint64_t startTime, uint64_t endTime, std::map< std::string, double > &logParams, std::map< std::string, std::string > &logStrings, std::map< std::string, std::string > &allParams)
Definition LoadBBY2.cpp:486
void init() override
Initialise the algorithm.
Definition LoadBBY2.cpp:171
void createInstrument(const Nexus::NXEntry &entry, uint64_t startTime, uint64_t endTime, InstrumentInfo &instrumentInfo, std::map< std::string, double > &logParams, std::map< std::string, std::string > &logStrings, std::map< std::string, std::string > &allParams)
Definition LoadBBY2.cpp:604
void execLoader() override
Execute the algorithm.
Definition LoadBBY2.cpp:230
static std::vector< bool > createRoiVector(const std::string &maskfile)
Definition LoadBBY2.cpp:436
A class for holding :
Definition EventList.h:57
void setSortOrder(const EventSortType order) const
Manually set the event list sort order value.
void reserve(size_t num) override
Reserve a certain number of entries in event list of the specified eventType.
Records the filename and the description of failure.
Definition Exception.h:98
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertyGroup(const std::string &name, const std::string &group)
Set the group for a given property.
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 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
bool isDebug() const
Returns true if log level is at least debug.
Definition Logger.cpp:189
OptionalBool : Tri-state bool.
The concrete, templated class for properties.
A specialised Property class for holding a series of time-value pairs.
Implements NXentry Nexus class.
Implements NXroot Nexus class.
NXEntry openFirstEntry()
Open the first NXentry in the file.
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::string extractWorkspaceTitle(const std::string &nxsFile)
void ReadEventData(ProgressTracker &prog, const Nexus::NXEntry &entry, EventProcessor *handler, uint64_t start_nsec, uint64_t end_nsec, const std::string &neutron_path, int tube_resolution=1024)
bool loadNXString(const Nexus::NXEntry &entry, const std::string &path, std::string &value)
int64_t epochRelDateTimeBase(int64_t epochInNanoSeconds)
bool loadNXDataSet(const Nexus::NXEntry &entry, const std::string &path, T &value, int index)
std::pair< uint64_t, uint64_t > getHMScanLimits(const Nexus::NXEntry &entry, int datasetIx)
uint64_t extractTimedDataSet(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime, uint64_t endTime, std::vector< uint64_t > &times, std::vector< T > &events, std::string &units)
std::pair< uint64_t, uint64_t > getTimeScanLimits(const Nexus::NXEntry &entry, int datasetIx)
std::vector< Types::Event::TofEvent > * EventVector_pt
pointer to the vector of events
static char const *const FilenameStr
Definition LoadBBY.cpp:55
static char const *const FilterByTofMaxStr
Definition LoadBBY.cpp:59
static const size_t HISTO_BINS_X
Definition LoadBBY.cpp:48
static const size_t HISTO_BINS_Y
Definition LoadBBY.cpp:49
static const size_t Progress_LoadBinFile
Definition LoadBBY.cpp:51
void addSinglePointTimeSeriesProperty(API::LogManager &logManager, const std::string &time, const std::string &name, const TYPE value)
Definition LoadBBY2.cpp:109
static char const *const FilterByTofMinStr
Definition LoadBBY.cpp:58
void loadEvents(API::Progress &prog, const char *progMsg, EP &eventProcessor, const Nexus::NXEntry &entry, uint64_t start_nsec, uint64_t end_nsec)
Definition LoadBBY2.cpp:120
void traceStatistics(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime, uint64_t endTime, Kernel::Logger &log)
Definition LoadBBY2.cpp:82
static char const *const MaskStr
Definition LoadBBY.cpp:56
static char const *const FilterByTimeStartStr
Definition LoadBBY.cpp:61
static const size_t Progress_Total
Definition LoadBBY.cpp:53
static char const *const UseHMScanTimeStr
Definition LoadBBY2.cpp:73
static const std::map< std::string, Anxs::ScanLog > ScanLogMap
Definition LoadBBY2.cpp:78
static char const *const FilterByTimeStopStr
Definition LoadBBY.cpp:62
static const size_t Progress_ReserveMemory
Definition LoadBBY.cpp:52
static const int LAST_INDEX
Definition LoadBBY2.cpp:56
DLLExport void getEventsFrom(EventList &el, std::vector< Types::Event::TofEvent > *&events)
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
int32_t detid_t
Typedef for a detector ID.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition EmptyValues.h:42
STL namespace.
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54