Mantid
Loading...
Searching...
No Matches
LoadMcStasNexus.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 +
14#include "MantidKernel/Unit.h"
15// clang-format off
16#include <nexus/NeXusFile.hpp>
17#include <nexus/NeXusException.hpp>
18// clang-format on
19
20#include <boost/algorithm/string.hpp>
21
22namespace Mantid::DataHandling {
23using namespace Kernel;
24using namespace API;
25
27
28//----------------------------------------------------------------------------------------------
30const std::string LoadMcStasNexus::name() const { return "LoadMcStasNexus"; }
31
33int LoadMcStasNexus::version() const { return 1; }
34
36const std::string LoadMcStasNexus::category() const { return "DataHandling\\Nexus"; }
37
45 int confidence(0);
46 const auto &entries = descriptor.getAllEntries();
47 const static auto target_dataset = "information";
48 for (auto iter = entries.begin(); iter != entries.end(); ++iter) {
49 const auto grouped_entries = iter->second;
50 for (const auto &path : grouped_entries) {
51 // Mccode writes an information dataset so can be reasonably confident if we find it
52 if (boost::ends_with(path, target_dataset)) {
53 confidence = 40;
54 break;
55 }
56 }
57 }
58 return confidence;
59}
60
61//----------------------------------------------------------------------------------------------
62
63//----------------------------------------------------------------------------------------------
67 const std::vector<std::string> exts{".h5", ".nxs"};
68 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, exts),
69 "The name of the Nexus file to load");
70
71 declareProperty(std::make_unique<WorkspaceProperty<Workspace>>("OutputWorkspace", "", Direction::Output),
72 "An output workspace.");
73}
74
75//----------------------------------------------------------------------------------------------
79 std::string filename = getPropertyValue("Filename");
80 g_log.debug() << "Opening file " << filename << '\n';
81
82 ::NeXus::File nxFile(filename);
83 auto entries = nxFile.getEntries();
84 auto itend = entries.end();
85 WorkspaceGroup_sptr outputGroup(new WorkspaceGroup);
86
87 for (auto it = entries.begin(); it != itend; ++it) {
88 std::string name = it->first;
89 std::string type = it->second;
90 nxFile.openGroup(name, type);
91 auto dataEntries = nxFile.getEntries();
92
93 for (auto &dataEntry : dataEntries) {
94 const std::string &dataName = dataEntry.first;
95 const std::string &dataType = dataEntry.second;
96 if (dataName == "content_nxs" || dataType != "NXdata")
97 continue;
98 g_log.debug() << "Opening " << dataName << " " << dataType << '\n';
99
100 nxFile.openGroup(dataName, dataType);
101
102 // Find the axis names
103 auto nxdataEntries = nxFile.getEntries();
104 std::string axis1Name, axis2Name;
105 for (auto &nxdataEntry : nxdataEntries) {
106 if (nxdataEntry.second == "NXparameters")
107 continue;
108 nxFile.openData(nxdataEntry.first);
109 if (nxFile.hasAttr("axis")) {
110 int axisNo(0);
111 nxFile.getAttr("axis", axisNo);
112 if (axisNo == 1)
113 axis1Name = nxdataEntry.first;
114 else if (axisNo == 2)
115 axis2Name = nxdataEntry.first;
116 else
117 throw std::invalid_argument("Unknown axis number");
118 }
119 nxFile.closeData();
120 }
121
122 std::vector<double> axis1Values, axis2Values;
123 nxFile.readData<double>(axis1Name, axis1Values);
124 nxFile.readData<double>(axis2Name, axis2Values);
125
126 const auto axis1Length = axis1Values.size();
127 const auto axis2Length = axis2Values.size();
128 g_log.debug() << "Axis lengths=" << axis1Length << " " << axis2Length << '\n';
129
130 // Require "data" field
131 std::vector<double> data;
132 nxFile.readData<double>("data", data);
133
134 // Optional errors field
135 std::vector<double> errors;
136 try {
137 nxFile.readData<double>("errors", errors);
138 } catch (::NeXus::Exception &) {
139 g_log.information() << "Field " << dataName << " contains no error information.\n";
140 }
141
143 WorkspaceFactory::Instance().create("Workspace2D", axis2Length, axis1Length, axis1Length);
144 Axis *axis1 = ws->getAxis(0);
145 axis1->title() = axis1Name;
146 // Set caption
147 auto lblUnit = std::make_shared<Units::Label>();
148 lblUnit->setLabel(axis1Name, "");
149 axis1->unit() = lblUnit;
150
151 auto axis2 = std::make_unique<NumericAxis>(axis2Length);
152 auto axis2Raw = axis2.get();
153 axis2->title() = axis2Name;
154 // Set caption
155 lblUnit = std::make_shared<Units::Label>();
156 lblUnit->setLabel(axis2Name, "");
157 axis2->unit() = lblUnit;
158
159 ws->setYUnit(axis2Name);
160 ws->replaceAxis(1, std::move(axis2));
161
162 ws->mutableX(0) = axis1Values;
163
164 for (size_t wsIndex = 0; wsIndex < axis2Length; ++wsIndex) {
165 auto &dataY = ws->mutableY(wsIndex);
166 auto &dataE = ws->mutableE(wsIndex);
167 ws->setSharedX(wsIndex, ws->sharedX(0));
168
169 for (size_t j = 0; j < axis1Length; ++j) {
170 // Data is stored in column-major order so we are translating to
171 // row major for Mantid
172 const size_t fileDataIndex = j * axis2Length + wsIndex;
173
174 dataY[j] = data[fileDataIndex];
175 if (!errors.empty())
176 dataE[j] = errors[fileDataIndex];
177 }
178 axis2Raw->setValue(wsIndex, axis2Values[wsIndex]);
179 }
180 // Make Mantid store the workspace in the group
181 outputGroup->addWorkspace(ws);
182
183 nxFile.closeGroup();
184 }
185 nxFile.closeGroup();
186 }
187
188 setProperty("OutputWorkspace", outputGroup);
189}
190
191} // namespace Mantid::DataHandling
#define DECLARE_NEXUS_HDF5_FILELOADER_ALGORITHM(classname)
DECLARE_NEXUS_HDF5_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM mac...
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
Class to represent the axis of a workspace.
Definition: Axis.h:30
const std::string & title() const
Returns the user-defined title for this axis.
Definition: Axis.cpp:20
const std::shared_ptr< Kernel::Unit > & unit() const
The unit for this axis.
Definition: Axis.cpp:28
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
Class to hold a set of workspaces.
A property class for workspaces.
LoadMcStasNexus : TODO: DESCRIPTION.
const std::string name() const override
Algorithm's name for identification.
int confidence(Kernel::NexusHDF5Descriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
void init() override
Initialize the algorithm's properties.
void exec() override
Execute the algorithm.
int version() const override
Algorithm's version for identification.
const std::string category() const override
Algorithm's category for identification.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
const std::map< std::string, std::set< std::string > > & getAllEntries() const noexcept
Returns a const reference of the internal map holding all entries in the NeXus HDF5 file.
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
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
STL namespace.
@ Output
An output workspace.
Definition: Property.h:54