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
10#include "MantidAPI/Axis.h"
13#include "MantidAPI/Progress.h"
15#include "MantidAPI/Run.h"
22#include "MantidHistogramData/LinearGenerator.h"
29#include "MantidNexus/H5Util.h"
32#include "MantidNexus/NexusFile.h"
33
34namespace Mantid::DataHandling {
35
36using namespace Kernel;
37using namespace API;
38using namespace Nexus;
39
41
42//----------------------------------------------------------------------------------------------
46 : m_supportedInstruments{"D11", "D22", "D33", "D16"}, m_defaultBinning{0, 0}, m_resMode("nominal"), m_isTOF(false),
47 m_sourcePos(0.), m_numberOfMonitors(2) {}
48
49//----------------------------------------------------------------------------------------------
51const std::string LoadILLSANS::name() const { return "LoadILLSANS"; }
52
54int LoadILLSANS::version() const { return 1; }
55
57const std::string LoadILLSANS::category() const { return "DataHandling\\Nexus;ILL\\SANS"; }
58
60const std::string LoadILLSANS::summary() const {
61 return "Loads ILL nexus files for SANS instruments D11, D16, D22, D33.";
62}
63
64//----------------------------------------------------------------------------------------------
65
73 // fields existent only at the ILL for SANS machines
74 if (descriptor.isEntry("/entry0/mode") &&
75 ((descriptor.isEntry("/entry0/reactor_power") && descriptor.isEntry("/entry0/instrument_name")) ||
76 (descriptor.isEntry("/entry0/instrument/name") && descriptor.isEntry("/entry0/acquisition_mode") &&
77 !descriptor.isEntry("/entry0/instrument/Detector")))) // serves to remove the TOF instruments
78 {
79 return 80;
80 } else {
81 return 0;
82 }
83}
84
85//----------------------------------------------------------------------------------------------
89 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, ".nxs"),
90 "Name of the nexus file to load");
91 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
92 "The name to use for the output workspace");
93 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
94 mustBePositive->setLower(0);
95 declareProperty("Wavelength", 0.0, mustBePositive,
96 "The wavelength of the experiment, in angstroms. Used only for D16. Will "
97 "override the nexus' value if there is one.");
98 declareProperty(std::make_unique<FileProperty>("SensitivityMap", "", FileProperty::OptionalLoad, ".nxs"),
99 "Name of the file containing sensitivity map.");
100}
101
102//----------------------------------------------------------------------------------------------
106 const std::string filename = getPropertyValue("Filename");
107 m_isD16Omega = false;
108 getMonitorIndices(filename);
109 NXRoot root(filename);
110 NXEntry firstEntry = root.openFirstEntry();
111 const std::string instrumentAddress = LoadHelper::findInstrumentNexusAddress(firstEntry);
112 setInstrumentName(firstEntry, instrumentAddress);
113 Progress progress(this, 0.0, 1.0, 4);
114 progress.report("Initializing the workspace for " + m_instrumentName);
115 if (m_instrumentName == "D33") {
116 initWorkSpaceD33(firstEntry, instrumentAddress);
117 progress.report("Loading the instrument " + m_instrumentName);
119 const DetectorPosition detPos = getDetectorPositionD33(firstEntry, instrumentAddress);
120 progress.report("Moving detectors");
121 moveDetectorsD33(detPos);
122 if (m_isTOF) {
123 adjustTOF();
124 moveSource();
125 }
126
127 } else if (m_instrumentName == "D16") {
128 initWorkSpace(firstEntry, instrumentAddress);
129 progress.report("Loading the instrument " + m_instrumentName);
131
132 double distance;
133 try {
134 distance = firstEntry.getFloat(instrumentAddress + "/Det/value") / 1000; // mm to metre
135 } catch (std::runtime_error &) {
136 distance = 0;
137 }
138 const double angle = firstEntry.getFloat(instrumentAddress + "/Gamma/value");
139 placeD16(-angle, distance, "detector");
140
141 } else if (m_instrumentName == "D11B") {
142 initWorkSpaceD11B(firstEntry, instrumentAddress);
143 progress.report("Loading the instrument " + m_instrumentName);
145
146 // we move the parent "detector" component, but since it is at (0,0,0), we
147 // need to find the distance it has to move and move it to this position
148 double finalDistance = firstEntry.getFloat(instrumentAddress + "/Detector 1/det_calc");
149 V3D pos = LoadHelper::getComponentPosition(m_localWorkspace, "detector_center");
150 double currentDistance = pos.Z();
151
152 moveDetectorDistance(finalDistance - currentDistance, "detector");
153 API::Run &runDetails = m_localWorkspace->mutableRun();
154 runDetails.addProperty<double>("L2", finalDistance, true);
155
156 } else if (m_instrumentName == "D22B") {
157 initWorkSpaceD22B(firstEntry, instrumentAddress);
158
159 const std::string backIndex = m_localWorkspace->getInstrument()->getStringParameter("back_detector_index")[0];
160 const std::string frontIndex = m_localWorkspace->getInstrument()->getStringParameter("front_detector_index")[0];
161
162 // first we move the central (back) detector
163 double distance = firstEntry.getFloat(instrumentAddress + "/Detector " + backIndex + "/det" + backIndex + "_calc");
164 moveDetectorDistance(distance, "detector_back");
165 API::Run &runDetails = m_localWorkspace->mutableRun();
166 runDetails.addProperty<double>("L2", distance, true);
167
168 double offset = firstEntry.getFloat(instrumentAddress + "/Detector " + backIndex + "/dtr" + backIndex + "_actual");
169 moveDetectorHorizontal(-offset / 1000, "detector_back"); // mm to meter
170
171 // then the front (right) one
172 distance = firstEntry.getFloat(instrumentAddress + "/Detector " + frontIndex + "/det" + frontIndex + "_calc");
173 moveDetectorDistance(distance, "detector_front");
174
175 // mm to meter
176 offset = firstEntry.getFloat(instrumentAddress + "/Detector " + frontIndex + "/dtr" + frontIndex + "_actual");
177 moveDetectorHorizontal(-offset / 1000, "detector_front"); // mm to meter
178 double angle = firstEntry.getFloat(instrumentAddress + "/Detector " + frontIndex + "/dan" + frontIndex + "_actual");
179 rotateInstrument(-angle, "detector_front");
180
181 } else {
182 // D11 and D22
183 initWorkSpace(firstEntry, instrumentAddress);
184 progress.report("Loading the instrument " + m_instrumentName);
186 double distance = LoadHelper::getDoubleFromNexusAddress(firstEntry, instrumentAddress + "/detector/det_calc");
187 progress.report("Moving detectors");
188 moveDetectorDistance(distance, "detector");
189 API::Run &runDetails = m_localWorkspace->mutableRun();
190 runDetails.addProperty<double>("L2", distance, true);
191 if (m_instrumentName == "D22") {
192 double offset = LoadHelper::getDoubleFromNexusAddress(firstEntry, instrumentAddress + "/detector/dtr_actual");
193 moveDetectorHorizontal(-offset / 1000, "detector"); // mm to meter
194 }
195 }
196 if (m_instrumentName.find("D16") != std::string::npos && !isDefault("SensitivityMap")) {
198 }
199 progress.report("Setting sample logs");
200 setFinalProperties(filename);
201 setProperty("OutputWorkspace", m_localWorkspace);
202}
203
209void LoadILLSANS::setInstrumentName(const Nexus::NXEntry &firstEntry, const std::string &instrumentNameAddress) {
210 if (instrumentNameAddress.empty()) {
211 throw std::runtime_error("Cannot set the instrument name from the Nexus file!");
212 }
213 m_instrumentName = LoadHelper::getStringFromNexusAddress(firstEntry, instrumentNameAddress + "/name");
214 const auto inst = std::find(m_supportedInstruments.begin(), m_supportedInstruments.end(), m_instrumentName);
215
216 // set alternative version name. Note that D16B is set later, because we need to open the data to distinguish with D16
217 if ((m_instrumentName == "D11" || m_instrumentName == "D22") && firstEntry.containsGroup("data1")) {
218 m_instrumentName += "B";
219 }
220
221 if (inst == m_supportedInstruments.end()) {
222 throw std::runtime_error("Instrument " + m_instrumentName +
223 " is not supported. Only D11, D16, D22 and D33 are supported");
224 }
225 g_log.debug() << "Instrument name set to: " + m_instrumentName << '\n';
226}
227
233 // loading nexus processed returns Workspace type, so cannot be used as a child algorithm
234 LoadNexusProcessed loader;
235 loader.initialize();
236 loader.setPropertyValue("Filename", getPropertyValue("SensitivityMap"));
237 loader.setPropertyValue("OutputWorkspace", "sensitivity_map");
238 loader.execute();
239 auto divide = createChildAlgorithm("Divide");
240 divide->setProperty("LHSWorkspace", m_localWorkspace);
241 divide->setPropertyValue("RHSWorkspace", "sensitivity_map");
242 divide->setProperty("AllowDifferentNumberSpectra",
243 true); // in case the localWorkspace contains monitors but sensitivityMap does not
244 divide->executeAsChildAlg();
245 m_localWorkspace = divide->getProperty("OutputWorkspace");
246}
247
255 const std::string &instrumentNameAddress) {
256 std::string detectorAddress(instrumentNameAddress + "/detector");
258 pos.distanceSampleRear = LoadHelper::getDoubleFromNexusAddress(firstEntry, detectorAddress + "/det2_calc");
259 pos.distanceSampleBottomTop = LoadHelper::getDoubleFromNexusAddress(firstEntry, detectorAddress + "/det1_calc");
262 LoadHelper::getDoubleFromNexusAddress(firstEntry, detectorAddress + "/det1_panel_separation");
263 pos.shiftLeft = LoadHelper::getDoubleFromNexusAddress(firstEntry, detectorAddress + "/OxL_actual") * 1e-3;
264 pos.shiftRight = LoadHelper::getDoubleFromNexusAddress(firstEntry, detectorAddress + "/OxR_actual") * 1e-3;
265 pos.shiftUp = LoadHelper::getDoubleFromNexusAddress(firstEntry, detectorAddress + "/OyT_actual") * 1e-3;
266 pos.shiftDown = LoadHelper::getDoubleFromNexusAddress(firstEntry, detectorAddress + "/OyB_actual") * 1e-3;
267 pos >> g_log.debug();
268 return pos;
269}
270
279void LoadILLSANS::getDataDimensions(const Nexus::NXInt &data, size_t &numberOfChannels, size_t &numberOfTubes,
280 size_t &numberOfPixelsPerTube) {
281 if (m_isD16Omega) {
282 numberOfChannels = static_cast<size_t>(data.dim0());
283 numberOfTubes = static_cast<size_t>(data.dim1());
284 numberOfPixelsPerTube = static_cast<size_t>(data.dim2());
285 } else {
286 numberOfPixelsPerTube = static_cast<size_t>(data.dim1());
287 numberOfChannels = static_cast<size_t>(data.dim2());
288 numberOfTubes = static_cast<size_t>(data.dim0());
289 }
290 g_log.debug() << "Dimensions found:\n- Number of tubes: " << numberOfTubes
291 << "\n- Number of pixels per tube: " << numberOfPixelsPerTube
292 << "\n- Number of channels: " << numberOfChannels << "\n";
293}
294
299void LoadILLSANS::getMonitorIndices(const std::string &filename) {
300 /*
301 * The below tries to access names of scanned variables. These should exist only for omega scans of D16B,
302 * and will not be there for other instruments and modes of measurement (D16B gamma scan for example).
303 * Therefore, any issue from accessing this data is wrapped in try-catch clause. Assumed is proper order
304 * of monitors: Monitor1 should preceed Monitor2 in the scanned variables. The order of these indices
305 * in the variables_names will be used to load the monitor data.
306 *
307 * This method needs to be run before NeXus file is opened with NX library, otherwise it is not possible
308 * to open the same file with these two libraries (H5 and NX) simultaneously.
309 */
310 try {
311 H5::H5File h5file(filename, H5F_ACC_RDONLY, Nexus::H5Util::defaultFileAcc());
312 H5::DataSet scanVarNames = h5file.openDataSet("entry0/data_scan/scanned_variables/variables_names/name");
313 H5::DataSpace scanVarNamesSpace = scanVarNames.getSpace();
314 const auto nDims = scanVarNamesSpace.getSimpleExtentNdims();
315 auto dimsSize = std::vector<hsize_t>(nDims);
316 scanVarNamesSpace.getSimpleExtentDims(dimsSize.data(), nullptr);
317 std::vector<char *> rdata(dimsSize[0]);
318 scanVarNames.read(rdata.data(), scanVarNames.getDataType());
319 size_t monitorIndex = 0;
320 while (monitorIndex < rdata.size()) {
321 const auto varName = std::string(rdata[monitorIndex]);
322 if (varName.find("Monitor") != std::string::npos)
323 m_monitorIndices.push_back(monitorIndex);
324 monitorIndex++;
325 }
326 h5file.close();
327 } catch (...) { // silence all issues accessing the data
328 return;
329 }
330}
331
337void LoadILLSANS::initWorkSpace(Nexus::NXEntry &firstEntry, const std::string &instrumentAddress) {
338 g_log.debug("Fetching data...");
339 std::string address;
340 if (firstEntry.containsGroup("data")) {
341 address = "data";
342 } else {
343 address = "data_scan/detector_data/data";
344 }
345 auto data = LoadHelper::getIntDataset(firstEntry, address);
346 data.load();
347
348 // determine if the data comes from a D16 scan
349 m_isD16Omega = (data.dim0() >= 1 && data.dim2() > 1 && m_instrumentName == "D16");
350
351 if (m_instrumentName == "D16") {
352 const size_t numberOfWiresInD16B = 1152;
353 const size_t numberOfPixelsPerWireInD16B = 192;
354
355 // Check if the instrument loaded is D16B. It cannot be differentiated from D16 by the structure of the nexus file
356 // only, so we need to check the data size.
357 if (data.dim1() == numberOfWiresInD16B && data.dim2() == numberOfPixelsPerWireInD16B) {
358 m_instrumentName = "D16B";
359 m_isD16Omega = true;
360 }
361 }
362
363 size_t numberOfTubes, numberOfPixelsPerTubes, numberOfChannels;
364 getDataDimensions(data, numberOfChannels, numberOfTubes, numberOfPixelsPerTubes);
365
366 // For these monochromatic instruments, one bin is "TOF" mode, and more than that is a scan
367 MultichannelType type = (numberOfChannels == 1) ? MultichannelType::TOF : MultichannelType::SCAN;
368
369 size_t numberOfHistograms = numberOfPixelsPerTubes * numberOfTubes + m_numberOfMonitors;
370
371 createEmptyWorkspace(numberOfHistograms, numberOfChannels, type);
372 loadMetaData(firstEntry, instrumentAddress);
373
374 std::vector<double> binning = m_isD16Omega && numberOfChannels > 1
375 ? getOmegaBinning(firstEntry, "data_scan/scanned_variables/data")
377
378 size_t nextIndex;
379 nextIndex = loadDataFromTubes(data, binning, 0);
380 if (m_instrumentName == "D16B" ||
381 (m_isD16Omega && data.dim0() > 1)) // second condition excludes legacy D16 omega scans with single scan point
382 loadDataFromD16ScanMonitors(firstEntry, nextIndex, binning);
383 else
384 loadDataFromMonitors(firstEntry, nextIndex);
385
386 if (data.dim1() == 128) {
387 m_resMode = "low";
388 }
389}
390
396void LoadILLSANS::initWorkSpaceD11B(Nexus::NXEntry &firstEntry, const std::string &instrumentAddress) {
397 g_log.debug("Fetching data...");
398
399 auto dataCenter = LoadHelper::getIntDataset(firstEntry, "D11/Detector 1/data");
400 dataCenter.load();
401 auto dataLeft = LoadHelper::getIntDataset(firstEntry, "D11/Detector 2/data");
402 dataLeft.load();
403 auto dataRight = LoadHelper::getIntDataset(firstEntry, "D11/Detector 3/data");
404 dataRight.load();
405
406 size_t numberOfHistograms =
407 static_cast<size_t>(dataCenter.dim0() * dataCenter.dim1() + dataRight.dim0() * dataRight.dim1() +
408 dataLeft.dim0() * dataLeft.dim1()) +
410
411 size_t numberOfChannels, numberOfPixelsPerTubeCenter, numberOfTubesCenter;
412 getDataDimensions(dataCenter, numberOfChannels, numberOfTubesCenter, numberOfPixelsPerTubeCenter);
413
414 MultichannelType type = (numberOfChannels != 1) ? MultichannelType::KINETIC : MultichannelType::TOF;
415 createEmptyWorkspace(numberOfHistograms, numberOfChannels, type);
416 loadMetaData(firstEntry, instrumentAddress);
417
418 // we need to adjust the default binning after loadmetadata
419 if (numberOfChannels != 1) {
420 std::vector<double> frames(numberOfChannels, 0);
421 for (size_t i = 0; i < numberOfChannels; ++i) {
422 frames[i] = static_cast<double>(i);
423 }
424 m_defaultBinning.resize(numberOfChannels);
425 std::copy(frames.cbegin(), frames.cend(), m_defaultBinning.begin());
426 }
427
428 size_t nextIndex;
429 nextIndex = loadDataFromTubes(dataCenter, m_defaultBinning, 0, type);
430 nextIndex = loadDataFromTubes(dataLeft, m_defaultBinning, nextIndex, type);
431 nextIndex = loadDataFromTubes(dataRight, m_defaultBinning, nextIndex, type);
432 nextIndex = loadDataFromMonitors(firstEntry, nextIndex, type);
433
434 if (numberOfChannels != 1) {
435 // there are a few runs with no 2nd monitor in kinetic, so we load the first monitor once again to preserve the
436 // dimensions and x-axis
437 if (nextIndex < numberOfHistograms)
438 nextIndex = loadDataFromMonitors(firstEntry, nextIndex, type);
439
440 // hijack the second monitor spectrum to store per-frame durations to enable time normalisation
441 NXFloat durations = firstEntry.openNXFloat("slices");
442 durations.load();
443 const HistogramData::Counts histoCounts(durations(), durations() + numberOfChannels);
444 m_localWorkspace->setCounts(nextIndex - 1, histoCounts);
445 m_localWorkspace->setCountVariances(nextIndex - 1,
446 HistogramData::CountVariances(std::vector<double>(numberOfChannels, 0)));
447 }
448}
449
455void LoadILLSANS::initWorkSpaceD22B(Nexus::NXEntry &firstEntry, const std::string &instrumentAddress) {
456 g_log.debug("Fetching data...");
457
458 auto data1_data = LoadHelper::getIntDataset(firstEntry, "data1");
459 data1_data.load();
460 auto data2_data = LoadHelper::getIntDataset(firstEntry, "data2");
461 data2_data.load();
462
463 size_t numberOfHistograms =
464 static_cast<size_t>(data2_data.dim0() * data2_data.dim1() + data1_data.dim0() * data1_data.dim1()) +
466
467 size_t numberOfChannels, numberOfPixelsPerTubeCenter, numberOfTubesCenter;
468 getDataDimensions(data1_data, numberOfChannels, numberOfTubesCenter, numberOfPixelsPerTubeCenter);
469
470 MultichannelType type = (numberOfChannels != 1) ? MultichannelType::KINETIC : MultichannelType::TOF;
471
472 createEmptyWorkspace(numberOfHistograms, numberOfChannels, type);
473 loadMetaData(firstEntry, instrumentAddress);
474
475 // we need to adjust the default binning after loadmetadata
476 if (numberOfChannels != 1) {
477 std::vector<double> frames(numberOfChannels, 0);
478 for (size_t i = 0; i < numberOfChannels; ++i) {
479 frames[i] = static_cast<double>(i);
480 }
481 m_defaultBinning.resize(numberOfChannels);
482 std::copy(frames.cbegin(), frames.cend(), m_defaultBinning.begin());
483 }
484
486
487 const std::string backIndex = m_localWorkspace->getInstrument()->getStringParameter("back_detector_index")[0];
488 size_t nextIndex;
489 if (backIndex == "2") {
490 nextIndex = loadDataFromTubes(data2_data, m_defaultBinning, 0, type);
491 nextIndex = loadDataFromTubes(data1_data, m_defaultBinning, nextIndex, type);
492 } else {
493 nextIndex = loadDataFromTubes(data1_data, m_defaultBinning, 0, type);
494 nextIndex = loadDataFromTubes(data2_data, m_defaultBinning, nextIndex, type);
495 }
496 nextIndex = loadDataFromMonitors(firstEntry, nextIndex, type);
497
498 // hijack the second monitor spectrum to store per-frame durations to enable time normalisation
499 if (numberOfChannels != 1) {
500 NXFloat durations = firstEntry.openNXFloat("slices");
501 durations.load();
502 const HistogramData::Counts histoCounts(durations(), durations() + numberOfChannels);
503 m_localWorkspace->setCounts(nextIndex - 1, std::move(histoCounts));
504 m_localWorkspace->setCountVariances(nextIndex - 1,
505 HistogramData::CountVariances(std::vector<double>(numberOfChannels, 0)));
506 }
507}
508
514void LoadILLSANS::initWorkSpaceD33(Nexus::NXEntry &firstEntry, const std::string &instrumentAddress) {
515
516 g_log.debug("Fetching data...");
517
518 auto dataRear = LoadHelper::getIntDataset(firstEntry, "data1");
519 dataRear.load();
520 auto dataRight = LoadHelper::getIntDataset(firstEntry, "data2");
521 dataRight.load();
522 auto dataLeft = LoadHelper::getIntDataset(firstEntry, "data3");
523 dataLeft.load();
524 auto dataDown = LoadHelper::getIntDataset(firstEntry, "data4");
525 dataDown.load();
526 auto dataUp = LoadHelper::getIntDataset(firstEntry, "data5");
527 dataUp.load();
528 g_log.debug("Checking channel numbers...");
529
530 // check number of channels
531 if (dataRear.dim2() != dataRight.dim2() && dataRight.dim2() != dataLeft.dim2() &&
532 dataLeft.dim2() != dataDown.dim2() && dataDown.dim2() != dataUp.dim2()) {
533 throw std::runtime_error("The time bins have not the same dimension for all the 5 detectors!");
534 }
535 const auto numberOfHistograms = static_cast<size_t>(
536 dataRear.dim0() * dataRear.dim1() + dataRight.dim0() * dataRight.dim1() + dataLeft.dim0() * dataLeft.dim1() +
537 dataDown.dim0() * dataDown.dim1() + dataUp.dim0() * dataUp.dim1());
538
539 g_log.debug("Creating empty workspace...");
540 createEmptyWorkspace(numberOfHistograms + m_numberOfMonitors, static_cast<size_t>(dataRear.dim2()));
541
542 loadMetaData(firstEntry, instrumentAddress);
543
544 std::vector<double> binningRear, binningRight, binningLeft, binningDown, binningUp;
545
546 if (firstEntry.getFloat("mode") == 0.0) { // Not TOF
547 g_log.debug("Getting default wavelength bins...");
548 binningRear = m_defaultBinning;
549 binningRight = m_defaultBinning;
550 binningLeft = m_defaultBinning;
551 binningDown = m_defaultBinning;
552 binningUp = m_defaultBinning;
553
554 } else { // TOF
555 m_isTOF = true;
556 NXInt masterPair = firstEntry.openNXInt(m_instrumentName + "/tof/master_pair");
557 masterPair.load();
558
559 const std::string first = std::to_string(masterPair[0]);
560 const std::string second = std::to_string(masterPair[1]);
561 g_log.debug("Master choppers are " + first + " and " + second);
562
563 NXFloat firstChopper = firstEntry.openNXFloat(m_instrumentName + "/chopper" + first + "/sample_distance");
564 firstChopper.load();
565 NXFloat secondChopper = firstEntry.openNXFloat(m_instrumentName + "/chopper" + second + "/sample_distance");
566 secondChopper.load();
567 m_sourcePos = (firstChopper[0] + secondChopper[0]) / 2.;
568 g_log.debug("Source distance computed, moving moderator to Z=-" + std::to_string(m_sourcePos));
569 g_log.debug("Getting wavelength bins from the nexus file...");
570 bool vtof = true;
571 // try VTOF mode
572 try {
573 NXInt channelWidthSum = firstEntry.openNXInt(m_instrumentName + "/tof/chwidth_sum");
574 NXFloat channelWidthTimes = firstEntry.openNXFloat(m_instrumentName + "/tof/chwidth_times");
575 channelWidthSum.load();
576 channelWidthTimes.load();
577 std::string distancePrefix(instrumentAddress + "/tof/tof_distance_detector");
578 binningRear = getVariableTimeBinning(firstEntry, distancePrefix + "1", channelWidthSum, channelWidthTimes);
579 binningRight = getVariableTimeBinning(firstEntry, distancePrefix + "2", channelWidthSum, channelWidthTimes);
580 binningLeft = getVariableTimeBinning(firstEntry, distancePrefix + "3", channelWidthSum, channelWidthTimes);
581 binningDown = getVariableTimeBinning(firstEntry, distancePrefix + "4", channelWidthSum, channelWidthTimes);
582 binningUp = getVariableTimeBinning(firstEntry, distancePrefix + "5", channelWidthSum, channelWidthTimes);
583 } catch (const std::runtime_error &) {
584 vtof = false;
585 }
586 if (!vtof) {
587 try {
588 // LTOF mode
589 std::string binAddressPrefix(instrumentAddress + "/tof/tof_wavelength_detector");
590 binningRear = LoadHelper::getTimeBinningFromNexusAddress(firstEntry, binAddressPrefix + "1");
591 binningRight = LoadHelper::getTimeBinningFromNexusAddress(firstEntry, binAddressPrefix + "2");
592 binningLeft = LoadHelper::getTimeBinningFromNexusAddress(firstEntry, binAddressPrefix + "3");
593 binningDown = LoadHelper::getTimeBinningFromNexusAddress(firstEntry, binAddressPrefix + "4");
594 binningUp = LoadHelper::getTimeBinningFromNexusAddress(firstEntry, binAddressPrefix + "5");
595 } catch (std::runtime_error &e) {
596 throw std::runtime_error("Unable to load the wavelength axes for TOF data " + std::string(e.what()));
597 }
598 }
599 }
600
601 g_log.debug("Loading the data into the workspace...");
602
603 size_t nextIndex = loadDataFromTubes(dataRear, binningRear, 0);
604 nextIndex = loadDataFromTubes(dataRight, binningRight, nextIndex);
605 nextIndex = loadDataFromTubes(dataLeft, binningLeft, nextIndex);
606 nextIndex = loadDataFromTubes(dataDown, binningDown, nextIndex);
607 nextIndex = loadDataFromTubes(dataUp, binningUp, nextIndex);
608 loadDataFromMonitors(firstEntry, nextIndex);
609}
610
618size_t LoadILLSANS::loadDataFromMonitors(Nexus::NXEntry &firstEntry, size_t firstIndex, const MultichannelType type) {
619
620 // let's find the monitors; should be monitor1 and monitor2
621 for (std::vector<NXClassInfo>::const_iterator it = firstEntry.groups().begin(); it != firstEntry.groups().end();
622 ++it) {
623 if (it->nxclass == "NXmonitor") {
624 auto data = LoadHelper::getIntDataset(firstEntry, it->nxname);
625 data.load();
626 g_log.debug() << "Monitor: " << it->nxname << " dims = " << data.dim0() << "x" << data.dim1() << "x"
627 << data.dim2() << '\n';
628 std::vector<double> binning(data.dim2());
629 bool pointData;
630 if (m_isTOF) {
631 binning.push_back(0.0); // bin edges require size to include one more value
632 std::iota(binning.begin(), binning.end(), 0.0);
633 pointData = false;
634 } else {
635 binning = m_defaultBinning;
636 pointData = type == MultichannelType::KINETIC;
637 }
638 LoadHelper::fillStaticWorkspace(m_localWorkspace, data, binning, static_cast<int>(firstIndex), pointData);
639 // Add average monitor counts to a property:
640 double averageMonitorCounts =
641 std::accumulate(data(), data() + data.dim2(), double(0)) / static_cast<double>(data.dim2());
642 // make sure the monitor has values!
643 if (averageMonitorCounts > 0) {
644 API::Run &runDetails = m_localWorkspace->mutableRun();
645 runDetails.addProperty("monitor", averageMonitorCounts, true);
646 }
647 firstIndex++;
648 }
649 }
650 return firstIndex;
651}
652
661size_t LoadILLSANS::loadDataFromD16ScanMonitors(const Nexus::NXEntry &firstEntry, size_t firstIndex,
662 const std::vector<double> &binning) {
663 std::string address = "/data_scan/scanned_variables/data";
664 // It is not possible to ensure that monitors are in the same position in the scanned_variables data table.
665 // Therefore, the order is obtained by getting monitor indices explicitly via getMonitorIndices method.
666 auto scannedVariables = LoadHelper::getDoubleDataset(firstEntry, address);
667 scannedVariables.load();
668 auto monitorNumber = 1; // for the naming of sample log variable
669 for (auto monitorIndex : m_monitorIndices) {
670 auto firstMonitorValuePos = scannedVariables() + monitorIndex * scannedVariables.dim1();
671 const HistogramData::Counts counts(firstMonitorValuePos, firstMonitorValuePos + scannedVariables.dim1());
672 m_localWorkspace->setCounts(firstIndex, counts);
673
674 if ((m_instrumentName == "D16" || m_instrumentName == "D16B") && scannedVariables.dim1() == 1) {
675 // This is the old D16 data scan format, which also covers single-scan D16B data. It is pain.
676 // Due to the fact it was verified with a data structure using binedges rather than points for the wavelength,
677 // we have to keep that and not make it an histogram, because some algorithms later in the reduction process
678 // handle errors completely differently in this case.
679 // We distinguish it from D16 data in the new format but checking there is only one slice of the omega scan
680 const HistogramData::BinEdges binEdges(binning);
681 m_localWorkspace->setBinEdges(firstIndex, binEdges);
682 } else {
683 HistogramData::Points points = HistogramData::Points(binning);
684 m_localWorkspace->setPoints(firstIndex, points);
685 }
686
687 // Add average monitor counts to a property:
688 const auto averageMonitorCounts =
689 std::accumulate(firstMonitorValuePos, firstMonitorValuePos + scannedVariables.dim1(), double(0)) /
690 static_cast<double>(scannedVariables.dim1());
691
692 // make sure the monitor has values!
693 if (averageMonitorCounts > 0) {
694 API::Run &runDetails = m_localWorkspace->mutableRun();
695 runDetails.addProperty("monitor" + std::to_string(monitorNumber), averageMonitorCounts, true);
696 }
697 monitorNumber++;
698 firstIndex++;
699 if (m_instrumentName == "D16") {
700 // the old D16 has 2 monitors, the second being empty but still needing a binning
701
702 if (scannedVariables.dim1() == 1) {
703 const HistogramData::BinEdges binEdges(binning);
704 m_localWorkspace->setBinEdges(firstIndex, binEdges);
705 } else {
706 HistogramData::Points points = HistogramData::Points(binning);
707 m_localWorkspace->setPoints(firstIndex, points);
708 }
709 firstIndex++;
710 }
711 }
712 return firstIndex;
713}
714
723size_t LoadILLSANS::loadDataFromTubes(Nexus::NXInt const &data, const std::vector<double> &timeBinning,
724 size_t firstIndex, const MultichannelType type) {
725
726 size_t numberOfTubes, numberOfChannels, numberOfPixelsPerTube;
727 getDataDimensions(data, numberOfChannels, numberOfTubes, numberOfPixelsPerTube);
728
729 bool pointData = true;
730 std::tuple<short, short, short> dimOrder;
731 if (m_isD16Omega) {
732 dimOrder = std::tuple<short, short, short>{1, 2, 0}; // channels (scans) - tubes - pixels
733 if ((m_instrumentName == "D16" || m_instrumentName == "D16B") && numberOfChannels == 1) { // D16 omega scan data
734 pointData = false;
735 } else { // D16B data
736 pointData = true;
737 }
738 } else {
739 pointData = type == MultichannelType::KINETIC;
740 dimOrder = std::tuple<short, short, short>{0, 1, 2}; // default, tubes-pixels-channels
741 }
742 LoadHelper::fillStaticWorkspace(m_localWorkspace, data, timeBinning, static_cast<int>(firstIndex), pointData,
743 std::vector<int>(), std::set<detid_t>(), dimOrder);
744 return firstIndex + numberOfTubes * numberOfPixelsPerTube;
745}
746
753void LoadILLSANS::createEmptyWorkspace(const size_t numberOfHistograms, const size_t numberOfChannels,
754 const MultichannelType type) {
755 const size_t numberOfElementsInX = numberOfChannels + ((type == MultichannelType::TOF && !m_isD16Omega) ? 1 : 0);
757 WorkspaceFactory::Instance().create("Workspace2D", numberOfHistograms, numberOfElementsInX, numberOfChannels);
758
759 switch (type) {
761 m_localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("Wavelength");
762 break;
764 auto labelX = std::dynamic_pointer_cast<Kernel::Units::Label>(Kernel::UnitFactory::Instance().create("Label"));
765 labelX->setLabel("Omega angle");
766 m_localWorkspace->getAxis(0)->unit() = labelX;
767 break;
768 }
770 break;
771 }
772
773 m_localWorkspace->setYUnitLabel("Counts");
774}
775
782std::string LoadILLSANS::getInstrumentFilePath(const std::string &instName) const {
783
784 std::filesystem::path directory(ConfigService::Instance().getInstrumentDirectory());
785 std::filesystem::path fullPath = directory / (instName + "_Definition.xml");
786 return fullPath.string();
787}
788
793 std::string instrumentPath = m_instrumentName;
794 if (m_resMode == "low") {
795 // low resolution mode we have only defined for the old D11 and D22
796 instrumentPath += "lr";
797 }
798 instrumentPath += "_Definition.xml";
800}
801
807 // Move in Z
808 moveDetectorDistance(detPos.distanceSampleRear, "back_detector");
809 moveDetectorDistance(detPos.distanceSampleBottomTop, "front_detector_top");
810 moveDetectorDistance(detPos.distanceSampleBottomTop, "front_detector_bottom");
811 moveDetectorDistance(detPos.distanceSampleRightLeft, "front_detector_right");
812 moveDetectorDistance(detPos.distanceSampleRightLeft, "front_detector_left");
813 // Move in X
814 moveDetectorHorizontal(detPos.shiftLeft, "front_detector_left");
815 moveDetectorHorizontal(-detPos.shiftRight, "front_detector_right");
816 // Move in Y
817 moveDetectorVertical(detPos.shiftUp, "front_detector_top");
818 moveDetectorVertical(-detPos.shiftDown, "front_detector_bottom");
819 // Set the sample log
820 API::Run &runDetails = m_localWorkspace->mutableRun();
821 runDetails.addProperty<double>("L2", detPos.distanceSampleRear, true);
822}
823
829void LoadILLSANS::moveDetectorDistance(double distance, const std::string &componentName) {
830
831 auto mover = createChildAlgorithm("MoveInstrumentComponent");
833 mover->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
834 mover->setProperty("ComponentName", componentName);
835
836 mover->setProperty("X", pos.X());
837 mover->setProperty("Y", pos.Y());
838 mover->setProperty("Z", distance);
839 mover->setProperty("RelativePosition", false);
840 mover->executeAsChildAlg();
841
842 g_log.debug() << "Moving component '" << componentName << "' to Z = " << distance << '\n';
843}
844
850void LoadILLSANS::rotateInstrument(double angle, const std::string &componentName) {
851 auto rotater = createChildAlgorithm("RotateInstrumentComponent");
852 rotater->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
853 rotater->setProperty("ComponentName", componentName);
854 rotater->setProperty("X", 0.);
855 rotater->setProperty("Y", 1.);
856 rotater->setProperty("Z", 0.);
857 rotater->setProperty("Angle", angle);
858 rotater->setProperty("RelativeRotation", false);
859 rotater->executeAsChildAlg();
860 g_log.debug() << "Rotating component '" << componentName << "' to angle = " << angle << " degrees.\n";
861}
862
869void LoadILLSANS::placeD16(double angle, double distance, const std::string &componentName) {
870 auto mover = createChildAlgorithm("MoveInstrumentComponent");
871 mover->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
872 mover->setProperty("ComponentName", componentName);
873 mover->setProperty("X", sin(angle * M_PI / 180) * distance);
874 mover->setProperty("Y", 0.);
875 mover->setProperty("Z", cos(angle * M_PI / 180) * distance);
876 mover->setProperty("RelativePosition", false);
877 mover->executeAsChildAlg();
878
879 // rotate the detector so it faces the sample.
880 rotateInstrument(angle, componentName);
881 API::Run &runDetails = m_localWorkspace->mutableRun();
882 runDetails.addProperty<double>("L2", distance, true);
883
884 g_log.debug() << "Moving component '" << componentName << "' to angle = " << angle
885 << " degrees and distance = " << distance << "metres.\n";
886}
887
893void LoadILLSANS::moveDetectorHorizontal(double shift, const std::string &componentName) {
894 auto mover = createChildAlgorithm("MoveInstrumentComponent");
896 mover->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
897 mover->setProperty("ComponentName", componentName);
898 mover->setProperty("X", shift);
899 mover->setProperty("Y", pos.Y());
900 mover->setProperty("Z", pos.Z());
901 mover->setProperty("RelativePosition", false);
902 mover->executeAsChildAlg();
903 g_log.debug() << "Moving component '" << componentName << "' to X = " << shift << '\n';
904}
905
911void LoadILLSANS::moveDetectorVertical(double shift, const std::string &componentName) {
912 auto mover = createChildAlgorithm("MoveInstrumentComponent");
914 mover->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
915 mover->setProperty("ComponentName", componentName);
916 mover->setProperty("X", pos.X());
917 mover->setProperty("Y", shift);
918 mover->setProperty("Z", pos.Z());
919 mover->setProperty("RelativePosition", false);
920 mover->executeAsChildAlg();
921 g_log.debug() << "Moving component '" << componentName << "' to Y = " << shift << '\n';
922}
923
929void LoadILLSANS::loadMetaData(const Nexus::NXEntry &entry, const std::string &instrumentNameAddress) {
930
931 g_log.debug("Loading metadata...");
932 API::Run &runDetails = m_localWorkspace->mutableRun();
933
934 if ((entry.getFloat("mode") == 0.0) || (m_instrumentName == "D16")) { // Not TOF
935 runDetails.addProperty<std::string>("tof_mode", "Non TOF");
936 } else {
937 runDetails.addProperty<std::string>("tof_mode", "TOF");
938 }
939
940 double wavelength;
941 if (getPointerToProperty("Wavelength")->isDefault()) {
942 if (m_instrumentName == "D16" || m_instrumentName == "D16B") {
943 wavelength = entry.getFloat(instrumentNameAddress + "/Beam/wavelength");
944 } else {
945 wavelength = entry.getFloat(instrumentNameAddress + "/selector/wavelength");
946 }
947 g_log.debug() << "Wavelength found in the nexus file: " << wavelength << '\n';
948 } else {
949 wavelength = getProperty("Wavelength");
950 }
951
952 // round the wavelength to avoid unnecessary rebinning during merge runs
953 wavelength = std::round(wavelength * 100) / 100.;
954
955 if (wavelength <= 0) {
956 g_log.debug() << "Mode = " << entry.getFloat("mode") << '\n';
957 g_log.information("The wavelength present in the NeXus file <= 0.");
958 if (entry.getFloat("mode") == 0.0) { // Not TOF
959 throw std::runtime_error("Working in Non TOF mode and the wavelength in "
960 "the file is <=0 !!! Check with the instrument "
961 "scientist!");
962 }
963 } else {
964 double wavelengthRes = 10.;
965 const std::string entryResolution = instrumentNameAddress + "/selector/";
966 try {
967 wavelengthRes = entry.getFloat(entryResolution + "wavelength_res");
968 } catch (const std::runtime_error &) {
969 try {
970 wavelengthRes = entry.getFloat(entryResolution + "wave_length_res");
971 } catch (const std::runtime_error &) {
972 if (m_instrumentName == "D16")
973 wavelengthRes = 1;
974 g_log.information() << "Could not find wavelength resolution, assuming " << wavelengthRes << "%.\n";
975 }
976 }
977 // round also the wavelength res to avoid unnecessary rebinning during
978 // merge runs
979 wavelengthRes = std::round(wavelengthRes * 100) / 100.;
980 runDetails.addProperty<double>("wavelength", wavelength);
981 double ei = LoadHelper::calculateEnergy(wavelength);
982 runDetails.addProperty<double>("Ei", ei, true);
983 // wavelength
984 m_defaultBinning[0] = wavelength - wavelengthRes * wavelength * 0.01 / 2;
985 m_defaultBinning[1] = wavelength + wavelengthRes * wavelength * 0.01 / 2;
986 }
987
988 // the start time is needed in the workspace when loading the parameter file
989 std::string startDate = entry.getString("start_time");
990 runDetails.addProperty<std::string>("start_time", LoadHelper::dateTimeInIsoFormat(startDate));
991 // set the facility
992 runDetails.addProperty<std::string>("Facility", std::string("ILL"));
993}
994
999void LoadILLSANS::setFinalProperties(const std::string &filename) {
1000 API::Run &runDetails = m_localWorkspace->mutableRun();
1001 try {
1002 Nexus::File nxHandle(filename, NXaccess::READ);
1003 LoadHelper::addNexusFieldsToWsRun(nxHandle, runDetails);
1004 } catch (Nexus::Exception const &e) {
1005 g_log.debug() << "Failed to open nexus file \"" << filename << "\" in read mode: " << e.what() << "\n";
1006 }
1007}
1008
1014 const auto &specInfo = m_localWorkspace->spectrumInfo();
1015 const double l1 = m_sourcePos;
1016 const size_t nHist = m_localWorkspace->getNumberHistograms();
1018 for (int64_t index = 0; index < static_cast<int64_t>(nHist - m_numberOfMonitors); ++index) {
1019 const double l2 = specInfo.l2(index);
1020 const double z = specInfo.position(index).Z();
1021 auto &x = m_localWorkspace->mutableX(index);
1022 const double scale = (l1 + z) / (l1 + l2);
1023 std::transform(x.begin(), x.end(), x.begin(), [scale](double lambda) { return scale * lambda; });
1024 }
1025
1026 // Try to set sensible (but not strictly physical) wavelength axes for monitors
1027 // Normalisation is done by acquisition time, so these axes should not be used
1028 auto firstPixel = m_localWorkspace->histogram(0).dataX();
1029 const double l2 = specInfo.l2(0);
1030 const double monitor2 = -specInfo.position(nHist - 1).Z();
1031 const double l1Monitor2 = m_sourcePos - monitor2;
1032 const double monScale = (l1 + l2) / l1Monitor2;
1033 std::transform(firstPixel.begin(), firstPixel.end(), firstPixel.begin(),
1034 [monScale](double lambda) { return monScale * lambda; });
1035 for (size_t mIndex = nHist - m_numberOfMonitors; mIndex < nHist; ++mIndex) {
1036 const HistogramData::Counts counts = m_localWorkspace->histogram(mIndex).counts();
1037 const HistogramData::BinEdges binEdges(firstPixel);
1038 m_localWorkspace->setHistogram(mIndex, binEdges, counts);
1039 }
1040}
1041
1047 auto mover = createChildAlgorithm("MoveInstrumentComponent");
1048 mover->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
1049 mover->setProperty("ComponentName", "moderator");
1050 mover->setProperty("X", 0.);
1051 mover->setProperty("Y", 0.);
1052 mover->setProperty("Z", -m_sourcePos);
1053 mover->setProperty("RelativePosition", false);
1054 mover->executeAsChildAlg();
1055}
1056
1064std::vector<double> LoadILLSANS::getOmegaBinning(const NXEntry &entry, const std::string &address) const {
1065
1066 auto scannedValues = LoadHelper::getDoubleDataset(entry, address);
1067 scannedValues.load();
1068
1069 const int64_t nBins = scannedValues.dim1();
1070 std::vector<double> binning(nBins, 0);
1071
1072 for (int64_t i = 0; i < nBins; ++i) {
1073 // for D16, we are only interested in the first line, which contains the omega values
1074 binning[i] = scannedValues(0, i);
1075 }
1076 return binning;
1077}
1078
1087std::vector<double> LoadILLSANS::getVariableTimeBinning(const NXEntry &entry, const std::string &address,
1088 const NXInt &sum, const NXFloat &times) const {
1089 const int64_t nBins = sum.dim0();
1090 std::vector<double> binCenters;
1091 binCenters.reserve(nBins);
1092 NXFloat distance = entry.openNXFloat(address);
1093 distance.load();
1094 for (int64_t bin = 0; bin < nBins; ++bin) {
1095 // sum is in nanoseconds, times is in microseconds
1096 const double tof = sum[bin] * 1E-9 - times[bin] * 1E-6 / 2.;
1097 // velocity in m/s
1098 const double velocity = distance[0] / tof;
1099 // wavelength in AA
1100 const double lambda = PhysicalConstants::h / PhysicalConstants::NeutronMass / velocity * 1E+10;
1101 binCenters.emplace_back(lambda);
1102 }
1103 std::vector<double> binEdges;
1104 binEdges.reserve(nBins + 1);
1105 VectorHelper::convertToBinBoundary(binCenters, binEdges);
1106 // after conversion to bin edges, the first item might get negative,
1107 // which is not physical, set to 0
1108 if (binEdges[0] < 0.) {
1109 binEdges[0] = 0.;
1110 }
1111 return binEdges;
1112}
1113
1114} // namespace Mantid::DataHandling
const std::vector< double > * lambda
std::map< DeltaEMode::Type, std::string > index
#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.
Kernel::Property * getPointerToProperty(const std::string &name) const override
Get a property by name.
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.
void initialize() override
Initialization method invoked by the framework.
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.
Kernel::Logger & g_log
Definition Algorithm.h:422
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
bool execute() override final
The actions to be performed by the algorithm on a dataset.
bool isDefault(const std::string &name) const
void setPropertyValue(const std::string &name, const std::string &value) override
Set the value of a property by string N.B.
@ 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 addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
Definition LogManager.h:91
Helper class for reporting progress from algorithms.
Definition Progress.h:25
This class stores information regarding an experimental run as a series of log entries.
Definition Run.h:35
A property class for workspaces.
LoadILLSANS; supports D11, D22 and D33 (TOF/monochromatic)
Definition LoadILLSANS.h:22
bool m_isTOF
TOF or monochromatic flag.
Definition LoadILLSANS.h:93
void runLoadInstrument()
Loads the instrument from the IDF.
void initWorkSpaceD33(Nexus::NXEntry &, const std::string &)
Loads data for D33.
void getMonitorIndices(const std::string &)
Gets monitor indices from the scanned variables names and sets them in a vector of indices to be used...
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.
size_t loadDataFromTubes(Nexus::NXInt const &, const std::vector< double > &, size_t, const MultichannelType type=MultichannelType::TOF)
Loads data from tubes in scan both mode (channels - tubes - pixels) (D16B)
const std::string name() const override
Algorithm's name for identification.
const std::string summary() const override
Algorithm's summary.
void initWorkSpaceD22B(Nexus::NXEntry &, const std::string &)
LoadILLSANS::initWorkSpaceD22B Load D22B data.
void init() override
Initialize the algorithm's properties.
double m_sourcePos
Source Z (for D33 TOF)
Definition LoadILLSANS.h:94
const std::string category() const override
Algorithm's category for identification.
void setFinalProperties(const std::string &filename)
Sets full sample logs.
size_t loadDataFromD16ScanMonitors(const Nexus::NXEntry &firstEntry, size_t firstIndex, const std::vector< double > &binning)
Load data from D16B's monitor.
std::vector< double > getOmegaBinning(const Nexus::NXEntry &entry, const std::string &address) const
LoadILLSANS::getOmegaBinning Get the binning for an omega scan for D16B files.
void moveDetectorDistance(double distance, const std::string &componentName)
Move detectors in Z axis (X,Y are kept constant)
int version() const override
Algorithm's version for identification.
int confidence(Nexus::NexusDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
void setInstrumentName(const Nexus::NXEntry &, const std::string &)
Set member variable with the instrument name.
void moveSource()
Moves the source to the middle of the two master choppers Used only for D33 in TOF mode.
void loadMetaData(const Nexus::NXEntry &, const std::string &)
Loads some metadata present in the nexus file.
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 applySensitivityMap()
Applies sensitivity map correction to the loaded D16B data.
size_t loadDataFromMonitors(Nexus::NXEntry &firstEntry, size_t firstIndex=0, const MultichannelType type=MultichannelType::TOF)
Loads data from all the monitors.
void moveDetectorVertical(double, const std::string &)
Move detectors in Y.
size_t m_numberOfMonitors
Number of monitors in this instrument.
Definition LoadILLSANS.h:96
void placeD16(double, double, const std::string &)
LoadILLSANS::placeD16 : place the D16 detector.
std::vector< double > m_defaultBinning
the default x-axis binning
Definition LoadILLSANS.h:91
void exec() override
Execute the algorithm.
std::vector< std::string > m_supportedInstruments
List of supported instruments.
Definition LoadILLSANS.h:89
void initWorkSpace(Nexus::NXEntry &, const std::string &)
Loads data for D11, D16 and D22.
void adjustTOF()
Adjusts pixel by pixel the wavelength axis Used only for D33 in TOF mode.
void getDataDimensions(const Nexus::NXInt &data, size_t &numberOfChannels, size_t &numberOfTubes, size_t &numberOfPixelsPerTube)
LoadILLSANS::getDataDimensions Retrieves physical dimensions of the data from the dataset dimensions.
void moveDetectorHorizontal(double, const std::string &)
Move detectors in X.
API::MatrixWorkspace_sptr m_localWorkspace
to-be output workspace
Definition LoadILLSANS.h:90
void initWorkSpaceD11B(Nexus::NXEntry &, const std::string &)
LoadILLSANS::initWorkSpaceD11B Load D11B data.
void rotateInstrument(double, const std::string &)
Rotates instrument detector around y-axis in place.
std::vector< size_t > m_monitorIndices
Indices for monitor data in scanned variables table.
Definition LoadILLSANS.h:97
DetectorPosition getDetectorPositionD33(const Nexus::NXEntry &, const std::string &)
Get detector panel distances from the nexus file.
bool m_isD16Omega
Data comes from a D16 omega scan flag.
Definition LoadILLSANS.h:95
std::string m_instrumentName
Name of the instrument.
Definition LoadILLSANS.h:88
std::string m_resMode
Resolution mode for D11 and D22.
Definition LoadILLSANS.h:92
std::string getInstrumentFilePath(const std::string &) const
Makes up the full path of the relevant IDF dependent on resolution mode.
Loads a workspace from a NeXus Processed entry in a NeXus file.
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:145
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
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:238
constexpr double Y() const noexcept
Get y.
Definition V3D.h:239
constexpr double Z() const noexcept
Get z.
Definition V3D.h:240
Class that provides for a standard Nexus exception.
float getFloat(const std::string &name) const
Returns a float.
std::string getString(const std::string &name) const
Returns a string.
bool containsGroup(const std::string &query) const
Returns whether an individual group (or group) is present.
NXFloat openNXFloat(const std::string &name) const
Creates and opens a float dataset.
std::vector< NXClassInfo > & groups() const
Returns a list of all classes (or groups) in this NXClass.
NXInt openNXInt(const std::string &name) const
Creates and opens an integer dataset.
Templated class implementation of NXDataSet.
void load()
Read all of the datablock in.
dimsize_t dim0() const
Returns the number of elements along the first dimension.
dimsize_t dim2() const
Returns the number of elements along the third dimension.
dimsize_t dim1() const
Returns the number of elements along the second dimension.
Implements NXentry Nexus class.
Implements NXroot Nexus class.
NXEntry openFirstEntry()
Open the first NXentry in the file.
bool isEntry(const std::string &entryName, const std::string &groupClass) const noexcept
Checks if a full-address entry exists for a particular groupClass in a Nexus dataset.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::string getStringFromNexusAddress(const Mantid::Nexus::NXEntry &, const std::string &)
void addNexusFieldsToWsRun(Nexus::File &filehandle, API::Run &runDetails, const std::string &entryName="", bool useFullAddress=false)
Add properties from a nexus file to the workspace run.
double calculateEnergy(double)
Calculate Neutron Energy from wavelength: .
Nexus::NXInt getIntDataset(const Nexus::NXEntry &, const std::string &)
Fetches NXInt data from the requested group name in the entry provided.
Nexus::NXDouble getDoubleDataset(const Nexus::NXEntry &, const std::string &)
Fetches NXDouble data from the requested group name in the entry provided.
std::vector< double > getTimeBinningFromNexusAddress(const Mantid::Nexus::NXEntry &, const std::string &)
Gets the time binning from a Nexus float array Adds an extra bin at the end.
void fillStaticWorkspace(const API::MatrixWorkspace_sptr &, const Mantid::Nexus::NXInt &, const std::vector< double > &xAxis, int64_t initialSpectrum=0, bool pointData=false, const std::vector< detid_t > &detectorIDs=std::vector< int >(), const std::set< detid_t > &acceptedID=std::set< int >(), const std::tuple< short, short, short > &axisOrder=std::tuple< short, short, short >(0, 1, 2))
Fills workspace with histogram data from provided data structure.
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...
Kernel::V3D getComponentPosition(const API::MatrixWorkspace_sptr &ws, const std::string &componentName)
LoadHelper::getComponentPosition.
void loadEmptyInstrument(const API::MatrixWorkspace_sptr &ws, const std::string &instrumentName, const std::string &instrumentAddress="")
Loads empty instrument of chosen name into a provided workspace.
double getDoubleFromNexusAddress(const Mantid::Nexus::NXEntry &, const std::string &)
std::string findInstrumentNexusAddress(const Mantid::Nexus::NXEntry &)
Finds the address for the instrument name in the nexus file Usually of the form: entry0/<NXinstrument...
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.
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.
MANTID_NEXUS_DLL H5::FileAccPropList defaultFileAcc()
Default file access is H5F_CLOSE_STRONG.
Definition H5Util.cpp:119
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