Mantid
Loading...
Searching...
No Matches
LoadILLSALSA.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2021 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
15#include "MantidHistogramData/Points.h"
18
19#include <iterator>
20#include <sstream>
21
22namespace Mantid::DataHandling {
23
25
28
37 if ((descriptor.pathExists("/entry0/data_scan") || descriptor.pathExists("/entry0/data")) &&
38 descriptor.pathExists("/entry0/instrument/Tx") && descriptor.pathExists("/entry0/instrument/Ty") &&
39 descriptor.pathExists("/entry0/instrument/Tz"))
40 return 80;
41 else
42 return 0;
43}
44
49 declareProperty(std::make_unique<API::FileProperty>("Filename", "", API::FileProperty::Load, ".nxs"),
50 "File path of the Data file to load");
51 declareProperty(std::make_unique<API::WorkspaceProperty<>>("OutputWorkspace", "", Kernel::Direction::Output),
52 "The name to use for the output workspace");
53 auto mustBePositive = std::make_shared<Kernel::BoundedValidator<double>>();
54 mustBePositive->setLower(0.0);
55 declareProperty("DetectorDistance", 1.0, mustBePositive, "Distance between the sample and the detector (meters)");
56 declareProperty("ThetaOffset", 0.0, "Offset for the 2theta value (degrees)");
57}
58
63 const std::string filename = getPropertyValue("Filename");
64 H5::H5File h5file(filename, H5F_ACC_RDONLY);
65
66 enum FileType { NONE, V1, V2 };
67
68 FileType fileType = NONE;
69 // guess type of file
70 try {
71 H5::Group detectorDataset = h5file.openGroup("entry0/data");
72 detectorDataset.close();
73 fileType = V1;
74 } catch (H5::Exception &) {
75 fileType = NONE;
76 }
77 if (fileType == NONE) {
78 try {
79 H5::Group detectorDataset = h5file.openGroup("entry0/data_scan");
80 detectorDataset.close();
81 fileType = V2;
82 } catch (H5::Exception &) {
83 fileType = NONE;
84 }
85 }
86
87 switch (fileType) {
88 case NONE:
89 throw std::runtime_error("The Nexus file your are trying to open is not supported by the SALSA loader.");
90 break;
91 case V1:
92 loadNexusV1(h5file);
93
94 break;
95 case V2:
96 loadNexusV2(h5file);
97 break;
98 }
99
100 // set the instrument
101 double sampleToDetectorDistance = getProperty("DetectorDistance");
102 H5::DataSet thetaDataset = h5file.openDataSet("entry0/instrument/2theta/value");
103 float theta;
104 thetaDataset.read(&theta, thetaDataset.getDataType());
105 double twoThetaAngle = theta + static_cast<double>(getProperty("ThetaOffset"));
106 setInstrument(sampleToDetectorDistance, twoThetaAngle);
107 thetaDataset.close();
108
109 h5file.close();
110
111 fillWorkspaceMetadata(filename);
112}
113
119void LoadILLSALSA::setInstrument(double distance, double angle) {
120 // load instrument
121 auto loadInst = createChildAlgorithm("LoadInstrument");
122 loadInst->setPropertyValue("InstrumentName", "SALSA");
123 loadInst->setProperty<API::MatrixWorkspace_sptr>("Workspace", m_outputWorkspace);
124 loadInst->setProperty("RewriteSpectraMap", Kernel::OptionalBool(true));
125 loadInst->execute();
126
127 // translation
128 double angleRad = angle * M_PI / 180.0;
129 double dx = -distance * sin(angleRad);
130 double dz = distance * cos(angleRad);
131 auto moveInst = createChildAlgorithm("MoveInstrumentComponent");
132 moveInst->setProperty<API::MatrixWorkspace_sptr>("Workspace", m_outputWorkspace);
133 moveInst->setPropertyValue("ComponentName", "detector");
134 moveInst->setProperty<double>("X", dx);
135 moveInst->setProperty<double>("Y", 0.);
136 moveInst->setProperty<double>("Z", dz);
137 moveInst->setProperty<bool>("RelativePosition", false);
138 moveInst->execute();
139
140 // rotation
141 auto rotateInst = createChildAlgorithm("RotateInstrumentComponent");
142 rotateInst->setProperty<API::MatrixWorkspace_sptr>("Workspace", m_outputWorkspace);
143 rotateInst->setPropertyValue("ComponentName", "detector");
144 rotateInst->setPropertyValue("Y", "1");
145 rotateInst->setProperty<double>("Angle", -angle);
146 rotateInst->execute();
147}
148
153void LoadILLSALSA::loadNexusV1(const H5::H5File &h5file) {
154 H5::DataSet detectorDataset = h5file.openDataSet("entry0/data/Multi_data");
155 H5::DataSet monitorDataset = h5file.openDataSet("entry0/monitor/data");
156
157 m_outputWorkspace = DataObjects::create<DataObjects::Workspace2D>(
158 VERTICAL_NUMBER_PIXELS * HORIZONTAL_NUMBER_PIXELS + 1, HistogramData::Points(1));
159 setProperty("OutputWorkspace", m_outputWorkspace);
160
161 std::vector<int> dataInt(VERTICAL_NUMBER_PIXELS * HORIZONTAL_NUMBER_PIXELS + 1);
162 detectorDataset.read(dataInt.data(), detectorDataset.getDataType());
163 monitorDataset.read(dataInt.data() + VERTICAL_NUMBER_PIXELS * HORIZONTAL_NUMBER_PIXELS, monitorDataset.getDataType());
164
165 for (size_t i = 0; i < dataInt.size(); i++) {
166 double count = dataInt[i];
167 double error = sqrt(count);
168 m_outputWorkspace->mutableY(i)[0] = count;
169 m_outputWorkspace->mutableE(i)[0] = error;
170 }
171
172 detectorDataset.close();
173 monitorDataset.close();
174}
175
181void LoadILLSALSA::loadNexusV2(const H5::H5File &h5file) {
182 H5::DataSet detectorDataset = h5file.openDataSet("entry0/data_scan/detector_data/data");
183 H5::DataSpace detectorDataspace = detectorDataset.getSpace();
184
185 int nDims = detectorDataspace.getSimpleExtentNdims();
186 std::vector<hsize_t> dimsSize(nDims);
187 detectorDataspace.getSimpleExtentDims(dimsSize.data(), NULL);
188
189 size_t numberOfScans = dimsSize[0];
190
191 if ((dimsSize[1] != VERTICAL_NUMBER_PIXELS) || (dimsSize[2] != HORIZONTAL_NUMBER_PIXELS)) {
192 std::ostringstream oss;
193 oss << "Unexpected data shape, got " << dimsSize[1] << "x" << dimsSize[2] << "pixels ";
194 oss << "instead of " << VERTICAL_NUMBER_PIXELS << "x" << HORIZONTAL_NUMBER_PIXELS;
195 throw std::runtime_error(oss.str());
196 }
197
198 m_outputWorkspace = DataObjects::create<DataObjects::Workspace2D>(
199 VERTICAL_NUMBER_PIXELS * HORIZONTAL_NUMBER_PIXELS + 1, HistogramData::Points(numberOfScans));
200 setProperty("OutputWorkspace", m_outputWorkspace);
201
202 std::vector<int> dataInt(numberOfScans * VERTICAL_NUMBER_PIXELS * HORIZONTAL_NUMBER_PIXELS);
203 detectorDataset.read(dataInt.data(), detectorDataset.getDataType());
204
205 detectorDataset.close();
206
207 // get scanned variable names
208 H5::DataSet scanVarNames = h5file.openDataSet("entry0/data_scan/scanned_variables/variables_names/name");
209 H5::DataSpace scanVarNamesSpace = scanVarNames.getSpace();
210
211 nDims = scanVarNamesSpace.getSimpleExtentNdims();
212 dimsSize = std::vector<hsize_t>(nDims);
213 scanVarNamesSpace.getSimpleExtentDims(dimsSize.data(), nullptr);
214
215 std::vector<char *> rdata(dimsSize[0]);
216 scanVarNames.read(rdata.data(), scanVarNames.getDataType());
217 size_t monitorIndex = 0;
218 while (monitorIndex < rdata.size()) {
219 if (std::string(rdata[monitorIndex]) == "Monitor1")
220 break;
221 monitorIndex++;
222 }
223 if (monitorIndex == rdata.size())
224 throw std::runtime_error("Monitor count not found. Please check your nexus file.");
225 scanVarNames.vlenReclaim(rdata.data(), scanVarNames.getDataType(), scanVarNamesSpace);
226
227 scanVarNames.close();
228
229 // get scanned variable values and extract monitor count
230 H5::DataSet scanVar = h5file.openDataSet("entry0/data_scan/scanned_variables/data");
231 H5::DataSpace scanVarSpace = scanVar.getSpace();
232
233 nDims = scanVarSpace.getSimpleExtentNdims();
234 dimsSize = std::vector<hsize_t>(nDims);
235 scanVarSpace.getSimpleExtentDims(dimsSize.data(), nullptr);
236 if ((nDims != 2) || (dimsSize[1] != numberOfScans))
237 throw std::runtime_error("Scanned variables are not formatted properly. Check you nexus file.");
238
239 std::vector<double> scanVarData(dimsSize[0] * dimsSize[1]);
240 scanVar.read(scanVarData.data(), scanVar.getDataType());
241 std::vector<double> monitorData(dimsSize[1]);
242 for (size_t i = 0; i < monitorData.size(); i++)
243 monitorData[i] = scanVarData[monitorIndex * dimsSize[1] + i];
244
245 scanVar.close();
246
247 // fill the workspace
248 for (size_t j = 0; j < numberOfScans; j++) {
249 for (size_t i = 0; i < VERTICAL_NUMBER_PIXELS * HORIZONTAL_NUMBER_PIXELS; i++) {
250 double count = dataInt[j * VERTICAL_NUMBER_PIXELS * HORIZONTAL_NUMBER_PIXELS + i];
251 double error = sqrt(count);
252 m_outputWorkspace->mutableY(i)[j] = count;
253 m_outputWorkspace->mutableE(i)[j] = error;
254 }
256 }
257}
258
259void LoadILLSALSA::fillWorkspaceMetadata(const std::string &filename) {
260 API::Run &runDetails = m_outputWorkspace->mutableRun();
261 NXhandle nxHandle;
262 NXopen(filename.c_str(), NXACC_READ, &nxHandle);
263 LoadHelper::addNexusFieldsToWsRun(nxHandle, runDetails);
264 NXclose(&nxHandle);
265}
266} // namespace Mantid::DataHandling
double error
Definition: IndexPeaks.cpp:133
int count
counter
Definition: Matrix.cpp:37
#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
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
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
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
This class stores information regarding an experimental run as a series of log entries.
Definition: Run.h:38
A property class for workspaces.
void exec() override
Executes the algorithm.
void init() override
Initialises the algorithm.
void loadNexusV2(const H5::H5File &h5file)
Load V2 Nexus file.
void fillWorkspaceMetadata(const std::string &filename)
int confidence(Kernel::NexusDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
std::shared_ptr< DataObjects::Workspace2D > m_outputWorkspace
Definition: LoadILLSALSA.h:57
static const size_t HORIZONTAL_NUMBER_PIXELS
Definition: LoadILLSALSA.h:43
void loadNexusV1(const H5::H5File &h5file)
Load V1 Nexus file.
void setInstrument(double distance, double angle)
Load the instrument and set its position.
static const size_t VERTICAL_NUMBER_PIXELS
Definition: LoadILLSALSA.h:41
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
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
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
void addNexusFieldsToWsRun(NXhandle nxfileID, API::Run &runDetails, const std::string &entryName="", bool useFullPath=false)
Add properties from a nexus file to the workspace run.
Definition: LoadHelper.cpp:131
FileType
Allowed file types.
@ Output
An output workspace.
Definition: Property.h:54