Mantid
Loading...
Searching...
No Matches
LoadILLSANS.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"
12#include "MantidAPI/Progress.h"
14#include "MantidAPI/Run.h"
21#include "MantidHistogramData/LinearGenerator.h"
29
30#include <Poco/Path.h>
31
32namespace Mantid::DataHandling {
33
34using namespace Kernel;
35using namespace API;
36using namespace NeXus;
37
39
40//----------------------------------------------------------------------------------------------
44 : m_supportedInstruments{"D11", "D22", "D33", "D16"}, m_defaultBinning{0, 0}, m_resMode("nominal"), m_isTOF(false),
45 m_sourcePos(0.) {}
46
47//----------------------------------------------------------------------------------------------
49const std::string LoadILLSANS::name() const { return "LoadILLSANS"; }
50
52int LoadILLSANS::version() const { return 1; }
53
55const std::string LoadILLSANS::category() const { return "DataHandling\\Nexus;ILL\\SANS"; }
56
58const std::string LoadILLSANS::summary() const {
59 return "Loads ILL nexus files for SANS instruments D11, D16, D22, D33.";
60}
61
62//----------------------------------------------------------------------------------------------
63
71 // fields existent only at the ILL for SANS machines
72 if (descriptor.pathExists("/entry0/mode") &&
73 ((descriptor.pathExists("/entry0/reactor_power") && descriptor.pathExists("/entry0/instrument_name")) ||
74 (descriptor.pathExists("/entry0/instrument/name") && descriptor.pathExists("/entry0/acquisition_mode") &&
75 !descriptor.pathExists("/entry0/instrument/Detector")))) // serves to remove the TOF instruments
76 {
77 return 80;
78 } else {
79 return 0;
80 }
81}
82
83//----------------------------------------------------------------------------------------------
87 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, ".nxs"),
88 "Name of the nexus file to load");
89 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
90 "The name to use for the output workspace");
91 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
92 mustBePositive->setLower(0);
93 declareProperty("Wavelength", 0.0, mustBePositive,
94 "The wavelength of the experiment, in angstroms. Used only for D16. Will "
95 "override the nexus' value if there is one.");
96}
97
98//----------------------------------------------------------------------------------------------
102 const std::string filename = getPropertyValue("Filename");
103 m_isD16Omega = false;
104 NXRoot root(filename);
105 NXEntry firstEntry = root.openFirstEntry();
106 const std::string instrumentPath = LoadHelper::findInstrumentNexusPath(firstEntry);
107 setInstrumentName(firstEntry, instrumentPath);
109 Progress progress(this, 0.0, 1.0, 4);
110 progress.report("Initializing the workspace for " + m_instrumentName);
111 if (m_instrumentName == "D33") {
112 initWorkSpaceD33(firstEntry, instrumentPath);
113 progress.report("Loading the instrument " + m_instrumentName);
115 const DetectorPosition detPos = getDetectorPositionD33(firstEntry, instrumentPath);
116 progress.report("Moving detectors");
117 moveDetectorsD33(detPos);
118 if (m_isTOF) {
119 adjustTOF();
120 moveSource();
121 }
122
123 } else if (m_instrumentName == "D16") {
124 initWorkSpace(firstEntry, instrumentPath);
125 progress.report("Loading the instrument " + m_instrumentName);
127
128 double distance;
129 try {
130 distance = firstEntry.getFloat(instrumentPath + "/Det/value") / 1000; // mm to metre
131 } catch (std::runtime_error &) {
132 distance = 0;
133 }
134 const double angle = firstEntry.getFloat(instrumentPath + "/Gamma/value");
135 placeD16(-angle, distance, "detector");
136
137 } else if (m_instrumentName == "D11B") {
138 initWorkSpaceD11B(firstEntry, instrumentPath);
139 progress.report("Loading the instrument " + m_instrumentName);
141
142 // we move the parent "detector" component, but since it is at (0,0,0), we
143 // need to find the distance it has to move and move it to this position
144 double finalDistance = firstEntry.getFloat(instrumentPath + "/Detector 1/det_calc");
145 V3D pos = getComponentPosition("detector_center");
146 double currentDistance = pos.Z();
147
148 moveDetectorDistance(finalDistance - currentDistance, "detector");
149 API::Run &runDetails = m_localWorkspace->mutableRun();
150 runDetails.addProperty<double>("L2", finalDistance, true);
151
152 } else if (m_instrumentName == "D22B") {
153 initWorkSpaceD22B(firstEntry, instrumentPath);
154
155 const std::string backIndex = m_localWorkspace->getInstrument()->getStringParameter("back_detector_index")[0];
156 const std::string frontIndex = m_localWorkspace->getInstrument()->getStringParameter("front_detector_index")[0];
157
158 // first we move the central (back) detector
159 double distance = firstEntry.getFloat(instrumentPath + "/Detector " + backIndex + "/det" + backIndex + "_calc");
160 moveDetectorDistance(distance, "detector_back");
161 API::Run &runDetails = m_localWorkspace->mutableRun();
162 runDetails.addProperty<double>("L2", distance, true);
163
164 double offset = firstEntry.getFloat(instrumentPath + "/Detector " + backIndex + "/dtr" + backIndex + "_actual");
165 moveDetectorHorizontal(-offset / 1000, "detector_back"); // mm to meter
166
167 // then the front (right) one
168 distance = firstEntry.getFloat(instrumentPath + "/Detector " + frontIndex + "/det" + frontIndex + "_calc");
169 moveDetectorDistance(distance, "detector_front");
170
171 // mm to meter
172 offset = firstEntry.getFloat(instrumentPath + "/Detector " + frontIndex + "/dtr" + frontIndex + "_actual");
173 moveDetectorHorizontal(-offset / 1000, "detector_front"); // mm to meter
174 double angle = firstEntry.getFloat(instrumentPath + "/Detector " + frontIndex + "/dan" + frontIndex + "_actual");
175 rotateInstrument(-angle, "detector_front");
176
177 } else {
178 // D11 and D22
179 initWorkSpace(firstEntry, instrumentPath);
180 progress.report("Loading the instrument " + m_instrumentName);
182 double distance = LoadHelper::getDoubleFromNexusPath(firstEntry, instrumentPath + "/detector/det_calc");
183 progress.report("Moving detectors");
184 moveDetectorDistance(distance, "detector");
185 API::Run &runDetails = m_localWorkspace->mutableRun();
186 runDetails.addProperty<double>("L2", distance, true);
187 if (m_instrumentName == "D22") {
188 double offset = LoadHelper::getDoubleFromNexusPath(firstEntry, instrumentPath + "/detector/dtr_actual");
189 moveDetectorHorizontal(-offset / 1000, "detector"); // mm to meter
190 }
191 }
192
193 progress.report("Setting sample logs");
194 setFinalProperties(filename);
195 setProperty("OutputWorkspace", m_localWorkspace);
196}
197
203void LoadILLSANS::setInstrumentName(const NeXus::NXEntry &firstEntry, const std::string &instrumentNamePath) {
204 if (instrumentNamePath.empty()) {
205 throw std::runtime_error("Cannot set the instrument name from the Nexus file!");
206 }
207 m_instrumentName = LoadHelper::getStringFromNexusPath(firstEntry, instrumentNamePath + "/name");
208 const auto inst = std::find(m_supportedInstruments.begin(), m_supportedInstruments.end(), m_instrumentName);
209
210 // set alternative version name. Note that D16B is set later, because we need to open the data to distinguish with D16
211 if ((m_instrumentName == "D11" || m_instrumentName == "D22") && firstEntry.containsGroup("data1")) {
212 m_instrumentName += "B";
213 }
214
215 if (inst == m_supportedInstruments.end()) {
216 throw std::runtime_error("Instrument " + m_instrumentName +
217 " is not supported. Only D11, D16, D22 and D33 are supported");
218 }
219 g_log.debug() << "Instrument name set to: " + m_instrumentName << '\n';
220}
221
229 const std::string &instrumentNamePath) {
230 std::string detectorPath(instrumentNamePath + "/detector");
232 pos.distanceSampleRear = LoadHelper::getDoubleFromNexusPath(firstEntry, detectorPath + "/det2_calc");
233 pos.distanceSampleBottomTop = LoadHelper::getDoubleFromNexusPath(firstEntry, detectorPath + "/det1_calc");
235 LoadHelper::getDoubleFromNexusPath(firstEntry, detectorPath + "/det1_panel_separation");
236 pos.shiftLeft = LoadHelper::getDoubleFromNexusPath(firstEntry, detectorPath + "/OxL_actual") * 1e-3;
237 pos.shiftRight = LoadHelper::getDoubleFromNexusPath(firstEntry, detectorPath + "/OxR_actual") * 1e-3;
238 pos.shiftUp = LoadHelper::getDoubleFromNexusPath(firstEntry, detectorPath + "/OyT_actual") * 1e-3;
239 pos.shiftDown = LoadHelper::getDoubleFromNexusPath(firstEntry, detectorPath + "/OyB_actual") * 1e-3;
240 pos >> g_log.debug();
241 return pos;
242}
243
249
258void LoadILLSANS::getDataDimensions(const NeXus::NXInt &data, int &numberOfChannels, int &numberOfTubes,
259 int &numberOfPixelsPerTube) {
260 if (m_isD16Omega) {
261 numberOfChannels = data.dim0();
262 numberOfTubes = data.dim1();
263 numberOfPixelsPerTube = data.dim2();
264 } else {
265 numberOfPixelsPerTube = data.dim1();
266 numberOfChannels = data.dim2();
267 numberOfTubes = data.dim0();
268 }
269 g_log.debug() << "Dimensions found:\n- Number of tubes: " << numberOfTubes
270 << "\n- Number of pixels per tube: " << numberOfPixelsPerTube
271 << "\n- Number of channels: " << numberOfChannels << "\n";
272}
273
279void LoadILLSANS::initWorkSpace(NeXus::NXEntry &firstEntry, const std::string &instrumentPath) {
280 g_log.debug("Fetching data...");
281 std::string path;
282 if (firstEntry.containsGroup("data")) {
283 path = "data";
284 } else {
285 path = "data_scan/detector_data/data";
286 }
287 NXData dataGroup = firstEntry.openNXData(path);
288 NXInt data = dataGroup.openIntData();
289 data.load();
290 size_t numberOfHistograms;
291
292 // determine if the data comes from a D16 scan
293 m_isD16Omega = (data.dim0() >= 1 && data.dim2() > 1 && m_instrumentName == "D16");
294
295 if (m_instrumentName == "D16") {
296 const size_t numberOfWiresInD16B = 1152;
297 const size_t numberOfPixelsPerWireInD16B = 192;
298
299 // Check if the instrument loaded is D16B. It cannot be differentiated from D16 by the structure of the nexus file
300 // only, so we need to check the data size.
301 if (data.dim1() == numberOfWiresInD16B && data.dim2() == numberOfPixelsPerWireInD16B) {
302 m_instrumentName = "D16B";
303 m_isD16Omega = true;
304 setNumberOfMonitors(); // update the number of monitors now that the instrument changed.
305 }
306 }
307
308 int numberOfTubes, numberOfPixelsPerTubes, numberOfChannels;
309 getDataDimensions(data, numberOfChannels, numberOfTubes, numberOfPixelsPerTubes);
310
311 // For these monochromatic instruments, one bin is "TOF" mode, and more than that is a scan
312 MultichannelType type = (numberOfChannels == 1) ? MultichannelType::TOF : MultichannelType::SCAN;
313
314 numberOfHistograms = numberOfPixelsPerTubes * numberOfTubes + m_numberOfMonitors;
315
316 createEmptyWorkspace(numberOfHistograms, numberOfChannels, type);
317 loadMetaData(firstEntry, instrumentPath);
318
319 std::vector<double> binning = m_isD16Omega && numberOfChannels > 1
320 ? getOmegaBinning(firstEntry, "data_scan/scanned_variables/data")
322
323 size_t nextIndex;
324 nextIndex = loadDataFromTubes(data, binning, 0);
325 if (!m_isD16Omega || data.dim0() == 1) { // second condition covers legacy D16 omega scans with single scan point
326 loadDataFromMonitors(firstEntry, nextIndex);
327 } else
328 loadDataFromD16ScanMonitors(firstEntry, nextIndex, binning);
329
330 if (data.dim1() == 128) {
331 m_resMode = "low";
332 }
333}
334
340void LoadILLSANS::initWorkSpaceD11B(NeXus::NXEntry &firstEntry, const std::string &instrumentPath) {
341 g_log.debug("Fetching data...");
342
343 NXData data1 = firstEntry.openNXData("D11/Detector 1/data");
344 NXInt dataCenter = data1.openIntData();
345 dataCenter.load();
346 NXData data2 = firstEntry.openNXData("D11/Detector 2/data");
347 NXInt dataLeft = data2.openIntData();
348 dataLeft.load();
349 NXData data3 = firstEntry.openNXData("D11/Detector 3/data");
350 NXInt dataRight = data3.openIntData();
351 dataRight.load();
352
353 size_t numberOfHistograms =
354 static_cast<size_t>(dataCenter.dim0() * dataCenter.dim1() + dataRight.dim0() * dataRight.dim1() +
355 dataLeft.dim0() * dataLeft.dim1()) +
357
358 int numberOfChannels, numberOfPixelsPerTubeCenter, numberOfTubesCenter;
359 getDataDimensions(dataCenter, numberOfChannels, numberOfTubesCenter, numberOfPixelsPerTubeCenter);
360
361 MultichannelType type = (numberOfChannels != 1) ? MultichannelType::KINETIC : MultichannelType::TOF;
362 createEmptyWorkspace(numberOfHistograms, numberOfChannels, type);
363 loadMetaData(firstEntry, instrumentPath);
364
365 // we need to adjust the default binning after loadmetadata
366 if (numberOfChannels != 1) {
367 std::vector<double> frames(numberOfChannels, 0);
368 for (int i = 0; i < numberOfChannels; ++i) {
369 frames[i] = i;
370 }
371 m_defaultBinning.resize(numberOfChannels);
372 std::copy(frames.cbegin(), frames.cend(), m_defaultBinning.begin());
373 }
374
375 size_t nextIndex;
376 nextIndex = loadDataFromTubes(dataCenter, m_defaultBinning, 0, type);
377 nextIndex = loadDataFromTubes(dataLeft, m_defaultBinning, nextIndex, type);
378 nextIndex = loadDataFromTubes(dataRight, m_defaultBinning, nextIndex, type);
379 nextIndex = loadDataFromMonitors(firstEntry, nextIndex, type);
380
381 if (numberOfChannels != 1) {
382 // there are a few runs with no 2nd monitor in kinetic, so we load the first monitor once again to preserve the
383 // dimensions and x-axis
384 if (nextIndex < numberOfHistograms)
385 nextIndex = loadDataFromMonitors(firstEntry, nextIndex, type);
386
387 // hijack the second monitor spectrum to store per-frame durations to enable time normalisation
388 NXFloat durations = firstEntry.openNXFloat("slices");
389 durations.load();
390 const HistogramData::Counts histoCounts(durations(), durations() + numberOfChannels);
391 m_localWorkspace->setCounts(nextIndex - 1, histoCounts);
392 m_localWorkspace->setCountVariances(nextIndex - 1,
393 HistogramData::CountVariances(std::vector<double>(numberOfChannels, 0)));
394 }
395}
396
402void LoadILLSANS::initWorkSpaceD22B(NeXus::NXEntry &firstEntry, const std::string &instrumentPath) {
403 g_log.debug("Fetching data...");
404
405 NXData data1 = firstEntry.openNXData("data1");
406 NXInt data1_data = data1.openIntData();
407 data1_data.load();
408 NXData data2 = firstEntry.openNXData("data2");
409 NXInt data2_data = data2.openIntData();
410 data2_data.load();
411
412 size_t numberOfHistograms =
413 static_cast<size_t>(data2_data.dim0() * data2_data.dim1() + data1_data.dim0() * data1_data.dim1()) +
415
416 int numberOfChannels, numberOfPixelsPerTubeCenter, numberOfTubesCenter;
417 getDataDimensions(data1_data, numberOfChannels, numberOfTubesCenter, numberOfPixelsPerTubeCenter);
418
419 MultichannelType type = (numberOfChannels != 1) ? MultichannelType::KINETIC : MultichannelType::TOF;
420
421 createEmptyWorkspace(numberOfHistograms, numberOfChannels, type);
422 loadMetaData(firstEntry, instrumentPath);
423
424 // we need to adjust the default binning after loadmetadata
425 if (numberOfChannels != 1) {
426 std::vector<double> frames(numberOfChannels, 0);
427 for (int i = 0; i < numberOfChannels; ++i) {
428 frames[i] = i;
429 }
430 m_defaultBinning.resize(numberOfChannels);
431 std::copy(frames.cbegin(), frames.cend(), m_defaultBinning.begin());
432 }
433
435
436 const std::string backIndex = m_localWorkspace->getInstrument()->getStringParameter("back_detector_index")[0];
437 size_t nextIndex;
438 if (backIndex == "2") {
439 nextIndex = loadDataFromTubes(data2_data, m_defaultBinning, 0, type);
440 nextIndex = loadDataFromTubes(data1_data, m_defaultBinning, nextIndex, type);
441 } else {
442 nextIndex = loadDataFromTubes(data1_data, m_defaultBinning, 0, type);
443 nextIndex = loadDataFromTubes(data2_data, m_defaultBinning, nextIndex, type);
444 }
445 nextIndex = loadDataFromMonitors(firstEntry, nextIndex, type);
446
447 // hijack the second monitor spectrum to store per-frame durations to enable time normalisation
448 if (numberOfChannels != 1) {
449 NXFloat durations = firstEntry.openNXFloat("slices");
450 durations.load();
451 const HistogramData::Counts histoCounts(durations(), durations() + numberOfChannels);
452 m_localWorkspace->setCounts(nextIndex - 1, std::move(histoCounts));
453 m_localWorkspace->setCountVariances(nextIndex - 1,
454 HistogramData::CountVariances(std::vector<double>(numberOfChannels, 0)));
455 }
456}
457
463void LoadILLSANS::initWorkSpaceD33(NeXus::NXEntry &firstEntry, const std::string &instrumentPath) {
464
465 g_log.debug("Fetching data...");
466
467 NXData dataGroup1 = firstEntry.openNXData("data1");
468 NXInt dataRear = dataGroup1.openIntData();
469 dataRear.load();
470 NXData dataGroup2 = firstEntry.openNXData("data2");
471 NXInt dataRight = dataGroup2.openIntData();
472 dataRight.load();
473 NXData dataGroup3 = firstEntry.openNXData("data3");
474 NXInt dataLeft = dataGroup3.openIntData();
475 dataLeft.load();
476 NXData dataGroup4 = firstEntry.openNXData("data4");
477 NXInt dataDown = dataGroup4.openIntData();
478 dataDown.load();
479 NXData dataGroup5 = firstEntry.openNXData("data5");
480 NXInt dataUp = dataGroup5.openIntData();
481 dataUp.load();
482 g_log.debug("Checking channel numbers...");
483
484 // check number of channels
485 if (dataRear.dim2() != dataRight.dim2() && dataRight.dim2() != dataLeft.dim2() &&
486 dataLeft.dim2() != dataDown.dim2() && dataDown.dim2() != dataUp.dim2()) {
487 throw std::runtime_error("The time bins have not the same dimension for all the 5 detectors!");
488 }
489 const auto numberOfHistograms = static_cast<size_t>(
490 dataRear.dim0() * dataRear.dim1() + dataRight.dim0() * dataRight.dim1() + dataLeft.dim0() * dataLeft.dim1() +
491 dataDown.dim0() * dataDown.dim1() + dataUp.dim0() * dataUp.dim1());
492
493 g_log.debug("Creating empty workspace...");
494 createEmptyWorkspace(numberOfHistograms + m_numberOfMonitors, static_cast<size_t>(dataRear.dim2()));
495
496 loadMetaData(firstEntry, instrumentPath);
497
498 std::vector<double> binningRear, binningRight, binningLeft, binningDown, binningUp;
499
500 if (firstEntry.getFloat("mode") == 0.0) { // Not TOF
501 g_log.debug("Getting default wavelength bins...");
502 binningRear = m_defaultBinning;
503 binningRight = m_defaultBinning;
504 binningLeft = m_defaultBinning;
505 binningDown = m_defaultBinning;
506 binningUp = m_defaultBinning;
507
508 } else { // TOF
509 m_isTOF = true;
510 NXInt masterPair = firstEntry.openNXInt(m_instrumentName + "/tof/master_pair");
511 masterPair.load();
512
513 const std::string first = std::to_string(masterPair[0]);
514 const std::string second = std::to_string(masterPair[1]);
515 g_log.debug("Master choppers are " + first + " and " + second);
516
517 NXFloat firstChopper = firstEntry.openNXFloat(m_instrumentName + "/chopper" + first + "/sample_distance");
518 firstChopper.load();
519 NXFloat secondChopper = firstEntry.openNXFloat(m_instrumentName + "/chopper" + second + "/sample_distance");
520 secondChopper.load();
521 m_sourcePos = (firstChopper[0] + secondChopper[0]) / 2.;
522 g_log.debug("Source distance computed, moving moderator to Z=-" + std::to_string(m_sourcePos));
523 g_log.debug("Getting wavelength bins from the nexus file...");
524 bool vtof = true;
525 // try VTOF mode
526 try {
527 NXInt channelWidthSum = firstEntry.openNXInt(m_instrumentName + "/tof/chwidth_sum");
528 NXFloat channelWidthTimes = firstEntry.openNXFloat(m_instrumentName + "/tof/chwidth_times");
529 channelWidthSum.load();
530 channelWidthTimes.load();
531 std::string distancePrefix(instrumentPath + "/tof/tof_distance_detector");
532 binningRear = getVariableTimeBinning(firstEntry, distancePrefix + "1", channelWidthSum, channelWidthTimes);
533 binningRight = getVariableTimeBinning(firstEntry, distancePrefix + "2", channelWidthSum, channelWidthTimes);
534 binningLeft = getVariableTimeBinning(firstEntry, distancePrefix + "3", channelWidthSum, channelWidthTimes);
535 binningDown = getVariableTimeBinning(firstEntry, distancePrefix + "4", channelWidthSum, channelWidthTimes);
536 binningUp = getVariableTimeBinning(firstEntry, distancePrefix + "5", channelWidthSum, channelWidthTimes);
537 } catch (const std::runtime_error &) {
538 vtof = false;
539 }
540 if (!vtof) {
541 try {
542 // LTOF mode
543 std::string binPathPrefix(instrumentPath + "/tof/tof_wavelength_detector");
544 binningRear = LoadHelper::getTimeBinningFromNexusPath(firstEntry, binPathPrefix + "1");
545 binningRight = LoadHelper::getTimeBinningFromNexusPath(firstEntry, binPathPrefix + "2");
546 binningLeft = LoadHelper::getTimeBinningFromNexusPath(firstEntry, binPathPrefix + "3");
547 binningDown = LoadHelper::getTimeBinningFromNexusPath(firstEntry, binPathPrefix + "4");
548 binningUp = LoadHelper::getTimeBinningFromNexusPath(firstEntry, binPathPrefix + "5");
549 } catch (std::runtime_error &e) {
550 throw std::runtime_error("Unable to load the wavelength axes for TOF data " + std::string(e.what()));
551 }
552 }
553 }
554
555 g_log.debug("Loading the data into the workspace...");
556
557 size_t nextIndex = loadDataFromTubes(dataRear, binningRear, 0);
558 nextIndex = loadDataFromTubes(dataRight, binningRight, nextIndex);
559 nextIndex = loadDataFromTubes(dataLeft, binningLeft, nextIndex);
560 nextIndex = loadDataFromTubes(dataDown, binningDown, nextIndex);
561 nextIndex = loadDataFromTubes(dataUp, binningUp, nextIndex);
562 loadDataFromMonitors(firstEntry, nextIndex);
563}
564
572size_t LoadILLSANS::loadDataFromMonitors(NeXus::NXEntry &firstEntry, size_t firstIndex, const MultichannelType type) {
573
574 // let's find the monitors; should be monitor1 and monitor2
575 for (std::vector<NXClassInfo>::const_iterator it = firstEntry.groups().begin(); it != firstEntry.groups().end();
576 ++it) {
577 if (it->nxclass == "NXmonitor") {
578 NXData dataGroup = firstEntry.openNXData(it->nxname);
579 NXInt data = dataGroup.openIntData();
580 data.load();
581 g_log.debug() << "Monitor: " << it->nxname << " dims = " << data.dim0() << "x" << data.dim1() << "x"
582 << data.dim2() << '\n';
583 const HistogramData::Counts histoCounts(data(), data() + data.dim2());
584 m_localWorkspace->setCounts(firstIndex, histoCounts);
585 const HistogramData::CountVariances histoVariances(data(), data() + data.dim2());
586 m_localWorkspace->setCountVariances(firstIndex, histoVariances);
587
588 if (m_isTOF) {
589 HistogramData::BinEdges histoBinEdges(data.dim2() + 1, HistogramData::LinearGenerator(0.0, 1));
590 m_localWorkspace->setBinEdges(firstIndex, std::move(histoBinEdges));
591 } else {
592 if (type != MultichannelType::KINETIC) {
593 HistogramData::BinEdges histoBinEdges = HistogramData::BinEdges(m_defaultBinning);
594 m_localWorkspace->setBinEdges(firstIndex, std::move(histoBinEdges));
595 } else {
596 HistogramData::Points histoPoints = HistogramData::Points(m_defaultBinning);
597 m_localWorkspace->setPoints(firstIndex, std::move(histoPoints));
598 }
599 }
600 // Add average monitor counts to a property:
601 double averageMonitorCounts =
602 std::accumulate(data(), data() + data.dim2(), double(0)) / static_cast<double>(data.dim2());
603 // make sure the monitor has values!
604 if (averageMonitorCounts > 0) {
605 API::Run &runDetails = m_localWorkspace->mutableRun();
606 runDetails.addProperty("monitor", averageMonitorCounts, true);
607 }
608 firstIndex++;
609 }
610 }
611 return firstIndex;
612}
613
622size_t LoadILLSANS::loadDataFromD16ScanMonitors(const NeXus::NXEntry &firstEntry, size_t firstIndex,
623 const std::vector<double> &binning) {
624 std::string path = "/data_scan/scanned_variables/data";
625
626 // the monitor is the fourth scanned variable
627 // we could verify that by reading the /data_scan/scanned_variables/variable_names/name entry, if only nexus knew how
628 // to read string arrays.
629 uint32_t monitorIndex = 3;
630
631 NXData scannedVariablesData = firstEntry.openNXData(path);
632 NXDouble scannedVariables = scannedVariablesData.openDoubleData();
633 scannedVariables.load();
634
635 auto firstMonitorValuePos = scannedVariables() + monitorIndex * scannedVariables.dim1();
636
637 const HistogramData::Counts counts(firstMonitorValuePos, firstMonitorValuePos + scannedVariables.dim1());
638 m_localWorkspace->setCounts(firstIndex, counts);
639
640 if (m_instrumentName == "D16" && scannedVariables.dim1() == 1) {
641 // This is the old D16 data scan format. It is pain.
642 // Due to the fact it was verified with a data structure using binedges rather than points for the wavelength,
643 // we have to keep that and not make it an histogram, because some algorithms later in the reduction process
644 // handle errors completely differently in this case.
645 // We distinguish it from D16 data in the new format but checking there is only one slice of the omega scan
646 const HistogramData::BinEdges binEdges(binning);
647 m_localWorkspace->setBinEdges(firstIndex, binEdges);
648 } else {
649 HistogramData::Points points = HistogramData::Points(binning);
650 m_localWorkspace->setPoints(firstIndex, points);
651 }
652
653 // Add average monitor counts to a property:
654 double averageMonitorCounts =
655 std::accumulate(firstMonitorValuePos, firstMonitorValuePos + scannedVariables.dim1(), double(0)) /
656 static_cast<double>(scannedVariables.dim1());
657
658 // make sure the monitor has values!
659 if (averageMonitorCounts > 0) {
660 API::Run &runDetails = m_localWorkspace->mutableRun();
661 runDetails.addProperty("monitor", averageMonitorCounts, true);
662 }
663
664 firstIndex++;
665
666 if (m_instrumentName == "D16") {
667 // the old D16 has 2 monitors, the second being empty but still needing a binning
668
669 if (scannedVariables.dim1() == 1) {
670 const HistogramData::BinEdges binEdges(binning);
671 m_localWorkspace->setBinEdges(firstIndex, binEdges);
672 } else {
673 HistogramData::Points points = HistogramData::Points(binning);
674 m_localWorkspace->setPoints(firstIndex, points);
675 }
676 firstIndex++;
677 }
678 return firstIndex;
679}
680
689size_t LoadILLSANS::loadDataFromTubes(NeXus::NXInt &data, const std::vector<double> &timeBinning, size_t firstIndex = 0,
690 const MultichannelType type) {
691
692 int numberOfTubes, numberOfChannels, numberOfPixelsPerTube;
693 getDataDimensions(data, numberOfChannels, numberOfTubes, numberOfPixelsPerTube);
694
695 if (m_isD16Omega) {
697 for (int tubeIndex = 0; tubeIndex < numberOfTubes; ++tubeIndex) {
698 for (int pixelIndex = 0; pixelIndex < numberOfPixelsPerTube; ++pixelIndex) {
699 std::vector<int> spectrum(numberOfChannels);
700 for (int channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
701 spectrum[channelIndex] = data(channelIndex, tubeIndex, pixelIndex);
702 }
703 const size_t index = firstIndex + tubeIndex * numberOfPixelsPerTube + pixelIndex;
704 const HistogramData::Counts histoCounts(spectrum.begin(), spectrum.end());
705 const HistogramData::CountVariances histoVariances(spectrum.begin(), spectrum.end());
706
707 m_localWorkspace->setCounts(index, histoCounts);
708 m_localWorkspace->setCountVariances(index, histoVariances);
709
710 if (m_instrumentName == "D16" && numberOfChannels == 1) {
711 const HistogramData::BinEdges histoPoints(timeBinning);
712 m_localWorkspace->setBinEdges(index, histoPoints);
713 } else {
714 const HistogramData::Points histoPoints(timeBinning);
715 m_localWorkspace->setPoints(index, histoPoints);
716 }
717 }
718 }
719 } else {
720
722 for (int tubeIndex = 0; tubeIndex < numberOfTubes; ++tubeIndex) {
723 for (int pixelIndex = 0; pixelIndex < numberOfPixelsPerTube; ++pixelIndex) {
724 int *data_p;
725 if (m_isD16Omega) {
726 data_p = &data(0, tubeIndex, pixelIndex);
727 } else {
728 data_p = &data(tubeIndex, pixelIndex, 0);
729 }
730 const size_t index = firstIndex + tubeIndex * numberOfPixelsPerTube + pixelIndex;
731 const HistogramData::Counts histoCounts(data_p, data_p + numberOfChannels);
732 const HistogramData::CountVariances histoVariances(data_p, data_p + numberOfChannels);
733 m_localWorkspace->setCounts(index, histoCounts);
734 m_localWorkspace->setCountVariances(index, histoVariances);
735
736 if (type == MultichannelType::KINETIC) {
737 const HistogramData::Points histoPoints(timeBinning);
738 m_localWorkspace->setPoints(index, histoPoints);
739 } else {
740 const HistogramData::BinEdges binEdges(timeBinning);
741 m_localWorkspace->setBinEdges(index, binEdges);
742 }
743 }
744 }
745 }
746
747 return firstIndex + numberOfTubes * numberOfPixelsPerTube;
748}
749
756void LoadILLSANS::createEmptyWorkspace(const size_t numberOfHistograms, const size_t numberOfChannels,
757 const MultichannelType type) {
758 const size_t numberOfElementsInX = numberOfChannels + ((type == MultichannelType::TOF && !m_isD16Omega) ? 1 : 0);
760 WorkspaceFactory::Instance().create("Workspace2D", numberOfHistograms, numberOfElementsInX, numberOfChannels);
761
762 switch (type) {
764 m_localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("Wavelength");
765 break;
767 auto labelX = std::dynamic_pointer_cast<Kernel::Units::Label>(Kernel::UnitFactory::Instance().create("Label"));
768 labelX->setLabel("Omega angle");
769 m_localWorkspace->getAxis(0)->unit() = labelX;
770 break;
771 }
773 break;
774 }
775
776 m_localWorkspace->setYUnitLabel("Counts");
777}
778
785std::string LoadILLSANS::getInstrumentFilePath(const std::string &instName) const {
786
787 Poco::Path directory(ConfigService::Instance().getInstrumentDirectory());
788 Poco::Path file(instName + "_Definition.xml");
789 Poco::Path fullPath(directory, file);
790 return fullPath.toString();
791}
792
797
798 auto loadInst = createChildAlgorithm("LoadInstrument");
799 if (m_resMode == "nominal") {
800 loadInst->setPropertyValue("Filename", getInstrumentFilePath(m_instrumentName));
801 } else if (m_resMode == "low") {
802 // low resolution mode we have only defined for the old D11 and D22
803 loadInst->setPropertyValue("Filename", getInstrumentFilePath(m_instrumentName + "lr"));
804 }
805 loadInst->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
806 loadInst->setProperty("RewriteSpectraMap", Mantid::Kernel::OptionalBool(true));
807 loadInst->execute();
808}
809
815 // Move in Z
816 moveDetectorDistance(detPos.distanceSampleRear, "back_detector");
817 moveDetectorDistance(detPos.distanceSampleBottomTop, "front_detector_top");
818 moveDetectorDistance(detPos.distanceSampleBottomTop, "front_detector_bottom");
819 moveDetectorDistance(detPos.distanceSampleRightLeft, "front_detector_right");
820 moveDetectorDistance(detPos.distanceSampleRightLeft, "front_detector_left");
821 // Move in X
822 moveDetectorHorizontal(detPos.shiftLeft, "front_detector_left");
823 moveDetectorHorizontal(-detPos.shiftRight, "front_detector_right");
824 // Move in Y
825 moveDetectorVertical(detPos.shiftUp, "front_detector_top");
826 moveDetectorVertical(-detPos.shiftDown, "front_detector_bottom");
827 // Set the sample log
828 API::Run &runDetails = m_localWorkspace->mutableRun();
829 runDetails.addProperty<double>("L2", detPos.distanceSampleRear, true);
830}
831
837void LoadILLSANS::moveDetectorDistance(double distance, const std::string &componentName) {
838
839 auto mover = createChildAlgorithm("MoveInstrumentComponent");
840 V3D pos = getComponentPosition(componentName);
841 mover->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
842 mover->setProperty("ComponentName", componentName);
843
844 mover->setProperty("X", pos.X());
845 mover->setProperty("Y", pos.Y());
846 mover->setProperty("Z", distance);
847 mover->setProperty("RelativePosition", false);
848 mover->executeAsChildAlg();
849
850 g_log.debug() << "Moving component '" << componentName << "' to Z = " << distance << '\n';
851}
852
858void LoadILLSANS::rotateInstrument(double angle, const std::string &componentName) {
859 auto rotater = createChildAlgorithm("RotateInstrumentComponent");
860 rotater->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
861 rotater->setProperty("ComponentName", componentName);
862 rotater->setProperty("X", 0.);
863 rotater->setProperty("Y", 1.);
864 rotater->setProperty("Z", 0.);
865 rotater->setProperty("Angle", angle);
866 rotater->setProperty("RelativeRotation", false);
867 rotater->executeAsChildAlg();
868 g_log.debug() << "Rotating component '" << componentName << "' to angle = " << angle << " degrees.\n";
869}
870
877void LoadILLSANS::placeD16(double angle, double distance, const std::string &componentName) {
878 auto mover = createChildAlgorithm("MoveInstrumentComponent");
879 mover->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
880 mover->setProperty("ComponentName", componentName);
881 mover->setProperty("X", sin(angle * M_PI / 180) * distance);
882 mover->setProperty("Y", 0.);
883 mover->setProperty("Z", cos(angle * M_PI / 180) * distance);
884 mover->setProperty("RelativePosition", false);
885 mover->executeAsChildAlg();
886
887 // rotate the detector so it faces the sample.
888 rotateInstrument(angle, componentName);
889 API::Run &runDetails = m_localWorkspace->mutableRun();
890 runDetails.addProperty<double>("L2", distance, true);
891
892 g_log.debug() << "Moving component '" << componentName << "' to angle = " << angle
893 << " degrees and distance = " << distance << "metres.\n";
894}
895
901void LoadILLSANS::moveDetectorHorizontal(double shift, const std::string &componentName) {
902 auto mover = createChildAlgorithm("MoveInstrumentComponent");
903 V3D pos = getComponentPosition(componentName);
904 mover->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
905 mover->setProperty("ComponentName", componentName);
906 mover->setProperty("X", shift);
907 mover->setProperty("Y", pos.Y());
908 mover->setProperty("Z", pos.Z());
909 mover->setProperty("RelativePosition", false);
910 mover->executeAsChildAlg();
911 g_log.debug() << "Moving component '" << componentName << "' to X = " << shift << '\n';
912}
913
919void LoadILLSANS::moveDetectorVertical(double shift, const std::string &componentName) {
920 auto mover = createChildAlgorithm("MoveInstrumentComponent");
921 V3D pos = getComponentPosition(componentName);
922 mover->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
923 mover->setProperty("ComponentName", componentName);
924 mover->setProperty("X", pos.X());
925 mover->setProperty("Y", shift);
926 mover->setProperty("Z", pos.Z());
927 mover->setProperty("RelativePosition", false);
928 mover->executeAsChildAlg();
929 g_log.debug() << "Moving component '" << componentName << "' to Y = " << shift << '\n';
930}
931
937V3D LoadILLSANS::getComponentPosition(const std::string &componentName) {
938 Geometry::Instrument_const_sptr instrument = m_localWorkspace->getInstrument();
939 Geometry::IComponent_const_sptr component = instrument->getComponentByName(componentName);
940 return component->getPos();
941}
942
948void LoadILLSANS::loadMetaData(const NeXus::NXEntry &entry, const std::string &instrumentNamePath) {
949
950 g_log.debug("Loading metadata...");
951 API::Run &runDetails = m_localWorkspace->mutableRun();
952
953 if ((entry.getFloat("mode") == 0.0) || (m_instrumentName == "D16")) { // Not TOF
954 runDetails.addProperty<std::string>("tof_mode", "Non TOF");
955 } else {
956 runDetails.addProperty<std::string>("tof_mode", "TOF");
957 }
958
959 double wavelength;
960 if (getPointerToProperty("Wavelength")->isDefault()) {
961 if (m_instrumentName == "D16" || m_instrumentName == "D16B") {
962 wavelength = entry.getFloat(instrumentNamePath + "/Beam/wavelength");
963 } else {
964 wavelength = entry.getFloat(instrumentNamePath + "/selector/wavelength");
965 }
966 g_log.debug() << "Wavelength found in the nexus file: " << wavelength << '\n';
967 } else {
968 wavelength = getProperty("Wavelength");
969 }
970
971 // round the wavelength to avoid unnecessary rebinning during merge runs
972 wavelength = std::round(wavelength * 100) / 100.;
973
974 if (wavelength <= 0) {
975 g_log.debug() << "Mode = " << entry.getFloat("mode") << '\n';
976 g_log.information("The wavelength present in the NeXus file <= 0.");
977 if (entry.getFloat("mode") == 0.0) { // Not TOF
978 throw std::runtime_error("Working in Non TOF mode and the wavelength in "
979 "the file is <=0 !!! Check with the instrument "
980 "scientist!");
981 }
982 } else {
983 double wavelengthRes = 10.;
984 const std::string entryResolution = instrumentNamePath + "/selector/";
985 try {
986 wavelengthRes = entry.getFloat(entryResolution + "wavelength_res");
987 } catch (const std::runtime_error &) {
988 try {
989 wavelengthRes = entry.getFloat(entryResolution + "wave_length_res");
990 } catch (const std::runtime_error &) {
991 if (m_instrumentName == "D16")
992 wavelengthRes = 1;
993 g_log.information() << "Could not find wavelength resolution, assuming " << wavelengthRes << "%.\n";
994 }
995 }
996 // round also the wavelength res to avoid unnecessary rebinning during
997 // merge runs
998 wavelengthRes = std::round(wavelengthRes * 100) / 100.;
999 runDetails.addProperty<double>("wavelength", wavelength);
1000 double ei = LoadHelper::calculateEnergy(wavelength);
1001 runDetails.addProperty<double>("Ei", ei, true);
1002 // wavelength
1003 m_defaultBinning[0] = wavelength - wavelengthRes * wavelength * 0.01 / 2;
1004 m_defaultBinning[1] = wavelength + wavelengthRes * wavelength * 0.01 / 2;
1005 }
1006
1007 // the start time is needed in the workspace when loading the parameter file
1008 std::string startDate = entry.getString("start_time");
1009 runDetails.addProperty<std::string>("start_time", LoadHelper::dateTimeInIsoFormat(startDate));
1010 // set the facility
1011 runDetails.addProperty<std::string>("Facility", std::string("ILL"));
1012}
1013
1018void LoadILLSANS::setFinalProperties(const std::string &filename) {
1019 API::Run &runDetails = m_localWorkspace->mutableRun();
1020 NXhandle nxHandle;
1021 NXstatus nxStat = NXopen(filename.c_str(), NXACC_READ, &nxHandle);
1022 if (nxStat != NX_ERROR) {
1023 LoadHelper::addNexusFieldsToWsRun(nxHandle, runDetails);
1024 NXclose(&nxHandle);
1025 }
1026}
1027
1033 const auto &specInfo = m_localWorkspace->spectrumInfo();
1034 const double l1 = m_sourcePos;
1035 const size_t nHist = m_localWorkspace->getNumberHistograms();
1037 for (int64_t index = 0; index < static_cast<int64_t>(nHist - m_numberOfMonitors); ++index) {
1038 const double l2 = specInfo.l2(index);
1039 const double z = specInfo.position(index).Z();
1040 auto &x = m_localWorkspace->mutableX(index);
1041 const double scale = (l1 + z) / (l1 + l2);
1042 std::transform(x.begin(), x.end(), x.begin(), [scale](double lambda) { return scale * lambda; });
1043 }
1044
1045 // Try to set sensible (but not strictly physical) wavelength axes for monitors
1046 // Normalisation is done by acquisition time, so these axes should not be used
1047 auto firstPixel = m_localWorkspace->histogram(0).dataX();
1048 const double l2 = specInfo.l2(0);
1049 const double monitor2 = -specInfo.position(nHist - 1).Z();
1050 const double l1Monitor2 = m_sourcePos - monitor2;
1051 const double monScale = (l1 + l2) / l1Monitor2;
1052 std::transform(firstPixel.begin(), firstPixel.end(), firstPixel.begin(),
1053 [monScale](double lambda) { return monScale * lambda; });
1054 for (size_t mIndex = nHist - m_numberOfMonitors; mIndex < nHist; ++mIndex) {
1055 const HistogramData::Counts counts = m_localWorkspace->histogram(mIndex).counts();
1056 const HistogramData::BinEdges binEdges(firstPixel);
1057 m_localWorkspace->setHistogram(mIndex, binEdges, counts);
1058 }
1059}
1060
1066 auto mover = createChildAlgorithm("MoveInstrumentComponent");
1067 mover->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
1068 mover->setProperty("ComponentName", "moderator");
1069 mover->setProperty("X", 0.);
1070 mover->setProperty("Y", 0.);
1071 mover->setProperty("Z", -m_sourcePos);
1072 mover->setProperty("RelativePosition", false);
1073 mover->executeAsChildAlg();
1074}
1075
1083std::vector<double> LoadILLSANS::getOmegaBinning(const NXEntry &entry, const std::string &path) const {
1084 NXData scanning_data = entry.openNXData(path);
1085 NXDouble scanning_values = scanning_data.openDoubleData();
1086 scanning_values.load();
1087
1088 const int nBins = scanning_values.dim1();
1089 std::vector<double> binning(nBins, 0);
1090
1091 for (int i = 0; i < nBins; ++i) {
1092 // for D16, we are only interested in the first line, which contains the omega values
1093 binning[i] = scanning_values(0, i);
1094 }
1095 return binning;
1096}
1097
1106std::vector<double> LoadILLSANS::getVariableTimeBinning(const NXEntry &entry, const std::string &path, const NXInt &sum,
1107 const NXFloat &times) const {
1108 const int nBins = sum.dim0();
1109 std::vector<double> binCenters;
1110 binCenters.reserve(nBins);
1111 NXFloat distance = entry.openNXFloat(path);
1112 distance.load();
1113 for (int bin = 0; bin < nBins; ++bin) {
1114 // sum is in nanoseconds, times is in microseconds
1115 const double tof = sum[bin] * 1E-9 - times[bin] * 1E-6 / 2.;
1116 // velocity in m/s
1117 const double velocity = distance[0] / tof;
1118 // wavelength in AA
1119 const double lambda = PhysicalConstants::h / PhysicalConstants::NeutronMass / velocity * 1E+10;
1120 binCenters.emplace_back(lambda);
1121 }
1122 std::vector<double> binEdges;
1123 binEdges.reserve(nBins + 1);
1124 VectorHelper::convertToBinBoundary(binCenters, binEdges);
1125 // after conversion to bin edges, the first item might get negative,
1126 // which is not physical, set to 0
1127 if (binEdges[0] < 0.) {
1128 binEdges[0] = 0.;
1129 }
1130 return binEdges;
1131}
1132
1133} // namespace Mantid::DataHandling
const std::vector< double > * lambda
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#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
Kernel::Property * getPointerToProperty(const std::string &name) const override
Get a property by name.
Definition: Algorithm.cpp:2033
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
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
Definition: LogManager.h:79
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
This class stores information regarding an experimental run as a series of log entries.
Definition: Run.h:38
A property class for workspaces.
LoadILLSANS; supports D11, D22 and D33 (TOF/monochromatic)
Definition: LoadILLSANS.h:20
void initWorkSpaceD22B(NeXus::NXEntry &, const std::string &)
LoadILLSANS::initWorkSpaceD22B Load D22B data.
bool m_isTOF
TOF or monochromatic flag.
Definition: LoadILLSANS.h:91
void setInstrumentName(const NeXus::NXEntry &, const std::string &)
Set member variable with the instrument name.
void runLoadInstrument()
Loads the instrument from the IDF.
void loadMetaData(const NeXus::NXEntry &, const std::string &)
Loads some metadata present in the nexus file.
void initWorkSpace(NeXus::NXEntry &, const std::string &)
Loads data for D11, D16 and D22.
void moveDetectorsD33(const DetectorPosition &)
Move the detector banks for D33.
void createEmptyWorkspace(const size_t, const size_t, const MultichannelType type=MultichannelType::TOF)
Create a workspace without any data in it.
std::vector< double > getOmegaBinning(const NeXus::NXEntry &entry, const std::string &path) const
LoadILLSANS::getOmegaBinning Get the binning for an omega scan for D16B files.
const std::string name() const override
Algorithm's name for identification.
Definition: LoadILLSANS.cpp:49
const std::string summary() const override
Algorithm's summary.
Definition: LoadILLSANS.cpp:58
int confidence(Kernel::NexusDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
Definition: LoadILLSANS.cpp:70
size_t loadDataFromD16ScanMonitors(const NeXus::NXEntry &firstEntry, size_t firstIndex, const std::vector< double > &binning)
Load data from D16B's monitor.
void init() override
Initialize the algorithm's properties.
Definition: LoadILLSANS.cpp:86
double m_sourcePos
Source Z (for D33 TOF)
Definition: LoadILLSANS.h:92
const std::string category() const override
Algorithm's category for identification.
Definition: LoadILLSANS.cpp:55
void setFinalProperties(const std::string &filename)
Sets full sample logs.
size_t loadDataFromTubes(NeXus::NXInt &, const std::vector< double > &, size_t, const MultichannelType type=MultichannelType::TOF)
Loads data from tubes.
std::vector< double > getVariableTimeBinning(const NeXus::NXEntry &, const std::string &, const NeXus::NXInt &, const NeXus::NXFloat &) const
Returns the wavelength axis computed in VTOF mode.
void moveDetectorDistance(double distance, const std::string &componentName)
Move detectors in Z axis (X,Y are kept constant)
void initWorkSpaceD11B(NeXus::NXEntry &, const std::string &)
LoadILLSANS::initWorkSpaceD11B Load D11B data.
int version() const override
Algorithm's version for identification.
Definition: LoadILLSANS.cpp:52
void initWorkSpaceD33(NeXus::NXEntry &, const std::string &)
Loads data for D33.
Kernel::V3D getComponentPosition(const std::string &componentName)
Get position of a component.
void setNumberOfMonitors()
LoadILLSANS::setNumberOfMonitors Set the number of monitor attribute depending on the instrument load...
void getDataDimensions(const NeXus::NXInt &data, int &numberOfChannels, int &numberOfTubes, int &numberOfPixelsPerTube)
LoadILLSANS::getDataDimensions Retrieves physical dimensions of the data from the dataset dimensions.
void moveSource()
Moves the source to the middle of the two master choppers Used only for D33 in TOF mode.
void moveDetectorVertical(double, const std::string &)
Move detectors in Y.
size_t m_numberOfMonitors
Number of monitors in this instrument.
Definition: LoadILLSANS.h:94
void placeD16(double, double, const std::string &)
LoadILLSANS::placeD16 : place the D16 detector.
DetectorPosition getDetectorPositionD33(const NeXus::NXEntry &, const std::string &)
Get detector panel distances from the nexus file.
std::vector< double > m_defaultBinning
the default x-axis binning
Definition: LoadILLSANS.h:89
void exec() override
Execute the algorithm.
std::vector< std::string > m_supportedInstruments
List of supported instruments.
Definition: LoadILLSANS.h:87
void adjustTOF()
Adjusts pixel by pixel the wavelength axis Used only for D33 in TOF mode.
void moveDetectorHorizontal(double, const std::string &)
Move detectors in X.
API::MatrixWorkspace_sptr m_localWorkspace
to-be output workspace
Definition: LoadILLSANS.h:88
void rotateInstrument(double, const std::string &)
Rotates instrument detector around y-axis in place.
bool m_isD16Omega
Data comes from a D16 omega scan flag.
Definition: LoadILLSANS.h:93
std::string m_instrumentName
Name of the instrument.
Definition: LoadILLSANS.h:86
size_t loadDataFromMonitors(NeXus::NXEntry &firstEntry, size_t firstIndex=0, const MultichannelType type=MultichannelType::TOF)
Loads data from all the monitors.
std::string m_resMode
Resolution mode for D11 and D22.
Definition: LoadILLSANS.h:90
std::string getInstrumentFilePath(const std::string &) const
Makes up the full path of the relevant IDF dependent on resolution mode.
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 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 pathExists(const std::string &path) const
Query if a path exists.
OptionalBool : Tri-state bool.
Definition: OptionalBool.h:25
virtual bool isDefault() const =0
Overriden function that returns if property has the same value that it was initialised with,...
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Class for 3D vectors.
Definition: V3D.h:34
constexpr double X() const noexcept
Get x.
Definition: V3D.h:232
constexpr double Y() const noexcept
Get y.
Definition: V3D.h:233
constexpr double Z() const noexcept
Get z.
Definition: V3D.h:234
NXInt openNXInt(const std::string &name) const
Creates and opens an integer dataset.
Definition: NexusClasses.h:546
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
float getFloat(const std::string &name) const
Returns a float.
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
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.
int dim1() const
Returns the number of elements along the second dimension.
Implements NXdata Nexus class.
Definition: NexusClasses.h:795
NXDouble openDoubleData()
Opens data of double type.
Definition: NexusClasses.h:824
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
Implements NXroot Nexus class.
Definition: NexusClasses.h:922
NXEntry openFirstEntry()
Open the first NXentry in the file.
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
double calculateEnergy(double)
Calculate Neutron Energy from wavelength: .
Definition: LoadHelper.cpp:82
std::string getStringFromNexusPath(const Mantid::NeXus::NXEntry &, const std::string &)
Definition: LoadHelper.cpp:49
std::vector< double > getTimeBinningFromNexusPath(const Mantid::NeXus::NXEntry &, const std::string &)
Gets the time binning from a Nexus float array Adds an extra bin at the end.
Definition: LoadHelper.cpp:61
void addNexusFieldsToWsRun(NXhandle nxfileID, API::Run &runDetails, const std::string &entryName="", bool useFullPath=false)
Add properties from a nexus file to the workspace run.
Definition: LoadHelper.cpp:131
double getDoubleFromNexusPath(const Mantid::NeXus::NXEntry &, const std::string &)
Definition: LoadHelper.cpp:53
std::string findInstrumentNexusPath(const Mantid::NeXus::NXEntry &)
Finds the path for the instrument name in the nexus file Usually of the form: entry0/<NXinstrument cl...
Definition: LoadHelper.cpp:37
std::string dateTimeInIsoFormat(const std::string &)
Parses the date as formatted at the ILL: 29-Jun-12 11:27:26 and converts it to the ISO format used in...
Definition: LoadHelper.cpp:421
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
Definition: IComponent.h:161
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
void MANTID_KERNEL_DLL convertToBinBoundary(const std::vector< double > &bin_centers, std::vector< double > &bin_edges)
Convert an array of bin centers to bin boundary values.
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
Definition: MultiThreaded.h:22
static constexpr double NeutronMass
Mass of the neutron in kg.
static constexpr double h
Planck constant in J*s.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Output
An output workspace.
Definition: Property.h:54