Mantid
Loading...
Searching...
No Matches
LoadSassena.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 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/Axis.h"
18#include "MantidKernel/Unit.h"
20#include "MantidNexus/H5Util.h"
21
22#include <utility>
23
24namespace Mantid::DataHandling {
25
27
28
34int LoadSassena::confidence(Nexus::NexusDescriptor &descriptor) const {
35 if (descriptor.hasRootAttr("sassena_version") || descriptor.isEntry("/qvectors")) {
36 return 99;
37 }
38 return 0;
39}
40
49void LoadSassena::registerWorkspace(const API::WorkspaceGroup_sptr &gws, const std::string &wsName,
50 const DataObjects::Workspace2D_sptr &ws, const std::string &description) {
51 UNUSED_ARG(description);
52 API::AnalysisDataService::Instance().add(wsName, ws);
53 gws->addWorkspace(ws);
54}
55
63void LoadSassena::dataSetInfo(const H5::H5File &h5file, const std::string &setName, hsize_t *dims) const {
64 h5file.openDataSet(setName).getSpace().getSimpleExtentDims(dims);
65}
66
73void LoadSassena::dataSetDouble(const H5::H5File &h5file, const std::string &setName, std::vector<double> &buf) {
74 Mantid::Nexus::H5Util::readArray1DCoerce(h5file.openDataSet(setName), buf);
75}
76
77/* Helper object and function to sort modulus of Q-vectors
78 */
79using mypair = std::pair<double, int>;
80bool compare(const mypair &left, const mypair &right) { return left.first < right.first; }
92HistogramData::Points LoadSassena::loadQvectors(const H5::H5File &h5file, const API::WorkspaceGroup_sptr &gws,
93 std::vector<int> &sorting_indexes) {
94
95 // store the modulus of the vector
96 std::vector<double> qvmod;
97
98 const std::string gwsName = this->getPropertyValue("OutputWorkspace");
99 const std::string setName("qvectors");
100
101 hsize_t dims[3];
102 try {
103 this->dataSetInfo(h5file, setName, dims);
104 } catch (H5::Exception &) {
105 throw Kernel::Exception::FileError("Unable to read " + setName + " dataset info:", m_filename);
106 }
107
108 auto nq = static_cast<int>(dims[0]); // number of q-vectors
109 std::vector<double> buf(nq * 3);
110
111 try {
112 this->dataSetDouble(h5file, "qvectors", buf);
113 } catch (H5::Exception &) {
114 this->g_log.error("LoadSassena::loadQvectors cannot proceed");
115 qvmod.resize(0);
116 return HistogramData::Points(std::move(qvmod));
117 }
118
119 qvmod.reserve(nq);
120 for (auto curr = buf.cbegin(); curr != buf.cend(); curr += 3) {
121 qvmod.emplace_back(sqrt(curr[0] * curr[0] + curr[1] * curr[1] + curr[2] * curr[2]));
122 }
123
124 if (getProperty("SortByQVectors")) {
125 std::vector<mypair> qvmodpair;
126 qvmodpair.reserve(nq);
127 for (int iq = 0; iq < nq; iq++)
128 qvmodpair.emplace_back(qvmod[iq], iq);
129 std::sort(qvmodpair.begin(), qvmodpair.end(), compare);
130 for (int iq = 0; iq < nq; iq++)
131 sorting_indexes.emplace_back(qvmodpair[iq].second);
132 std::sort(qvmod.begin(), qvmod.end());
133 } else
134 for (int iq = 0; iq < nq; iq++)
135 sorting_indexes.emplace_back(iq);
136
137 DataObjects::Workspace2D_sptr ws = std::dynamic_pointer_cast<DataObjects::Workspace2D>(
138 API::WorkspaceFactory::Instance().create("Workspace2D", nq, 3, 3));
139 std::string wsName = gwsName + std::string("_") + setName;
140 ws->setTitle(wsName);
141
142 for (int iq = 0; iq < nq; iq++) {
143 auto &Y = ws->mutableY(iq);
144 auto curr = std::next(buf.cbegin(), 3 * sorting_indexes[iq]);
145 Y.assign(curr, std::next(curr, 3));
146 }
147
148 ws->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("MomentumTransfer"); // Set the Units
149
150 this->registerWorkspace(gws, wsName, ws, "X-axis: origin of Q-vectors; Y-axis: tip of Q-vectors");
151 return HistogramData::Points(std::move(qvmod));
152}
153
165void LoadSassena::loadFQ(const H5::H5File &h5file, const API::WorkspaceGroup_sptr &gws, const std::string &setName,
166 const HistogramData::Points &qvmod, const std::vector<int> &sorting_indexes) {
167
168 auto nq = static_cast<int>(qvmod.size()); // number of q-vectors
169 std::vector<double> buf(nq * 2);
170 try {
171 this->dataSetDouble(h5file, setName, buf);
172 } catch (H5::Exception &) {
173 this->g_log.error("LoadSassena::loadFQ cannot proceed");
174 return;
175 }
176
177 const std::string gwsName = this->getPropertyValue("OutputWorkspace");
178
179 DataObjects::Workspace2D_sptr ws = std::dynamic_pointer_cast<DataObjects::Workspace2D>(
180 API::WorkspaceFactory::Instance().create("Workspace2D", 2, nq, nq));
181 const std::string wsName = gwsName + std::string("_") + setName;
182 ws->setTitle(wsName);
183
184 auto &re = ws->mutableY(0); // store the real part
185 ws->setPoints(0, qvmod); // X-axis values are the modulus of the q vector
186 auto &im = ws->mutableY(1); // store the imaginary part
187 ws->setPoints(1, qvmod);
188
189 for (int iq = 0; iq < nq; ++iq) {
190 auto curr = std::next(buf.cbegin(), 2 * sorting_indexes[iq]);
191 re[iq] = *curr;
192 im[iq] = *std::next(curr);
193 }
194
195 // Set the Units
196 ws->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("MomentumTransfer");
197
198 this->registerWorkspace(gws, wsName, ws, "X-axis: Q-vector modulus; Y-axis: intermediate structure factor");
199}
200
214void LoadSassena::loadFQT(const H5::H5File &h5file, const API::WorkspaceGroup_sptr &gws, const std::string &setName,
215 const HistogramData::Points &qvmod, const std::vector<int> &sorting_indexes) {
216
217 hsize_t dims[3];
218 try {
219 this->dataSetInfo(h5file, setName, dims);
220 } catch (H5::Exception &) {
221 this->g_log.error("Unable to read " + setName + " dataset info");
222 this->g_log.error("LoadSassena::loadFQT cannot proceed");
223 return;
224 }
225 auto nnt = static_cast<int>(dims[1]); // number of non-negative time points
226 int nt = 2 * nnt - 1; // number of time points
227
228 auto nq = static_cast<int>(qvmod.size()); // number of q-vectors
229 std::vector<double> buf(nq * nnt * 2);
230 try {
231 this->dataSetDouble(h5file, setName, buf);
232 } catch (H5::Exception &) {
233 this->g_log.error("LoadSassena::loadFQT cannot proceed");
234 return;
235 }
236
237 const std::string gwsName = this->getPropertyValue("OutputWorkspace");
238 const double dt = getProperty("TimeUnit"); // time unit increment, in picoseconds;
239 DataObjects::Workspace2D_sptr wsRe = std::dynamic_pointer_cast<DataObjects::Workspace2D>(
240 API::WorkspaceFactory::Instance().create("Workspace2D", nq, nt, nt));
241 const std::string wsReName = gwsName + std::string("_") + setName + std::string(".Re");
242 wsRe->setTitle(wsReName);
243
244 DataObjects::Workspace2D_sptr wsIm = std::dynamic_pointer_cast<DataObjects::Workspace2D>(
245 API::WorkspaceFactory::Instance().create("Workspace2D", nq, nt, nt));
246 const std::string wsImName = gwsName + std::string("_") + setName + std::string(".Im");
247 wsIm->setTitle(wsImName);
248
249 int origin = nnt - 1;
250 for (int iq = 0; iq < nq; iq++) {
251 auto &reX = wsRe->mutableX(iq);
252 auto &imX = wsIm->mutableX(iq);
253 auto &reY = wsRe->mutableY(iq);
254 auto &imY = wsIm->mutableY(iq);
255 const int index = sorting_indexes[iq];
256 auto curr = std::next(buf.cbegin(), index * nnt * 2);
257 for (int it = 0; it < nnt; it++) {
258 reX[origin + it] = it * dt; // time point for the real part
259 reY[origin + it] = *curr; // real part of the intermediate structure factor
260 reX[origin - it] = -it * dt; // symmetric negative time
261 reY[origin - it] = *curr; // symmetric value for the negative time
262 ++curr;
263 imX[origin + it] = it * dt;
264 imY[origin + it] = *curr;
265 imX[origin - it] = -it * dt;
266 imY[origin - it] = -(*curr); // antisymmetric value for negative times
267 ++curr;
268 }
269 }
270
271 // Set the Time unit for the X-axis
272 wsRe->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("Label");
273 auto unitPtr = std::dynamic_pointer_cast<Kernel::Units::Label>(wsRe->getAxis(0)->unit());
274 unitPtr->setLabel("Time", "picoseconds");
275
276 wsIm->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("Label");
277 unitPtr = std::dynamic_pointer_cast<Kernel::Units::Label>(wsIm->getAxis(0)->unit());
278 unitPtr->setLabel("Time", "picoseconds");
279
280 // Create a numeric axis to replace the default vertical one
281 auto verticalAxisRe = std::make_unique<API::NumericAxis>(nq);
282 auto verticalAxisIm = std::make_unique<API::NumericAxis>(nq);
283 auto verticalAxisReRaw = verticalAxisRe.get();
284 auto verticalAxisImRaw = verticalAxisIm.get();
285 wsRe->replaceAxis(1, std::move(verticalAxisRe));
286 wsIm->replaceAxis(1, std::move(verticalAxisIm));
287
288 // Now set the axis values
289 for (int i = 0; i < nq; ++i) {
290 verticalAxisReRaw->setValue(i, qvmod[i]);
291 verticalAxisImRaw->setValue(i, qvmod[i]);
292 }
293
294 // Set the axis units
295 verticalAxisReRaw->unit() = Kernel::UnitFactory::Instance().create("MomentumTransfer");
296 verticalAxisReRaw->title() = "|Q|";
297 verticalAxisImRaw->unit() = Kernel::UnitFactory::Instance().create("MomentumTransfer");
298 verticalAxisImRaw->title() = "|Q|";
299
300 // Set the X axis title (for conversion to MD)
301 wsRe->getAxis(0)->title() = "Energy transfer";
302 wsIm->getAxis(0)->title() = "Energy transfer";
303
304 // Register the workspaces
305 registerWorkspace(gws, wsReName, wsRe, "X-axis: time; Y-axis: real part of intermediate structure factor");
306 registerWorkspace(gws, wsImName, wsIm, "X-axis: time; Y-axis: imaginary part of intermediate structure factor");
307}
308
315 // Declare the Filename algorithm property. Mandatory. Sets the path to the
316 // file to load.
317 const std::vector<std::string> exts{".h5", ".hd5"};
318 declareProperty(std::make_unique<API::FileProperty>("Filename", "", API::FileProperty::Load, exts), "A Sassena file");
319 // Declare the OutputWorkspace property
321 std::make_unique<API::WorkspaceProperty<API::Workspace>>("OutputWorkspace", "", Kernel::Direction::Output),
322 "The name of the group workspace to be created.");
324 "The Time unit in between data points, in picoseconds. "
325 "Default is 1.0 picosec.");
326 declareProperty(std::make_unique<Kernel::PropertyWithValue<bool>>("SortByQVectors", true, Kernel::Direction::Input),
327 "Sort structure factors by increasing momentum transfer?");
328}
329
334 // auto
335 // gws=std::dynamic_pointer_cast<API::WorkspaceGroup>(getProperty("OutputWorkspace"));
336 // API::WorkspaceGroup_sptr gws=getProperty("OutputWorkspace");
337 API::Workspace_sptr ows = getProperty("OutputWorkspace");
338
339 API::WorkspaceGroup_sptr gws = std::dynamic_pointer_cast<API::WorkspaceGroup>(ows);
340 if (gws && API::AnalysisDataService::Instance().doesExist(gws->getName())) {
341 // gws->deepRemoveAll(); // remove workspace members
342 API::AnalysisDataService::Instance().deepRemoveGroup(gws->getName());
343 } else {
344 gws = std::make_shared<API::WorkspaceGroup>();
345 setProperty("OutputWorkspace", std::dynamic_pointer_cast<API::Workspace>(gws));
346 }
347
348 // populate m_validSets
349 int nvalidSets = 4;
350 const char *validSets[] = {"fq", "fq0", "fq2", "fqt"};
351 for (int iSet = 0; iSet < nvalidSets; iSet++)
352 this->m_validSets.emplace_back(validSets[iSet]);
353
354 // open the HDF5 file for reading
355 m_filename = this->getPropertyValue("Filename");
356 H5::H5File h5file;
357 try {
358 h5file = H5::H5File(m_filename.c_str(), H5F_ACC_RDONLY, Nexus::H5Util::defaultFileAcc());
359 } catch (H5::FileIException &) {
360 this->g_log.error("Cannot open " + m_filename);
361 throw Kernel::Exception::FileError("Unable to open:", m_filename);
362 }
363
364 // Block to read the Q-vectors
365 std::vector<int> sorting_indexes;
366 const auto qvmod = this->loadQvectors(h5file, gws, sorting_indexes);
367 if (qvmod.empty()) {
368 this->g_log.error("No Q-vectors read. Unable to proceed");
369 h5file.close();
370 return;
371 }
372
373 // iterate over the valid sets
374 for (std::vector<std::string>::const_iterator it = this->m_validSets.begin(); it != this->m_validSets.end(); ++it) {
375 std::string setName = *it;
376 if (h5file.nameExists(setName)) {
377 if (setName == "fq" || setName == "fq0" || setName == "fq2")
378 this->loadFQ(h5file, gws, setName, qvmod, sorting_indexes);
379 else if (setName == "fqt")
380 this->loadFQT(h5file, gws, setName, qvmod, sorting_indexes);
381 } else
382 this->g_log.information("Dataset " + setName + " not present in file");
383 } // end of iterate over the valid sets
384
385 h5file.close();
386} // end of LoadSassena::exec()
387
388} // namespace Mantid::DataHandling
std::map< DeltaEMode::Type, std::string > index
double left
double right
uint64_t hsize_t
#define DECLARE_NEXUS_FILELOADER_ALGORITHM(classname)
DECLARE_NEXUS_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro wh...
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:48
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Kernel::Logger & g_log
Definition Algorithm.h:422
@ Load
allowed here which will be passed to the algorithm
A property class for workspaces.
Load Sassena Output files.
Definition LoadSassena.h:45
std::string m_filename
name and path of input file
Definition LoadSassena.h:89
std::vector< std::string > m_validSets
valid datasets
Definition LoadSassena.h:87
void init() override
Initialization code.
void dataSetDouble(const H5::H5File &h5file, const std::string &setName, std::vector< double > &buf)
Read dataset data to a buffer ot type double.
void exec() override
Execution code.
HistogramData::Points loadQvectors(const H5::H5File &h5file, const API::WorkspaceGroup_sptr &gws, std::vector< int > &sorting_indexes)
Load qvectors dataset, calculate modulus of vectors.
void dataSetInfo(const H5::H5File &h5file, const std::string &setName, hsize_t *dims) const
Read info about one HDF5 dataset, log if error.
void registerWorkspace(const API::WorkspaceGroup_sptr &gws, const std::string &wsName, const DataObjects::Workspace2D_sptr &ws, const std::string &description)
Add a workspace to the group and register in the analysis data service.
void loadFQT(const H5::H5File &h5file, const API::WorkspaceGroup_sptr &gws, const std::string &setName, const HistogramData::Points &qvmod, const std::vector< int > &sorting_indexes)
Load time-dependent structure factor.
void loadFQ(const H5::H5File &h5file, const API::WorkspaceGroup_sptr &gws, const std::string &setName, const HistogramData::Points &qvmod, const std::vector< int > &sorting_indexes)
Load structure factor asa function of q-vector modulus.
Records the filename and the description of failure.
Definition Exception.h:98
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::pair< double, int > mypair
bool compare(const mypair &left, const mypair &right)
std::shared_ptr< Workspace2D > Workspace2D_sptr
shared pointer to Mantid::DataObjects::Workspace2D
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
MANTID_NEXUS_DLL H5::FileAccPropList defaultFileAcc()
Default file access is H5F_CLOSE_STRONG.
Definition H5Util.cpp:119
void readArray1DCoerce(const H5::Group &group, const std::string &name, std::vector< NumT > &output)
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54