Mantid
Loading...
Searching...
No Matches
LoadISISNexusHelper.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
6// SPDX - License - Identifier: GPL - 3.0 +
8#include "MantidAPI/Run.h"
9#include "MantidAPI/Sample.h"
11namespace {
12static constexpr std::size_t RUN_TIME_STRING_LENGTH = 19;
13} // namespace
14
16
17using namespace API;
18using namespace Nexus;
19
27int64_t findNumberOfSpectra(const NXEntry &entry, const bool hasVMSBlock) {
28
29 if (hasVMSBlock) {
30 NXInt nsp1 = entry.openNXInt("isis_vms_compat/NSP1");
31 nsp1.load();
32 return nsp1[0];
33 } else {
34 NXClass det_class = entry.openNXGroup("detector_1");
35 NXInt spectrum_index = det_class.openNXInt("spectrum_index");
36 // Not clear what this variable is, number of detectors or number of
37 // detectors + monitors if it is number of detectors, that is just the
38 // length of the spectra
39 spectrum_index.load();
40 return spectrum_index.dim0();
41 }
42}
43
52std::tuple<NXInt, NXInt> findDetectorIDsAndSpectrumNumber(const NXEntry &entry, const bool hasVMSBlock) {
53 if (hasVMSBlock) {
54 NXInt udet = entry.openNXInt("isis_vms_compat/UDET");
55 udet.load();
56 NXInt spec = entry.openNXInt("isis_vms_compat/SPEC");
57 spec.load();
58 return std::make_tuple(udet, spec);
59 } else {
60 NXClass det_class = entry.openNXGroup("detector_1");
61 NXInt spectrum_index = det_class.openNXInt("spectrum_index");
62 spectrum_index.load();
63 // In the new v2 file there is no UDET variable
64 // Setting it to spectrum index assumes a 1 to 1 correspondence between
65 // detector id and spectrum number, i.e detector 1 maps to spectrum 1
66 // This is typical of a Muon Nexus file, as stated in the Nexus V2
67 // specification.
68 NXInt udet = spectrum_index;
69 NXInt spec = std::move(spectrum_index);
70 return std::make_tuple(udet, spec);
71 }
72}
73
81void loadSampleGeometry(Sample &sample, const NXEntry &entry, const bool hasVMSBlock) {
82
83 if (hasVMSBlock) {
84 NXInt spb = entry.openNXInt("isis_vms_compat/SPB");
85 // Just load the index we need, not the whole block. The flag is the
86 // third value in the array
87 spb.load(1, 2);
88 int geom_id = spb[0];
89 sample.setGeometryFlag(geom_id);
90
91 NXFloat rspb = entry.openNXFloat("isis_vms_compat/RSPB");
92 // Just load the indices we need, not the whole block. The values start
93 // from the 4th onward
94 rspb.load(3, 3);
95 double thick(rspb[0]);
96 double height(rspb[1]);
97 double width(rspb[2]);
98 sample.setThickness(thick);
99 sample.setHeight(height);
100 sample.setWidth(width);
101
102 } else {
103 NXClass sampleEntry = entry.openNXGroup("sample");
104 std::string id = sampleEntry.getString("id");
105 int geom_id(0);
106 if (!id.empty()) {
107 geom_id = std::stoi(id);
108 }
109 sample.setGeometryFlag(geom_id);
110
111 double thick = sampleEntry.getFloat("thickness");
112 double height = sampleEntry.getFloat("height");
113 double width = sampleEntry.getFloat("width");
114 sample.setThickness(thick);
115 sample.setHeight(height);
116 sample.setWidth(width);
117 }
118}
125void loadRunDetails(API::Run &run, const NXEntry &entry, const bool hasVMSBlock) {
126
127 // Charge is stored as a float
128 double proton_charge = static_cast<double>(entry.getFloat("proton_charge"));
129 run.setProtonCharge(proton_charge);
130
131 std::string run_num = std::to_string(entry.getInt("run_number"));
132 run.addProperty("run_number", run_num);
133
134 // End date and time is stored separately in ISO format in the
135 // "raw_data1/endtime" class
136 NXChar char_data = entry.openNXChar("end_time");
137 char_data.load();
138
139 std::string end_time_iso = std::string(char_data(), RUN_TIME_STRING_LENGTH);
140 run.addProperty("run_end", end_time_iso);
141
142 char_data = entry.openNXChar("start_time");
143 char_data.load();
144
145 std::string start_time_iso = std::string(char_data(), RUN_TIME_STRING_LENGTH);
146
147 run.addProperty("run_start", start_time_iso);
148
149 // If we have a vms block, load details from there
150 if (hasVMSBlock) {
151
152 NXClass vms_compat = entry.openNXGroup("isis_vms_compat");
153
154 // RPB struct info
155 NXInt rpb_int = vms_compat.openNXInt("IRPB");
156 rpb_int.load();
157 run.addProperty("freq",
158 rpb_int[6]); // 2**k where source frequency = 50 / 2**k
159 // Now double data
160 NXFloat rpb_dbl = vms_compat.openNXFloat("RRPB");
161 rpb_dbl.load();
162 run.addProperty("gd_prtn_chrg",
163 static_cast<double>(rpb_dbl[7])); // good proton charge (uA.hour)
164 run.addProperty("tot_prtn_chrg",
165 static_cast<double>(rpb_dbl[8])); // total proton charge (uA.hour)
166 run.addProperty("goodfrm", rpb_int[9]); // good frames
167 run.addProperty("rawfrm", rpb_int[10]); // raw frames
168 run.addProperty("rb_proposal", rpb_int[21]); // RB (proposal)
169 vms_compat.close();
170 } else {
171 NXFloat floatData = entry.openNXFloat("duration");
172 floatData.load();
173 run.addProperty("dur", static_cast<double>(floatData[0]), floatData.attributes("units"), true);
174
175 // These variables have changed, gd_prtn_chrg is now proton_charge
176 floatData = entry.openNXFloat("proton_charge");
177 floatData.load();
178 run.addProperty("gd_prtn_chrg", static_cast<double>(floatData[0]), floatData.attributes("units"), true);
179 // Total_proton_charge is now proton_charge_raw
180 floatData = entry.openNXFloat("proton_charge_raw");
181 floatData.load();
182 run.addProperty("tot_prtn_chrg", static_cast<double>(floatData[0]), floatData.attributes("units"), true);
183
184 auto sourceEntry = entry.openNXGroup("instrument/source");
185 if (sourceEntry.containsDataSet("frequency")) {
186 run.addProperty("freq", entry.getFloat("instrument/source/frequency"));
187 } else {
188 // If no entry, assume 50hz source (suggested by Freddie Akeroyd)
189 run.addProperty("freq", 50, "Hz", true);
190 }
191
192 run.addProperty("goodfrm", entry.getInt("good_frames"));
193 run.addProperty("rawfrm", entry.getInt("raw_frames"));
194 run.addProperty("rb_proposal",
195 entry.getString("experiment_identifier")); // RB (proposal)
196 }
197}
204std::shared_ptr<HistogramData::HistogramX> loadTimeData(const NXEntry &entry) {
205 // if neturon file time bins stored in dector_1/time_of_flight
206 auto detectorEntry = entry.openNXGroup("detector_1");
207 if (detectorEntry.containsDataSet("time_of_flight")) {
208 auto timeBins = entry.openNXFloat("detector_1/time_of_flight");
209 auto x_length = timeBins.dim0();
210 timeBins.load();
211 auto timeData = std::make_shared<HistogramData::HistogramX>(timeBins(), timeBins() + x_length);
212 return timeData;
213 } else { // Muon V2 file
214 auto timeBins = entry.openNXFloat("detector_1/raw_time");
215 auto x_length = timeBins.dim0();
216 timeBins.load();
217 auto timeData = std::make_shared<HistogramData::HistogramX>(timeBins(), timeBins() + x_length);
218 return timeData;
219 }
220}
221} // namespace Mantid::DataHandling::LoadISISNexusHelper
double height
Definition GetAllEi.cpp:155
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
Definition LogManager.h:90
This class stores information regarding an experimental run as a series of log entries.
Definition Run.h:35
void setProtonCharge(const double charge)
Set the proton charge.
Definition Run.cpp:283
This class stores information about the sample used in particular run.
Definition Sample.h:33
void setGeometryFlag(int geom_id)
Sets the geometry flag.
Definition Sample.cpp:208
void setWidth(double width)
Sets the width.
Definition Sample.cpp:245
void setHeight(double height)
Sets the height.
Definition Sample.cpp:233
void setThickness(double thick)
Sets the thickness.
Definition Sample.cpp:221
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).
void close()
Close this class.
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.
int32_t getInt(const std::string &name) const
Returns a int.
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.
NXAttributes attributes
Attributes.
Implements NXentry Nexus class.
void loadSampleGeometry(API::Sample &sample, const Nexus::NXEntry &entry, const bool hasVMSBlock)
Load geometrical data about the sample from the nexus entry into a workspace.
int64_t findNumberOfSpectra(const Nexus::NXEntry &entry, const bool hasVMSBlock)
find the number of spectra in the nexus file
std::shared_ptr< HistogramData::HistogramX > loadTimeData(const Nexus::NXEntry &entry)
Load the time data from nexus entry.
std::tuple< Nexus::NXInt, Nexus::NXInt > findDetectorIDsAndSpectrumNumber(const Nexus::NXEntry &entry, const bool hasVMSBlock)
find detector ids and spectrum numbers
void loadRunDetails(API::Run &runDetails, const Nexus::NXEntry &entry, const bool hasVMSBlock)
Load data about the run.
NXDataSetTyped< char > NXChar
The char dataset type.
std::string to_string(const wide_integer< Bits, Signed > &n)