Mantid
Loading...
Searching...
No Matches
LoadMuonNexusV2NexusHelper.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2020 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 +
9#include "MantidAPI/Run.h"
10#include "MantidAPI/TableRow.h"
14
15#include <algorithm>
16
17namespace {
18template <typename type> std::string convertVectorToString(const std::vector<type> &vector) {
19 std::string stringOfVector = "";
20 for (const auto &value : vector) {
21 stringOfVector += std::to_string(value) + ";";
22 }
23 return stringOfVector.substr(0, stringOfVector.size() - 1);
24}
25} // namespace
26
27namespace Mantid::DataHandling {
28
29namespace NeXusEntry {
30const std::string GOODFRAMES{"good_frames"};
31const std::string DETECTOR{"instrument/detector_1"};
32const std::string PERIOD{"periods"};
33const std::string ORIENTATON{"instrument/detector_1/orientation"};
34const std::string RESOLUTION{"resolution"};
35const std::string GROUPING{"grouping"};
36const std::string DEADTIME{"dead_time"};
37const std::string COUNTS{"counts"};
38const std::string FIRSTGOODBIN{"first_good_bin"};
39const std::string LASTGOODBIN{"last_good_bin"};
40const std::string TIMEZERO{"time_zero"};
41const std::string SAMPLE{"sample"};
42const std::string TEMPERATURE{"temperature"};
43const std::string MAGNETICFIELD{"magnetic_field"};
44const std::string RAWDATA{"/raw_data_1"};
45const std::string SEQUENCES{"sequences"};
46const std::string TYPE{"type"};
47const std::string REQUESTED{"frames_requested"};
48const std::string RAWFRAMES{"raw_frames"};
49const std::string PERIODOUTPUT{"output"};
50const std::string PERIODCOUNTS{"total_counts"};
51} // namespace NeXusEntry
52
53using namespace NeXus;
54using namespace Kernel;
55using namespace API;
56using namespace NeXus;
57using namespace HistogramData;
58using std::size_t;
59using namespace DataObjects;
60
62
63// Loads the good frames from the Muon Nexus V2 entry
65
66 if (!isFileMultiPeriod) {
67 try {
69 goodFrames.load();
70 return goodFrames;
71 } catch (std::runtime_error &) {
72 throw std::runtime_error("Could not load good frames data from nexus file, check Nexus file");
73 }
74 } else {
75 try {
77 // For multiperiod datasets, read raw_data_1/periods/good_frames
78 NXInt goodFrames = periodClass.openNXInt(NeXusEntry::GOODFRAMES);
79 goodFrames.load();
80 return goodFrames;
81 } catch (std::runtime_error &) {
82 throw std::runtime_error("Could not load good frames data from nexus file, check Nexus file");
83 }
84 }
85}
86// Loads the detector grouping from the Muon Nexus V2 entry
87// NOTE: Currently, the Muon Nexus V2 files do not implement grouping.
88// The method implemented here assumes that once implemented
89// each detector will map to a single group. If this is not the case,
90// the method will need to be altered.
91std::vector<detid_t>
92LoadMuonNexusV2NexusHelper::loadDetectorGroupingFromNexus(const std::vector<detid_t> &detectorsLoaded,
93 bool isFileMultiPeriod, int periodNumber) {
94 // We cast the numLoadedDetectors to an int, which is the index type used for
95 // Nexus Data sets. As detectorsLoaded is derived from a nexus entry we
96 // can be certain we won't overflow the integer type.
97 int numLoadedDetectors = static_cast<int>(detectorsLoaded.size());
98 std::vector<detid_t> grouping;
99 grouping.reserve(numLoadedDetectors);
100 // Open nexus entry
102 if (detectorGroup.containsDataSet(NeXusEntry::GROUPING)) {
103 NXInt groupingData = detectorGroup.openNXInt(NeXusEntry::GROUPING);
104 groupingData.load();
105 int groupingOffset = !isFileMultiPeriod ? 0 : (numLoadedDetectors) * (periodNumber - 1);
106 std::transform(detectorsLoaded.cbegin(), detectorsLoaded.cend(), std::back_inserter(grouping),
107 [&groupingData, groupingOffset](const auto detectorNumber) {
108 return groupingData[detectorNumber - 1 + groupingOffset];
109 });
110 }
111 return grouping;
112}
114 std::string mainFieldDirection = "Longitudinal"; // default
115 try {
117 // some files have no data there
118 orientation.load();
119 if (orientation[0] == 't') {
120 mainFieldDirection = "Transverse";
121 }
122 } catch (std::runtime_error &) {
123 // no data - assume main field was longitudinal and continue.
124 }
125 return mainFieldDirection;
126}
127// Loads dead times from the nexus file
128// Assumes one grouping entry per detector
129std::vector<double> LoadMuonNexusV2NexusHelper::loadDeadTimesFromNexus(const std::vector<detid_t> &loadedDetectors,
130 bool isFileMultiPeriod, int periodNumber) {
131 // We cast the numLoadedDetectors to an int, which is the index type used for
132 // Nexus Data sets. As loadedDectors is derived from a nexus entry we
133 // can be certain we won't overflow the integer type.
134 int numLoadedDetectors = static_cast<int>(loadedDetectors.size());
135 std::vector<double> deadTimes;
136 deadTimes.reserve(numLoadedDetectors);
137
139 if (detectorGroup.containsDataSet(NeXusEntry::DEADTIME)) {
140 NXFloat deadTimesData = detectorGroup.openNXFloat(NeXusEntry::DEADTIME);
141 deadTimesData.load();
142 // If we have a multi period file all the data will be stored in a single
143 // nexus entry of length (num_periods * numDetectors)
144 // So if we are load the second period we need to offset our indexes by
145 // (1*numDetectors)
146 int deadTimeOffset = !isFileMultiPeriod ? 0 : (numLoadedDetectors) * (periodNumber - 1);
147 std::transform(loadedDetectors.cbegin(), loadedDetectors.cend(), std::back_inserter(deadTimes),
148 [deadTimesData, deadTimeOffset](const auto detectorNumber) {
149 return deadTimesData[detectorNumber - 1 + deadTimeOffset];
150 });
151 }
152 return deadTimes;
153}
154
156 try {
158 NXInfo infoResolution = detectorEntry.getDataSetInfo(NeXusEntry::RESOLUTION);
159 NXInt counts = detectorEntry.openNXInt(NeXusEntry::COUNTS);
160 std::string firstGoodBin = counts.attributes(NeXusEntry::FIRSTGOODBIN);
161 double resolution;
162 switch (infoResolution.type) {
163 case NX_FLOAT32:
164 resolution = static_cast<double>(detectorEntry.getFloat(NeXusEntry::RESOLUTION));
165 break;
166 case NX_INT32:
167 resolution = static_cast<double>(detectorEntry.getInt(NeXusEntry::RESOLUTION));
168 break;
169 default:
170 throw std::runtime_error("Unsupported data type for resolution");
171 }
172 double bin = static_cast<double>(boost::lexical_cast<int>(firstGoodBin));
173 double bin_size = resolution / 1000000.0;
174 return bin * bin_size;
175 } catch (std::runtime_error &) {
176 throw std::runtime_error("Error loading FirstGoodData, check Nexus file");
177 }
178}
179
181 try {
183 NXInfo infoResolution = detectorEntry.getDataSetInfo(NeXusEntry::RESOLUTION);
184 NXInt counts = detectorEntry.openNXInt(NeXusEntry::COUNTS);
185 std::string lastGoodBin = counts.attributes(NeXusEntry::LASTGOODBIN);
186 double resolution;
187 switch (infoResolution.type) {
188 case NX_FLOAT32:
189 resolution = static_cast<double>(detectorEntry.getFloat(NeXusEntry::RESOLUTION));
190 break;
191 case NX_INT32:
192 resolution = static_cast<double>(detectorEntry.getInt(NeXusEntry::RESOLUTION));
193 break;
194 default:
195 throw std::runtime_error("Unsupported data type for resolution");
196 }
197 double bin = static_cast<double>(boost::lexical_cast<int>(lastGoodBin));
198 double bin_size = resolution / 1000000.0;
199 return bin * bin_size;
200 } catch (std::runtime_error &) {
201 throw std::runtime_error("Error loading LastGoodData, check Nexus file");
202 }
203}
204
206 try {
208 double timeZero = static_cast<double>(detectorEntry.getFloat(NeXusEntry::TIMEZERO));
209 return timeZero;
210 } catch (std::runtime_error &) {
211 throw std::runtime_error("Could not load time zero, check Nexus file");
212 }
213}
214
215std::vector<double> LoadMuonNexusV2NexusHelper::loadTimeZeroListFromNexusFile(size_t numSpectra) {
217
218 NXDouble timeZeroClass = det_class.openNXDouble(NeXusEntry::TIMEZERO);
219 std::vector<double> timeZeroVector = timeZeroClass.vecBuffer();
220 if (timeZeroVector.size() == 0) {
221 double timeZero = static_cast<double>(det_class.getFloat(NeXusEntry::TIMEZERO));
222 timeZeroVector = std::vector<double>(numSpectra, timeZero);
223 } else if (timeZeroVector.size() != numSpectra) {
224 throw std::runtime_error("Time zero list size does not match number of "
225 "spectra, check Nexus file.");
226 }
227 // We assume that this spectrum list increases monotonically
228 return timeZeroVector;
229}
230
232 auto runSample = m_entry.openNXGroup(NeXusEntry::SAMPLE);
233 MuonNexus::SampleInformation sampleInformation;
234 try {
235 sampleInformation.magneticField = runSample.getFloat(NeXusEntry::MAGNETICFIELD);
236 sampleInformation.temperature = runSample.getFloat(NeXusEntry::TEMPERATURE);
237 } catch (std::runtime_error &) {
238 throw std::runtime_error("Could not load sample information (temperature "
239 "and magnetic field) from nexus entry");
240 }
241 return sampleInformation;
242}
243
246 return periodClass.getInt("number");
247}
248
251 return periodClass.getString("labels");
252}
253
254std::vector<int> LoadMuonNexusV2NexusHelper::getIntVector(const int &numPeriods, const std::string &name) const {
256
257 NXInt dataClass = periodClass.openNXInt(name);
258 std::vector<int> dataVector;
259 dataClass.load();
260 for (int i = 0; i < numPeriods; ++i) {
261 dataVector.push_back(dataClass[i]);
262 }
263 return dataVector;
264}
265
266std::string LoadMuonNexusV2NexusHelper::getPeriodSequenceString(const int &numPeriods) const {
267 return convertVectorToString(getIntVector(numPeriods, NeXusEntry::SEQUENCES));
268}
269
270std::string LoadMuonNexusV2NexusHelper::getPeriodTypes(const int &numPeriods) const {
271 return convertVectorToString(getIntVector(numPeriods, NeXusEntry::TYPE));
272}
273
274std::string LoadMuonNexusV2NexusHelper::getPeriodFramesRequested(const int &numPeriods) const {
275 return convertVectorToString(getIntVector(numPeriods, NeXusEntry::REQUESTED));
276}
277std::string LoadMuonNexusV2NexusHelper::getPeriodRawFrames(const int &numPeriods) const {
278 return convertVectorToString(getIntVector(numPeriods, NeXusEntry::RAWFRAMES));
279}
280std::string LoadMuonNexusV2NexusHelper::getPeriodOutput(const int &numPeriods) const {
281 return convertVectorToString(getIntVector(numPeriods, NeXusEntry::PERIODOUTPUT));
282}
283
284std::string LoadMuonNexusV2NexusHelper::getPeriodTotalCounts(const int &numPeriods) const {
286
287 NXFloat countsData = periodClass.openNXFloat(NeXusEntry::PERIODCOUNTS);
288 std::vector<double> countsVector;
289 countsData.load();
290 for (int i = 0; i < numPeriods; ++i) {
291 countsVector.push_back(countsData[i]);
292 }
293 return convertVectorToString(countsVector);
294}
295
296} // namespace Mantid::DataHandling
double value
The value of the point.
Definition: FitMW.cpp:51
std::string getPeriodTotalCounts(const int &numPeriods) const
std::string getPeriodTypes(const int &numPeriods) const
std::vector< int > getIntVector(const int &numPeriods, const std::string &name) const
std::vector< double > loadDeadTimesFromNexus(const std::vector< detid_t > &loadedDetectors, bool isFileMultiPeriod, int periodNumber)
std::string getPeriodFramesRequested(const int &numPeriods) const
std::string getPeriodSequenceString(const int &numPeriods) const
std::string getPeriodRawFrames(const int &numPeriods) const
std::vector< detid_t > loadDetectorGroupingFromNexus(const std::vector< detid_t > &loadedDetectors, bool isFileMultiPeriod, int periodNumber)
std::vector< double > loadTimeZeroListFromNexusFile(size_t numSpectra)
NeXus::NXInt loadGoodFramesDataFromNexus(bool isFileMultiPeriod)
std::string getPeriodOutput(const int &numPeriods) const
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
NXDouble openNXDouble(const std::string &name) const
Creates and opens a double dataset.
Definition: NexusClasses.h:556
NXClass openNXGroup(const std::string &name) const
Creates and opens an arbitrary (non-standard) class (group).
Definition: NexusClasses.h:529
bool containsDataSet(const std::string &query) const
Returns whether an individual dataset is present.
NXInfo getDataSetInfo(const std::string &name) const
Returns NXInfo for a dataset.
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
NXChar openNXChar(const std::string &name) const
Creates and opens a char dataset.
Definition: NexusClasses.h:561
std::string getString(const std::string &name) const
Returns a string.
Templated class implementation of NXDataSet.
Definition: NexusClasses.h:203
container_T< T > & vecBuffer()
Returns a the internal buffer.
Definition: NexusClasses.h:265
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
Implements NXentry Nexus class.
Definition: NexusClasses.h:898
NXAttributes attributes
Attributes.
Definition: NexusClasses.h:111
MANTID_GEOMETRY_DLL PolygonEdge::Orientation orientation(const PolygonEdge &focusEdge, const PolygonEdge &refEdge, double &t)
Calculate the orientation type of one edge wrt to another.
Definition: PolygonEdge.cpp:81
std::string to_string(const wide_integer< Bits, Signed > &n)
C++ implementation of NeXus classes.
Definition: NexusClasses.h:41
int type
type of the data, e.g. NX_CHAR, NX_FLOAT32, see napi.h
Definition: NexusClasses.h:46