22#include <nexus/NeXusFile.hpp>
23#include <nexus/NeXusException.hpp>
31#include <boost/regex.hpp>
46using Mantid::HistogramData::BinEdges;
56 if (
value ==
"NXSPE") {
59 boost::regex re(
"^NXSP", boost::regex::icase);
60 if (boost::regex_match(
value, re)) {
75 using string_map_t = std::map<std::string, std::string>;
77 ::NeXus::File file = ::NeXus::File(descriptor.
filename());
78 string_map_t entries = file.getEntries();
79 for (string_map_t::const_iterator it = entries.begin(); it != entries.end(); ++it) {
80 if (it->second ==
"NXentry") {
81 file.openGroup(it->first, it->second);
82 file.openData(
"definition");
83 const std::string
value = file.getStrData();
87 }
catch (::NeXus::Exception &) {
95 const std::vector<std::string> exts{
".nxspe",
""};
98 "The name of the workspace that will be created.");
107 ::NeXus::File file(filename);
108 std::string mainEntry = (*(file.getEntries().begin())).first;
109 file.openGroup(mainEntry,
"NXentry");
110 file.openData(
"definition");
112 throw std::invalid_argument(
"Not NXSPE");
116 throw std::invalid_argument(
"Not NeXus or not NXSPE");
120 ::NeXus::File file(filename);
122 std::string mainEntry = (*(file.getEntries().begin())).first;
123 file.openGroup(mainEntry,
"NXentry");
125 file.openGroup(
"NXSPE_info",
"NXcollection");
126 std::map<std::string, std::string> entries = file.getEntries();
127 std::vector<double> temporary;
128 double fixed_energy, psi = 0.;
130 if (!entries.count(
"fixed_energy")) {
131 throw std::invalid_argument(
"fixed_energy field was not found");
133 file.openData(
"fixed_energy");
134 file.getData(temporary);
135 fixed_energy = temporary.at(0);
138 if (entries.count(
"psi")) {
139 file.openData(
"psi");
140 file.getData(temporary);
141 psi = temporary.at(0);
142 if (std::isnan(psi)) {
144 g_log.
warning(
"Entry for PSI is empty, will use default of 0.0 instead.");
150 if (entries.count(
"ki_over_kf_scaling")) {
151 file.openData(
"ki_over_kf_scaling");
152 std::vector<int> temporaryint;
153 file.getData(temporaryint);
154 kikfscaling = temporaryint.at(0);
160 file.openGroup(
"data",
"NXdata");
161 entries = file.getEntries();
163 if (!entries.count(
"data")) {
164 throw std::invalid_argument(
"data field was not found");
166 file.openData(
"data");
167 ::NeXus::Info info = file.getInfo();
168 auto numSpectra =
static_cast<std::size_t
>(info.dims.at(0));
169 auto numBins =
static_cast<std::size_t
>(info.dims.at(1));
170 std::vector<double> data;
174 if (!entries.count(
"error")) {
175 throw std::invalid_argument(
"error field was not found");
177 file.openData(
"error");
178 std::vector<double>
error;
182 if (!entries.count(
"energy")) {
183 throw std::invalid_argument(
"energy field was not found");
185 file.openData(
"energy");
186 std::vector<double> energies;
187 file.getData(energies);
190 if (!entries.count(
"azimuthal")) {
191 throw std::invalid_argument(
"azimuthal field was not found");
193 file.openData(
"azimuthal");
194 std::vector<double> azimuthal;
195 file.getData(azimuthal);
198 if (!entries.count(
"azimuthal_width")) {
199 throw std::invalid_argument(
"azimuthal_width field was not found");
201 file.openData(
"azimuthal_width");
202 std::vector<double> azimuthal_width;
203 file.getData(azimuthal_width);
206 if (!entries.count(
"polar")) {
207 throw std::invalid_argument(
"polar field was not found");
209 file.openData(
"polar");
210 std::vector<double> polar;
214 if (!entries.count(
"polar_width")) {
215 throw std::invalid_argument(
"polar_width field was not found");
217 file.openData(
"polar_width");
218 std::vector<double> polar_width;
219 file.getData(polar_width);
223 std::vector<double> distance;
224 if (entries.count(
"distance")) {
225 file.openData(
"distance");
226 file.getData(distance);
232 file.openGroup(
"instrument",
"NXinstrument");
233 entries = file.getEntries();
234 std::string instrument_name;
235 if (entries.count(
"name")) {
236 file.openData(
"name");
237 instrument_name = file.getStrData();
246 if ((
error.size() != data.size()) || (azimuthal.size() != numSpectra) || (azimuthal_width.size() != numSpectra) ||
247 (polar.size() != numSpectra) || (polar_width.size() != numSpectra) ||
248 ((energies.size() != numBins) && (energies.size() != numBins + 1))) {
249 throw std::invalid_argument(
"incompatible sizes of fields in the NXSPE file");
256 outputWS->setYUnit(
"SpectraNumber");
261 outputWS->mutableRun().addLogData(
267 outputWS->mutableRun().setGoniometer(gm,
true);
273 source->
setPos(0.0, 0.0, -10.);
274 instrument->add(source);
275 instrument->markAsSource(source);
277 instrument->add(sample);
278 instrument->markAsSamplePos(sample);
280 constexpr double deg2rad = M_PI / 180.0;
282 for (std::size_t i = 0; i < numSpectra; ++i) {
284 if (!distance.empty()) {
289 pos.
spherical(r, polar.at(i), azimuthal.at(i));
291 double rr = r * sin(std::min(std::abs(polar_width.at(i)), std::abs(azimuthal_width.at(i))) *
deg2rad / 2);
297 instrument->add(det);
298 instrument->markAsDetector(det);
300 outputWS->setInstrument(instrument);
302 std::vector<double>::iterator itdata = data.begin(), iterror =
error.begin(), itdataend, iterrorend;
303 auto &spectrumInfo = outputWS->mutableSpectrumInfo();
305 BinEdges edges(std::move(energies));
306 for (std::size_t i = 0; i < numSpectra; ++i) {
307 itdataend = itdata + numBins;
308 iterrorend = iterror + numBins;
309 outputWS->getSpectrum(i).setDetectorID(
static_cast<detid_t>(i + 1));
310 outputWS->setBinEdges(i, edges);
311 if ((!std::isfinite(*itdata)) || (*itdata <= -1e10))
313 spectrumInfo.setMasked(i,
true);
315 outputWS->mutableY(i).assign(itdata, itdataend);
316 outputWS->mutableE(i).assign(iterror, iterrorend);
318 itdata = (itdataend);
319 iterror = (iterrorend);
325 if (!instrument_name.empty() && instrument_name !=
"NXSPE") {
327 std::string instrument_parfile = IDF_filename.substr(0, IDF_filename.find(
"_Definition")) +
"_Parameters.xml";
328 if (Poco::File(instrument_parfile).
exists()) {
331 loadParamAlg->setProperty(
"Filename", instrument_parfile);
332 loadParamAlg->setProperty(
"Workspace", outputWS);
333 loadParamAlg->execute();
340 outputWS->setDistribution(
true);
double value
The value of the point.
#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.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
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.
@ Load
allowed here which will be passed to the algorithm
static std::string getInstrumentFilename(const std::string &instrumentName, const std::string &date="")
Get the IDF using the instrument name and date.
Helper class for reporting progress from algorithms.
A property class for workspaces.
void init() override
Initialise the properties.
static int identiferConfidence(const std::string &value)
Confidence in identifier.
int confidence(Kernel::NexusDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
void exec() override
Run the algorithm.
Component is a wrapper for a Component which can modify some of its parameters, e....
void setPos(double, double, double) override
Set the IComponent position, x, y, z respective to parent (if present)
This class represents a detector - i.e.
Class to represent a particular goniometer setting, which is described by the rotation matrix.
void pushAxis(const std::string &name, double axisx, double axisy, double axisz, double angle=0., int sense=CCW, int angUnit=angDegrees)
Add an additional axis to the goniometer, closer to the sample.
Object Component class, this class brings together the physical attributes of the component to the po...
void setShape(std::shared_ptr< const IObject > newShape)
Set a new shape on the component void setShape(std::shared_ptr<const IObject> newShape);.
Class originally intended to be used with the DataHandling 'LoadInstrument' algorithm.
static std::shared_ptr< CSGObject > createSphere(const Kernel::V3D ¢re, double radius)
Create a Sphere.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
Defines a wrapper around a file whose internal structure can be accessed using the NeXus API.
const std::string & filename() const
Access the filename.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
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...
void spherical(const double R, const double theta, const double phi) noexcept
Sets the vector position based on spherical coordinates.
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
bool exists(::NeXus::File &file, const std::string &name)
Based on the current group in the file, does the named sub-entry exist?
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.
constexpr double deg2rad
Defines units/enum for Crystal work.
std::shared_ptr< Instrument > Instrument_sptr
Shared pointer to an instrument object.
int32_t detid_t
Typedef for a detector ID.
@ Output
An output workspace.