Mantid
Loading...
Searching...
No Matches
LoadMLZ.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#include "MantidAPI/Axis.h"
11#include "MantidAPI/Progress.h"
22
23#include <algorithm>
24#include <cmath>
25#include <limits>
26#include <vector>
27
28namespace Mantid::DataHandling {
29
30using namespace Kernel;
31using namespace API;
32using namespace NeXus;
33using HistogramData::BinEdges;
34using HistogramData::Counts;
35
36// Register the algorithm into the AlgorithmFactory
38
39
42 : m_numberOfTubes{0}, m_numberOfPixelsPerTube{0}, m_numberOfChannels{0}, m_numberOfHistograms{0},
43 m_monitorElasticPeakPosition{0}, m_wavelength{0.0}, m_channelWidth{0.0}, m_timeOfFlightDelay{0.0},
44 m_monitorCounts{0}, m_chopper_speed{0.0}, m_chopper_ratio{0}, m_l1{0.0}, m_l2{0.0}, m_t1{0.0},
45 m_supportedInstruments{"TOFTOF", "DNS"} {}
46
48const std::string LoadMLZ::name() const { return "LoadMLZ"; }
49
51int LoadMLZ::version() const { return 1; }
52
54const std::string LoadMLZ::category() const { return "DataHandling\\Nexus"; }
55
59 const std::vector<std::string> exts{".nxs", ".hdf", ".hd5"};
60 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, exts),
61 "File path of the Data file to load");
62
63 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
64 "The name to use for the output workspace");
65}
66
70 // Retrieve filename
71 std::string filenameData = getPropertyValue("Filename");
72
73 // open the root node
74 NeXus::NXRoot dataRoot(filenameData);
75 NXEntry dataFirstEntry = dataRoot.openFirstEntry();
76
77 loadInstrumentDetails(dataFirstEntry);
78 loadTimeDetails(dataFirstEntry);
79
80 initWorkSpace(dataFirstEntry);
81
82 // load the instrument from the IDF
85
86 loadDataIntoTheWorkSpace(dataFirstEntry);
87 loadRunDetails(dataFirstEntry); // must run after runLoadInstrument
88 loadExperimentDetails(dataFirstEntry);
89 maskDetectors(dataFirstEntry);
90
91 setProperty("OutputWorkspace", m_localWorkspace);
92}
93
101 // fields existent only at the MLZ
102 if (descriptor.pathExists("/Scan/wavelength") && descriptor.pathExists("/Scan/title") &&
103 descriptor.pathExists("/Scan/mode")) {
104 return 80;
105 } else {
106 return 0;
107 }
108}
109
114 // path to the pixel_mask
115 std::string pmpath = "instrument/detector/pixel_mask";
116
117 NeXus::NXInt pmdata = entry.openNXInt(pmpath);
118 // load the counts from the file into memory
119 pmdata.load();
120 g_log.debug() << "PMdata size: " << pmdata.size() << '\n';
121 std::vector<int> masked_detectors(pmdata(), pmdata() + pmdata.size());
122
123 g_log.debug() << "Number of masked detectors: " << masked_detectors.size() << '\n';
124
125 auto &detInfo = m_localWorkspace->mutableDetectorInfo();
126 std::vector<size_t> indicesToMask;
127 for (auto masked_detector : masked_detectors) {
128 g_log.debug() << "List of masked detectors: ";
129 g_log.debug() << masked_detector;
130 g_log.debug() << ", ";
131 try {
132 indicesToMask.emplace_back(detInfo.indexOf(masked_detector));
133 } catch (std::out_of_range &) {
134 g_log.warning() << "Invalid detector ID " << masked_detector << ". Found while running LoadMLZ\n";
135 }
136 }
137 g_log.debug() << '\n';
138
139 for (const auto index : indicesToMask)
140 detInfo.setMasked(index, true);
141}
142
147
149
150 if (m_instrumentPath.empty()) {
151 throw std::runtime_error("Cannot set the instrument name from the Nexus file!");
152 }
153
155
156 if (std::find(m_supportedInstruments.begin(), m_supportedInstruments.end(), m_instrumentName) ==
158 std::string message = "The instrument " + m_instrumentName + " is not valid for this loader!";
159 throw std::runtime_error(message);
160 }
161
162 g_log.debug() << "Instrument name set to: " + m_instrumentName << '\n';
163}
164
172void LoadMLZ::initWorkSpace(NeXus::NXEntry &entry) //, const std::vector<std::vector<int> >&monitors)
173{
174 // read in the data
175 NXData dataGroup = entry.openNXData("data");
176 NXInt data = dataGroup.openIntData();
177
178 m_numberOfTubes = static_cast<size_t>(data.dim0());
179 m_numberOfPixelsPerTube = static_cast<size_t>(data.dim1());
180 m_numberOfChannels = static_cast<size_t>(data.dim2());
182
183 g_log.debug() << "NumberOfTubes: " << m_numberOfTubes << '\n';
184 g_log.debug() << "NumberOfPixelsPerTube: " << m_numberOfPixelsPerTube << '\n';
185 g_log.debug() << "NumberOfChannels: " << m_numberOfChannels << '\n';
186
187 // Now create the output workspace
190 m_localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
191 m_localWorkspace->setYUnitLabel("Counts");
192}
193
199 // Read data from IDF: distance source-sample and distance sample-detectors
200 m_l1 = m_localWorkspace->spectrumInfo().l1();
201 m_l2 = m_localWorkspace->spectrumInfo().l2(1);
202
203 g_log.debug() << "L1: " << m_l1 << ", L2: " << m_l2 << '\n';
204}
205
211
212 m_wavelength = entry.getFloat("wavelength");
213
214 // Monitor can be monitor or Monitor
215 std::string monitorName;
216 if (entry.containsGroup("monitor"))
217 monitorName = "monitor";
218 else if (entry.containsGroup("Monitor"))
219 monitorName = "Monitor";
220 else {
221 std::string message("Cannot find monitor/Monitor in the Nexus file!");
222 g_log.error(message);
223 throw std::runtime_error(message);
224 }
225
226 m_monitorCounts = entry.getInt(monitorName + "/integral");
227
228 m_monitorElasticPeakPosition = entry.getInt(monitorName + "/elastic_peak");
229
230 NXFloat time_of_flight_data = entry.openNXFloat(monitorName + "/time_of_flight");
231 time_of_flight_data.load();
232
233 // The entry "monitor/time_of_flight", has 3 fields:
234 // channel width [microseconds], number of channels, Time of flight delay
235 m_channelWidth = time_of_flight_data[0] * 50.e-3;
236 m_timeOfFlightDelay = time_of_flight_data[2] * 50.e-3;
237
238 g_log.debug("Nexus Data:");
239 g_log.debug() << " MonitorCounts: " << m_monitorCounts << '\n';
240 g_log.debug() << " ChannelWidth (microseconds): " << m_channelWidth << '\n';
241 g_log.debug() << " Wavelength (angstroems): " << m_wavelength << '\n';
242 g_log.debug() << " ElasticPeakPosition: " << m_monitorElasticPeakPosition << '\n';
243 g_log.debug() << " TimeOfFlightDelay (microseconds): " << m_timeOfFlightDelay << '\n';
244
245 m_chopper_speed = entry.getFloat("instrument/chopper/rotation_speed");
246
247 m_chopper_ratio = entry.getInt("instrument/chopper/ratio");
248
249 g_log.debug() << " ChopperSpeed: " << m_chopper_speed << '\n';
250 g_log.debug() << " ChopperRatio: " << m_chopper_ratio << '\n';
251}
252
261
262 API::Run &runDetails = m_localWorkspace->mutableRun();
263
264 std::string runNum = entry.getString("entry_identifier"); // run_number");
265 std::string run_num = boost::lexical_cast<std::string>(runNum);
266 runDetails.addProperty("run_number", run_num);
267
268 std::string start_time = entry.getString("start_time");
269 runDetails.addProperty("run_start", start_time);
270
271 std::string end_time = entry.getString("end_time");
272 runDetails.addProperty("run_end", end_time);
273
274 runDetails.addProperty("wavelength", m_wavelength, "Angstrom", true);
275
277 runDetails.addProperty<double>("Ei", ei, "meV", true); // overwrite
278
279 int duration = entry.getInt("duration");
280 runDetails.addProperty("duration", duration, "Seconds", true);
281
282 std::string mode = entry.getString("mode");
283 runDetails.addProperty("mode", mode);
284
285 std::string title = entry.getString("title");
286 m_localWorkspace->setTitle(title);
287
288 // Check if temperature is defined
289 NXClass sample = entry.openNXGroup("sample");
290 if (sample.containsDataSet("temperature")) {
291 double temperature = entry.getFloat("sample/temperature");
292 runDetails.addProperty("temperature", temperature, "K", true);
293 }
294
295 runDetails.addProperty("monitor_counts", static_cast<double>(m_monitorCounts));
296 runDetails.addProperty("chopper_speed", m_chopper_speed);
297 runDetails.addProperty("chopper_ratio", m_chopper_ratio);
298 runDetails.addProperty("channel_width", m_channelWidth, "microseconds", true);
299
300 // Calculate number of full time channels - use to crop workspace - S. Busch's
301 // method
302 double full_channels =
303 floor(30. * m_chopper_ratio / (m_chopper_speed)*1.e6 / m_channelWidth); // channelWidth in microsec.
304 runDetails.addProperty("full_channels", full_channels);
305
306 // Proposal title
307 std::string proposal_title = entry.getString("proposal");
308 runDetails.addProperty("proposal_title", proposal_title);
309
310 // proposal number
311 std::string proposal_number = entry.getString("proposal_number");
312 runDetails.addProperty("proposal_number", proposal_number);
313
314 // users
315 std::string user_name = entry.getString("user2/name");
316 runDetails.addProperty("experiment_team", user_name);
317
318 runDetails.addProperty("EPP", m_monitorElasticPeakPosition);
319 runDetails.addProperty("TOF1", m_t1, "microseconds", true);
320
321 // set instrument parameter Efixed, catch error, but don't stop
322 try {
323 auto setPar = createChildAlgorithm("SetInstrumentParameter");
324 setPar->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
325 setPar->setProperty("ParameterName", "Efixed");
326 setPar->setProperty("ParameterType", "Number");
327 setPar->setProperty("Value", std::to_string(ei));
328 setPar->execute();
329 } catch (...) {
330 g_log.warning("Cannot set the instrument parameter Efixed.");
331 }
332}
333
342 // TODO: Do the rest
343 // Pick out the geometry information
344
345 std::string description = boost::lexical_cast<std::string>(entry.getFloat("sample/description"));
346
347 m_localWorkspace->mutableSample().setName(description);
348}
349
356 // read in the data
357 NXData dataGroup = entry.openNXData("data");
358 NXInt data = dataGroup.openIntData();
359 data.load();
360
362 g_log.debug() << " t1 (microseconds): " << m_t1 << '\n';
363
364 std::vector<double> detectorTofBins(m_numberOfChannels + 1);
365 for (size_t i = 0; i < m_numberOfChannels + 1; ++i) {
366 detectorTofBins[i] = m_channelWidth * static_cast<double>(static_cast<int>(i)) + m_t1 + m_channelWidth / 2;
367 }
368
369 // Assign calculated bins to first X axis
370 BinEdges edges(std::move(detectorTofBins));
371
373 size_t spec = 0;
374 for (size_t i = 0; i < m_numberOfTubes; ++i) {
375 for (size_t j = 0; j < m_numberOfPixelsPerTube; ++j) {
376 // Assign Y
377 int *data_p = &data(static_cast<int>(i), static_cast<int>(j), 0);
378
379 m_localWorkspace->setHistogram(spec, edges, Counts(data_p, data_p + m_numberOfChannels));
380
381 ++spec;
382 progress.report();
383 }
384 }
385}
386
391 auto loadInst = createChildAlgorithm("LoadInstrument");
392
393 // Now execute the Child Algorithm. Catch and log any error, but don't stop.
394 try {
395 loadInst->setPropertyValue("InstrumentName", m_instrumentName);
396 g_log.debug() << "InstrumentName" << m_instrumentName << '\n';
397 loadInst->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
398 loadInst->setProperty("RewriteSpectraMap", Mantid::Kernel::OptionalBool(true));
399 loadInst->execute();
400 } catch (...) {
401 g_log.warning("Cannot load the instrument definition.");
402 }
403}
404
405} // namespace Mantid::DataHandling
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#define DECLARE_NEXUS_FILELOADER_ALGORITHM(classname)
DECLARE_NEXUS_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro wh...
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
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.
LoadMLZ : Loads MLZ nexus or hdf file into a Mantid workspace.
Definition: LoadMLZ.h:22
void loadDataIntoTheWorkSpace(NeXus::NXEntry &entry)
Loads all the spectra into the workspace, including that from the monitor.
Definition: LoadMLZ.cpp:355
void loadTimeDetails(const NeXus::NXEntry &entry)
Load the time details from the nexus file.
Definition: LoadMLZ.cpp:210
API::MatrixWorkspace_sptr m_localWorkspace
Definition: LoadMLZ.h:56
void exec() override
Execute the algorithm.
Definition: LoadMLZ.cpp:69
void loadInstrumentDetails(const NeXus::NXEntry &)
Set the instrument name along with its path on the nexus file.
Definition: LoadMLZ.cpp:146
std::string m_instrumentName
Name of the instrument.
Definition: LoadMLZ.h:58
const std::string name() const override
Algorithm's name for identification.
Definition: LoadMLZ.cpp:48
std::string m_instrumentPath
Name of the instrument path.
Definition: LoadMLZ.h:59
void loadExperimentDetails(const NeXus::NXEntry &entry)
Load data about the Experiment.
Definition: LoadMLZ.cpp:341
int version() const override
Algorithm's version for identification.
Definition: LoadMLZ.cpp:51
void maskDetectors(const NeXus::NXEntry &entry)
Loads Masked detectors from the /Scan/instrument/Detector/pixel_mask.
Definition: LoadMLZ.cpp:113
void initInstrumentSpecific()
Function to do specific instrument stuff.
Definition: LoadMLZ.cpp:198
void loadRunDetails(NeXus::NXEntry &entry)
Load information about the run.
Definition: LoadMLZ.cpp:260
void initWorkSpace(NeXus::NXEntry &entry)
Creates the workspace and initialises member variables with the corresponding values.
Definition: LoadMLZ.cpp:172
int confidence(Kernel::NexusDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
Definition: LoadMLZ.cpp:100
void init() override
Initialize the algorithm's properties.
Definition: LoadMLZ.cpp:58
void runLoadInstrument()
Run the Child Algorithm LoadInstrument.
Definition: LoadMLZ.cpp:390
std::vector< std::string > m_supportedInstruments
Definition: LoadMLZ.h:81
const std::string category() const override
Algorithm's category for identification.
Definition: LoadMLZ.cpp:54
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
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
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
The base class for a Nexus class (group).
Definition: NexusClasses.h:487
int getInt(const std::string &name) const
Returns a int.
NXInt openNXInt(const std::string &name) const
Creates and opens an integer dataset.
Definition: NexusClasses.h:546
NXClass openNXGroup(const std::string &name) const
Creates and opens an arbitrary (non-standard) class (group).
Definition: NexusClasses.h:529
bool containsGroup(const std::string &query) const
Returns whether an individual group (or group) is present.
bool containsDataSet(const std::string &query) const
Returns whether an individual dataset is present.
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 size() const
Returns the size of the data buffer.
Definition: NexusClasses.h:267
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
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::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
double calculateTOF(double, double)
Calculate TOF from distance.
Definition: LoadHelper.cpp:94
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Output
An output workspace.
Definition: Property.h:54