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"
15
16#include <algorithm>
17#include <cctype>
18
19namespace {
20template <typename type> std::string convertVectorToString(const std::vector<type> &vector) {
21 std::string stringOfVector = "";
22 for (const auto &value : vector) {
23 stringOfVector += std::to_string(value) + ";";
24 }
25 return stringOfVector.substr(0, stringOfVector.size() - 1);
26}
27} // namespace
28
29namespace Mantid::DataHandling {
30
31namespace NeXusEntry {
32const std::string GOODFRAMES{"good_frames"};
33const std::string DETECTOR{"instrument/detector_1"};
34const std::string PERIOD{"periods"};
35const std::string ORIENTATON{"instrument/detector_1/orientation"};
36const std::string RESOLUTION{"resolution"};
37const std::string GROUPING{"grouping"};
38const std::string DEADTIME{"dead_time"};
39const std::string COUNTS{"counts"};
40const std::string FIRSTGOODBIN{"first_good_bin"};
41const std::string LASTGOODBIN{"last_good_bin"};
42const std::string TIMEZERO{"time_zero"};
43const std::string SAMPLE{"sample"};
44const std::string TEMPERATURE{"temperature"};
45const std::string MAGNETICFIELD{"magnetic_field"};
46const std::string SEQUENCES{"sequences"};
47const std::string TYPE{"type"};
48const std::string REQUESTED{"frames_requested"};
49const std::string RAWFRAMES{"raw_frames"};
50const std::string PERIODOUTPUT{"output"};
51const std::string PERIODCOUNTS{"total_counts"};
52} // namespace NeXusEntry
53
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::optional<std::vector<detid_t>>
92LoadMuonNexusV2NexusHelper::loadDetectorGroupingFromNexus(const std::vector<detid_t> &detectorsLoaded,
93 bool isFileMultiPeriod, int periodNumber) {
94 // Open nexus entry
96 if (!detectorGroup.containsDataSet(NeXusEntry::GROUPING)) {
97 return std::nullopt;
98 }
99
100 // We cast the numLoadedDetectors to an int, which is the index type used for
101 // Nexus Data sets. As detectorsLoaded is derived from a nexus entry we
102 // can be certain we won't overflow the integer type.
103 int numLoadedDetectors = static_cast<int>(detectorsLoaded.size());
104 std::vector<detid_t> grouping;
105 grouping.reserve(numLoadedDetectors);
106
107 NXInt groupingData = detectorGroup.openNXInt(NeXusEntry::GROUPING);
108 groupingData.load();
109 int groupingOffset = !isFileMultiPeriod ? 0 : (numLoadedDetectors) * (periodNumber - 1);
110 std::transform(detectorsLoaded.cbegin(), detectorsLoaded.cend(), std::back_inserter(grouping),
111 [&groupingData, groupingOffset](const auto detectorNumber) {
112 return groupingData[detectorNumber - 1 + groupingOffset];
113 });
114
115 return grouping;
116}
118 std::string mainFieldDirection = "Longitudinal"; // default
119 try {
121 // some files have no data there
122 orientation.load();
123 if (std::tolower(orientation[0]) == 't') {
124 mainFieldDirection = "Transverse";
125 }
126 } catch (std::runtime_error &) {
127 // no data - assume main field was longitudinal and continue.
128 }
129 return mainFieldDirection;
130}
131// Loads dead times from the nexus file
132// Assumes one grouping entry per detector
133std::vector<double> LoadMuonNexusV2NexusHelper::loadDeadTimesFromNexus(const std::vector<detid_t> &loadedDetectors,
134 bool isFileMultiPeriod, int periodNumber) {
135 // We cast the numLoadedDetectors to an int, which is the index type used for
136 // Nexus Data sets. As loadedDectors is derived from a nexus entry we
137 // can be certain we won't overflow the integer type.
138 int numLoadedDetectors = static_cast<int>(loadedDetectors.size());
139 std::vector<double> deadTimes;
140 deadTimes.reserve(numLoadedDetectors);
141
143 if (detectorGroup.containsDataSet(NeXusEntry::DEADTIME)) {
144 NXFloat deadTimesData = detectorGroup.openNXFloat(NeXusEntry::DEADTIME);
145 deadTimesData.load();
146 // If we have a multi period file all the data will be stored in a single
147 // nexus entry of length (num_periods * numDetectors)
148 // So if we are load the second period we need to offset our indexes by
149 // (1*numDetectors)
150 int deadTimeOffset = !isFileMultiPeriod ? 0 : (numLoadedDetectors) * (periodNumber - 1);
151 std::transform(loadedDetectors.cbegin(), loadedDetectors.cend(), std::back_inserter(deadTimes),
152 [deadTimesData, deadTimeOffset](const auto detectorNumber) {
153 return deadTimesData[detectorNumber - 1 + deadTimeOffset];
154 });
155 }
156 return deadTimes;
157}
158
160 try {
162 NXInfo infoResolution = detectorEntry.getDataSetInfo(NeXusEntry::RESOLUTION);
163 NXInt counts = detectorEntry.openNXInt(NeXusEntry::COUNTS);
164 std::string firstGoodBin = counts.attributes(NeXusEntry::FIRSTGOODBIN);
165 double resolution;
166 switch (infoResolution.type) {
168 resolution = static_cast<double>(detectorEntry.getFloat(NeXusEntry::RESOLUTION));
169 break;
170 case NXnumtype::INT32:
171 resolution = static_cast<double>(detectorEntry.getInt(NeXusEntry::RESOLUTION));
172 break;
173 default:
174 throw std::runtime_error("Unsupported data type for resolution");
175 }
176 double bin = static_cast<double>(boost::lexical_cast<int>(firstGoodBin));
177 double bin_size = resolution / 1000000.0;
178 return bin * bin_size;
179 } catch (std::runtime_error &) {
180 throw std::runtime_error("Error loading FirstGoodData, check Nexus file");
181 }
182}
183
185 try {
187 NXInfo infoResolution = detectorEntry.getDataSetInfo(NeXusEntry::RESOLUTION);
188 NXInt counts = detectorEntry.openNXInt(NeXusEntry::COUNTS);
189 std::string lastGoodBin = counts.attributes(NeXusEntry::LASTGOODBIN);
190 double resolution;
191 switch (infoResolution.type) {
193 resolution = static_cast<double>(detectorEntry.getFloat(NeXusEntry::RESOLUTION));
194 break;
195 case NXnumtype::INT32:
196 resolution = static_cast<double>(detectorEntry.getInt(NeXusEntry::RESOLUTION));
197 break;
198 default:
199 throw std::runtime_error("Unsupported data type for resolution");
200 }
201 double bin = static_cast<double>(boost::lexical_cast<int>(lastGoodBin));
202 double bin_size = resolution / 1000000.0;
203 return bin * bin_size;
204 } catch (std::runtime_error &) {
205 throw std::runtime_error("Error loading LastGoodData, check Nexus file");
206 }
207}
208
210 try {
212 double timeZero = static_cast<double>(detectorEntry.getFloat(NeXusEntry::TIMEZERO));
213 return timeZero;
214 } catch (std::runtime_error &) {
215 throw std::runtime_error("Could not load time zero, check Nexus file");
216 }
217}
218
219std::vector<double> LoadMuonNexusV2NexusHelper::loadTimeZeroListFromNexusFile(size_t numSpectra) {
221
222 NXDouble timeZeroClass = det_class.openNXDouble(NeXusEntry::TIMEZERO);
223 std::vector<double> timeZeroVector = timeZeroClass.vecBuffer();
224 if (timeZeroVector.size() == 0) {
225 double timeZero = static_cast<double>(det_class.getFloat(NeXusEntry::TIMEZERO));
226 timeZeroVector = std::vector<double>(numSpectra, timeZero);
227 } else if (timeZeroVector.size() != numSpectra) {
228 throw std::runtime_error("Time zero list size does not match number of "
229 "spectra, check Nexus file.");
230 }
231 // We assume that this spectrum list increases monotonically
232 return timeZeroVector;
233}
234
236 auto runSample = m_entry.openNXGroup(NeXusEntry::SAMPLE);
237 MuonNexus::SampleInformation sampleInformation;
238 try {
239 sampleInformation.magneticField = runSample.getFloat(NeXusEntry::MAGNETICFIELD);
240 sampleInformation.temperature = runSample.getFloat(NeXusEntry::TEMPERATURE);
241 } catch (std::runtime_error &) {
242 throw std::runtime_error("Could not load sample information (temperature "
243 "and magnetic field) from nexus entry");
244 }
245 return sampleInformation;
246}
247
250 return periodClass.getInt("number");
251}
252
255 return periodClass.getString("labels");
256}
257
258std::vector<int> LoadMuonNexusV2NexusHelper::getIntVector(const int &numPeriods, const std::string &name) const {
260
261 NXInt dataClass = periodClass.openNXInt(name);
262 std::vector<int> dataVector;
263 dataClass.load();
264 for (int i = 0; i < numPeriods; ++i) {
265 dataVector.push_back(dataClass[i]);
266 }
267 return dataVector;
268}
269
270std::string LoadMuonNexusV2NexusHelper::getPeriodSequenceString(const int &numPeriods) const {
271 return convertVectorToString(getIntVector(numPeriods, NeXusEntry::SEQUENCES));
272}
273
274std::string LoadMuonNexusV2NexusHelper::getPeriodTypes(const int &numPeriods) const {
275 return convertVectorToString(getIntVector(numPeriods, NeXusEntry::TYPE));
276}
277
278std::string LoadMuonNexusV2NexusHelper::getPeriodFramesRequested(const int &numPeriods) const {
279 return convertVectorToString(getIntVector(numPeriods, NeXusEntry::REQUESTED));
280}
281std::string LoadMuonNexusV2NexusHelper::getPeriodRawFrames(const int &numPeriods) const {
282 return convertVectorToString(getIntVector(numPeriods, NeXusEntry::RAWFRAMES));
283}
284std::string LoadMuonNexusV2NexusHelper::getPeriodOutput(const int &numPeriods) const {
285 return convertVectorToString(getIntVector(numPeriods, NeXusEntry::PERIODOUTPUT));
286}
287
290 NXFloat countsData = periodClass.openNXFloat(NeXusEntry::PERIODCOUNTS);
291 countsData.load();
292
293 return convertVectorToString(countsData.vecBuffer());
294}
295
296} // namespace Mantid::DataHandling
std::string name
Definition Run.cpp:60
double value
The value of the point.
Definition FitMW.cpp:51
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::optional< std::vector< detid_t > > loadDetectorGroupingFromNexus(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< 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).
float getFloat(const std::string &name) const
Returns a float.
std::string getString(const std::string &name) const
Returns a string.
NXFloat openNXFloat(const std::string &name) const
Creates and opens a float dataset.
NXClass openNXGroup(const std::string &name) const
Creates and opens an arbitrary (non-standard) class (group).
NXChar openNXChar(const std::string &name) const
Creates and opens a char dataset.
NXInt openNXInt(const std::string &name) const
Creates and opens an integer dataset.
NXDouble openNXDouble(const std::string &name) const
Creates and opens a double dataset.
NXInfo getDataSetInfo(const std::string &name) const
Returns NXInfo for a dataset.
bool containsDataSet(const std::string &query) const
Returns whether an individual dataset is present.
int32_t getInt(const std::string &name) const
Returns a int.
Templated class implementation of NXDataSet.
void load()
Read all of the datablock in.
container_T< T > & vecBuffer()
Returns a the internal buffer.
NXAttributes attributes
Attributes.
Implements NXentry Nexus class.
static unsigned short constexpr INT32
static unsigned short constexpr FLOAT32
MANTID_GEOMETRY_DLL PolygonEdge::Orientation orientation(const PolygonEdge &focusEdge, const PolygonEdge &refEdge, double &t)
Calculate the orientation type of one edge wrt to another.
NXDataSetTyped< char > NXChar
The char dataset type.
std::string to_string(const wide_integer< Bits, Signed > &n)
Structure for keeping information about a Nexus data set, such as the dimensions and the type.
NXnumtype type
type of the data, e.g. NX_CHAR, FLOAT32; see NexusFile_fwd.h