Mantid
Loading...
Searching...
No Matches
LoadLLB.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"
19
20#include <algorithm>
21#include <cmath>
22#include <limits>
23#include <vector>
24
25namespace Mantid::DataHandling {
26
27using namespace Kernel;
28using namespace API;
29using namespace NeXus;
30using namespace HistogramData;
31
33
34//----------------------------------------------------------------------------------------------
38 : m_supportedInstruments{"MIBEMOL"}, m_numberOfTubes{0}, m_numberOfPixelsPerTube{0}, m_numberOfChannels{0},
39 m_numberOfHistograms{0}, m_wavelength{0.0}, m_channelWidth{0.0} {}
40
41//----------------------------------------------------------------------------------------------
43const std::string LoadLLB::name() const { return "LoadLLB"; }
44
46int LoadLLB::version() const { return 1; }
47
49const std::string LoadLLB::category() const { return "DataHandling\\Nexus"; }
50
58 // fields existent only at the LLB
59 if (descriptor.pathExists("/nxentry/program_name") && descriptor.pathExists("/nxentry/subrun_number") &&
60 descriptor.pathExists("/nxentry/total_subruns")) {
61 return 80;
62 } else {
63 return 0;
64 }
65}
66
67//----------------------------------------------------------------------------------------------
68
69//----------------------------------------------------------------------------------------------
73 const std::vector<std::string> exts{".nxs", ".hdf"};
74 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, exts),
75 "The name of the Nexus file to load");
76 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
77 "The name to use for the output workspace");
78}
79
80//----------------------------------------------------------------------------------------------
84
85 std::string filename = getPropertyValue("Filename");
86 NXRoot root(filename);
87 NXEntry entry = root.openFirstEntry();
88 setInstrumentName(entry);
89
90 initWorkSpace(entry);
91 runLoadInstrument(); // just to get IDF
92 loadTimeDetails(entry);
94
95 loadRunDetails(entry);
97
99
100 setProperty("OutputWorkspace", m_localWorkspace);
101}
102
104
105 m_instrumentPath = "nxinstrument";
107
108 if (m_instrumentName.empty()) {
109 throw std::runtime_error("Cannot read the instrument name from the Nexus file!");
110 }
111 g_log.debug() << "Instrument Name: " << m_instrumentName << " in NxPath: " << m_instrumentPath << '\n';
112}
113
115
116 // read in the data
117 NXData dataGroup = entry.openNXData("nxdata");
118 NXInt data = dataGroup.openIntData();
119
120 m_numberOfTubes = static_cast<size_t>(data.dim0());
122 m_numberOfChannels = static_cast<size_t>(data.dim1());
123
124 // dim0 * m_numberOfPixelsPerTube is the total number of detectors
126
127 g_log.debug() << "NumberOfTubes: " << m_numberOfTubes << '\n';
128 g_log.debug() << "NumberOfPixelsPerTube: " << m_numberOfPixelsPerTube << '\n';
129 g_log.debug() << "NumberOfChannels: " << m_numberOfChannels << '\n';
130
131 // Now create the output workspace
132 // Might need to get this value from the number of monitors in the Nexus file
133 // params:
134 // workspace type,
135 // total number of spectra + (number of monitors = 0),
136 // bin boundaries = m_numberOfChannels + 1
137 // Z/time dimension
140 m_localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
141 m_localWorkspace->setYUnitLabel("Counts");
142}
143
145
146 m_wavelength = entry.getFloat("nxbeam/incident_wavelength");
147 // Apparently this is in the wrong units
148 // http://iramis.cea.fr/Phocea/file.php?class=page&reload=1227895533&file=21/How_to_install_and_use_the_Fitmib_suite_v28112008.pdf
149 m_channelWidth = entry.getInt("nxmonitor/channel_width") * 0.1;
150
151 g_log.debug("Nexus Data:");
152 g_log.debug() << " ChannelWidth: " << m_channelWidth << '\n';
153 g_log.debug() << " Wavelength: " << m_wavelength << '\n';
154}
155
157
158 // read in the data
159 NXData dataGroup = entry.openNXData("nxdata");
160 NXFloat data = dataGroup.openFloatData();
161 data.load();
162
163 // EPP
164 int calculatedDetectorElasticPeakPosition = getDetectorElasticPeakPosition(data);
165
166 // Assign time bin to first X entry
167 setTimeBinning(m_localWorkspace->mutableX(0), calculatedDetectorElasticPeakPosition, m_channelWidth);
168
170 size_t spec = 0;
171 for (size_t i = 0; i < m_numberOfTubes; ++i) {
172 for (size_t j = 0; j < m_numberOfPixelsPerTube; ++j) {
173 float *data_p = &data(static_cast<int>(i), static_cast<int>(j));
174 m_localWorkspace->setHistogram(spec++, m_localWorkspace->binEdges(0),
175 Counts(data_p, data_p + m_numberOfChannels));
176 progress.report();
177 }
178 }
179
180 g_log.debug() << "Data loading inti WS done....\n";
181}
182
184
185 std::vector<int> cumulatedSumOfSpectras(m_numberOfChannels, 0);
186 for (size_t i = 0; i < m_numberOfTubes; i++) {
187 const float *data_p = &data(static_cast<int>(i), 0);
188 float currentSpec = 0;
189
190 for (size_t j = 0; j < m_numberOfChannels; ++j)
191 currentSpec += data_p[j];
192
193 if (i > 0) {
194 cumulatedSumOfSpectras[i] = cumulatedSumOfSpectras[i - 1] + static_cast<int>(currentSpec);
195 } else {
196 cumulatedSumOfSpectras[i] = static_cast<int>(currentSpec);
197 }
198 }
199 auto it = std::max_element(cumulatedSumOfSpectras.begin(), cumulatedSumOfSpectras.end());
200
201 int calculatedDetectorElasticPeakPosition;
202 if (it == cumulatedSumOfSpectras.end()) {
203 throw std::runtime_error("No Elastic peak position found while analyzing the data!");
204 } else {
205 // calculatedDetectorElasticPeakPosition = *it;
206 calculatedDetectorElasticPeakPosition = static_cast<int>(std::distance(cumulatedSumOfSpectras.begin(), it));
207
208 if (calculatedDetectorElasticPeakPosition == 0) {
209 throw std::runtime_error("No Elastic peak position found while analyzing "
210 "the data. Elastic peak position is ZERO!");
211 } else {
212 g_log.debug() << "Calculated Detector EPP: " << calculatedDetectorElasticPeakPosition << '\n';
213 }
214 }
215 return calculatedDetectorElasticPeakPosition;
216}
217
218void LoadLLB::setTimeBinning(HistogramX &histX, int elasticPeakPosition, double channelWidth) {
219
220 double l1 = m_localWorkspace->spectrumInfo().l1();
221 double l2 = m_localWorkspace->spectrumInfo().l2(1);
222
223 double theoreticalElasticTOF =
225
226 g_log.debug() << "elasticPeakPosition : " << static_cast<float>(elasticPeakPosition) << '\n';
227 g_log.debug() << "l1 : " << l1 << '\n';
228 g_log.debug() << "l2 : " << l2 << '\n';
229 g_log.debug() << "theoreticalElasticTOF : " << theoreticalElasticTOF << '\n';
230
231 for (size_t i = 0; i < m_numberOfChannels + 1; ++i) {
232 histX[i] = theoreticalElasticTOF + channelWidth * static_cast<double>(static_cast<int>(i) - elasticPeakPosition) -
233 channelWidth / 2; // to make sure the bin is in the middle of the elastic peak
234 }
235}
236
238
239 API::Run &runDetails = m_localWorkspace->mutableRun();
240
241 // int runNum = entry.getInt("run_number");
242 // std::string run_num = boost::lexical_cast<std::string>(runNum);
243 // runDetails.addProperty("run_number", run_num);
244
245 std::string start_time = entry.getString("start_time");
246 // start_time = getDateTimeInIsoFormat(start_time);
247 runDetails.addProperty("run_start", start_time);
248
249 std::string end_time = entry.getString("end_time");
250 // end_time = getDateTimeInIsoFormat(end_time);
251 runDetails.addProperty("run_end", end_time);
252
253 double wavelength = entry.getFloat("nxbeam/incident_wavelength");
254 runDetails.addProperty<double>("wavelength", wavelength);
255
256 double energy = LoadHelper::calculateEnergy(wavelength);
257 runDetails.addProperty<double>("Ei", energy, true); // overwrite
258
259 std::string title = entry.getString("title");
260 runDetails.addProperty("title", title);
261 m_localWorkspace->setTitle(title);
262}
263
264/*
265 * Load data about the Experiment.
266 *
267 * TODO: This is very incomplete. In ISIS they much more info in the nexus file
268 *than ILL.
269 *
270 * @param entry :: The Nexus entry
271 */
273
274 // TODO: Do the rest
275 // Pick out the geometry information
276
277 (void)entry;
278
279 // std::string description = boost::lexical_cast<std::string>(
280 // entry.getFloat("sample/description"));
281 //
282 // m_localWorkspace->mutableSample().setName(description);
283
284 // m_localWorkspace->mutableSample().setThickness(static_cast<double>
285 //(isis_raw->spb.e_thick));
286 // m_localWorkspace->mutableSample().setHeight(static_cast<double>
287 //(isis_raw->spb.e_height));
288 // m_localWorkspace->mutableSample().setWidth(static_cast<double>
289 //(isis_raw->spb.e_width));
290}
291
296
297 auto loadInst = createChildAlgorithm("LoadInstrument");
298
299 // Now execute the Child Algorithm. Catch and log any error, but don't stop.
300 try {
301
302 // TODO: depending on the m_numberOfPixelsPerTube we might need to load a
303 // different IDF
304
305 loadInst->setPropertyValue("InstrumentName", m_instrumentName);
306 loadInst->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
307 loadInst->setProperty("RewriteSpectraMap", Mantid::Kernel::OptionalBool(true));
308 loadInst->execute();
309 } catch (...) {
310 g_log.information("Cannot load the instrument definition.");
311 }
312}
313
314} // namespace Mantid::DataHandling
double energy
Definition: GetAllEi.cpp:157
#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.
LoadLLB : Loads an LLB MIBEMOL TOF NeXus file into a Workspace2D with the given name.
Definition: LoadLLB.h:21
void exec() override
Execute the algorithm.
Definition: LoadLLB.cpp:83
int getDetectorElasticPeakPosition(const NeXus::NXFloat &)
Definition: LoadLLB.cpp:183
void initWorkSpace(NeXus::NXEntry &)
Definition: LoadLLB.cpp:114
std::string m_instrumentName
Definition: LoadLLB.h:51
void setTimeBinning(HistogramData::HistogramX &histX, int, double)
Definition: LoadLLB.cpp:218
int version() const override
Algorithm's version for identification.
Definition: LoadLLB.cpp:46
const std::string category() const override
Algorithm's category for identification.
Definition: LoadLLB.cpp:49
void loadTimeDetails(const NeXus::NXEntry &entry)
Definition: LoadLLB.cpp:144
void loadRunDetails(const NeXus::NXEntry &)
Definition: LoadLLB.cpp:237
std::string m_instrumentPath
Name of the instrument path.
Definition: LoadLLB.h:52
const std::string name() const override
Algorithm's name for identification.
Definition: LoadLLB.cpp:43
int confidence(Kernel::NexusDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
Definition: LoadLLB.cpp:57
void loadDataIntoTheWorkSpace(NeXus::NXEntry &)
Definition: LoadLLB.cpp:156
void init() override
Initialize the algorithm's properties.
Definition: LoadLLB.cpp:72
void setInstrumentName(const NeXus::NXEntry &entry)
Definition: LoadLLB.cpp:103
API::MatrixWorkspace_sptr m_localWorkspace
Definition: LoadLLB.h:54
void runLoadInstrument()
Run the Child Algorithm LoadInstrument.
Definition: LoadLLB.cpp:295
void loadExperimentDetails(NeXus::NXEntry &)
Definition: LoadLLB.cpp:272
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
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
int getInt(const std::string &name) const
Returns a int.
float getFloat(const std::string &name) const
Returns a float.
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 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
NXFloat openFloatData()
Opens data of float type.
Definition: NexusClasses.h:826
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
double calculateTOF(double, double)
Calculate TOF from distance.
Definition: LoadHelper.cpp:94
@ Output
An output workspace.
Definition: Property.h:54