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