Mantid
Loading...
Searching...
No Matches
LoadSPE.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 +
8#include "MantidAPI/Axis.h"
15#include "MantidKernel/Unit.h"
17
18#include <cstdio>
19#include <fstream>
20#include <limits>
21
22namespace Mantid::DataHandling {
23
24using namespace Kernel;
25using namespace API;
26
28
29
35int LoadSPE::confidence(Kernel::FileDescriptor &descriptor) const {
36 if (!descriptor.isAscii())
37 return 0;
38
39 auto &file = descriptor.data();
40
41 std::string fileline;
42 // First line - expected to be a line 2 columns which is histogram & bin
43 // numbers
44 std::getline(file, fileline);
45 std::istringstream is(fileline);
46 unsigned int dummy(0);
47 is >> dummy >> dummy;
48 if (is.fail()) {
49 return 0; // Couldn't read 2 numbers so fail
50 }
51 // Trying to read another should produce eof
52 is >> dummy;
53 if (!is.eof())
54 return 0;
55
56 // Next line should be comment line: "### Phi Grid" or "### Q Grid"
57 std::getline(file, fileline);
58 if (fileline.find("Phi Grid") != std::string::npos || fileline.find("Q Grid") != std::string::npos) {
59 return 80;
60 } else
61 return 0;
62}
63
64//---------------------------------------------------
65// Private member functions
66//---------------------------------------------------
67
72 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, ".spe"),
73 "The name of the SPE file to load.");
74 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
75 "The name to use for the output workspace");
76}
77
82 // Retrieve filename and try to open the file
83 m_filename = getPropertyValue("Filename");
84
85 FILE *speFile;
86 speFile = fopen(m_filename.c_str(), "r");
87 if (!speFile) {
88 g_log.error("Failed to open file: " + m_filename);
89 throw Exception::FileError("Failed to open file: ", m_filename);
90 }
91
92 // The first two numbers are the number of histograms and the number of bins
93 size_t nhist = 0, nbins = 0;
94 unsigned int nhistTemp = 0, nbinsTemp = 0;
95 int retval = fscanf(speFile, "%8u%8u\n", &nhistTemp, &nbinsTemp);
96 if (retval != 2)
97 reportFormatError("Header line");
98 // Cast from temp values to size_t values
99 nhist = static_cast<size_t>(nhistTemp);
100 nbins = static_cast<size_t>(nbinsTemp);
101
102 // Next line should be comment line: "### Phi Grid" or "### Q Grid"
103 char comment[100];
104 fgets(comment, 100, speFile);
105 if (comment[0] != '#')
106 reportFormatError(std::string(comment));
107
108 // Create the axis that will hold the phi values
109 auto phiAxis = std::make_unique<BinEdgeAxis>(nhist + 1);
110 // Look at previously read comment field to see what unit vertical axis should
111 // have
112 if (comment[4] == 'Q' || comment[4] == 'q') {
113 phiAxis->unit() = UnitFactory::Instance().create("MomentumTransfer");
114 } else {
115 phiAxis->unit() = std::make_shared<Units::Phi>();
116 }
117
118 // Read in phi grid
119 for (size_t i = 0; i <= nhist; ++i) {
120 double phi;
121 retval = fscanf(speFile, "%10le", &phi);
122 if (retval != 1) {
123 std::stringstream ss;
124 ss << "Reading phi value" << i;
125 reportFormatError(ss.str());
126 }
127 phiAxis->setValue(i, phi);
128 }
129 // Read to EOL
130 fgets(comment, 100, speFile);
131
132 // Next line should be comment line: "### Energy Grid"
133 fgets(comment, 100, speFile);
134 if (comment[0] != '#')
135 reportFormatError(std::string(comment));
136
137 // Now the X bin boundaries
138 std::vector<double> X(nbins + 1);
139 for (size_t i = 0; i <= nbins; ++i) {
140 retval = fscanf(speFile, "%10le", &X[i]);
141 if (retval != 1) {
142 std::stringstream ss;
143 ss << "Reading energy value" << i;
144 reportFormatError(ss.str());
145 }
146 }
147 HistogramData::BinEdges XValues(std::move(X));
148
149 // Read to EOL
150 fgets(comment, 100, speFile);
151
152 // Now create the output workspace
153 MatrixWorkspace_sptr workspace = WorkspaceFactory::Instance().create("Workspace2D", nhist, nbins + 1, nbins);
154 workspace->getAxis(0)->unit() = UnitFactory::Instance().create("DeltaE");
155 workspace->setDistribution(true); // It should be a distribution
156 workspace->setYUnitLabel("S(Phi,Energy)");
157 // Replace the default spectrum axis with the phi values one
158 workspace->replaceAxis(1, std::move(phiAxis));
159
160 // Now read in the data spectrum-by-spectrum
161 Progress progress(this, 0.0, 1.0, nhist);
162 for (size_t j = 0; j < nhist; ++j) {
163 // Set the common X vector
164 workspace->setBinEdges(j, XValues);
165 // Read in the Y & E data
166 readHistogram(speFile, workspace, j);
167
168 progress.report();
169 }
170
171 // Close the file
172 fclose(speFile);
173
174 // Set the output workspace property
175 setProperty("OutputWorkspace", workspace);
176}
177
184 // First, there should be a comment line
185 char comment[100];
186 fgets(comment, 100, speFile);
187 if (comment[0] != '#')
188 reportFormatError(std::string(comment));
189
190 // Then it's the Y values
191 auto &Y = workspace->mutableY(index);
192 const size_t nbins = workspace->blocksize();
193 int retval;
194 for (size_t i = 0; i < nbins; ++i) {
195 retval = fscanf(speFile, "%10le", &Y[i]);
196 if (retval != 1) {
197 std::stringstream ss;
198 ss << "Reading data value" << i << " of histogram " << index;
199 reportFormatError(ss.str());
200 }
201 // -10^30 is the flag for not a number used in SPE files (from
202 // www.mantidproject.org/images/3/3d/Spe_file_format.pdf)
203 if (Y[i] == SaveSPE::MASK_FLAG) {
204 Y[i] = std::numeric_limits<double>::quiet_NaN();
205 }
206 }
207 // Read to EOL
208 fgets(comment, 100, speFile);
209
210 // Another comment line
211 fgets(comment, 100, speFile);
212 if (comment[0] != '#')
213 reportFormatError(std::string(comment));
214
215 // And then the error values
216 auto &E = workspace->mutableE(index);
217 for (size_t i = 0; i < nbins; ++i) {
218 retval = fscanf(speFile, "%10le", &E[i]);
219 if (retval != 1) {
220 std::stringstream ss;
221 ss << "Reading error value" << i << " of histogram " << index;
222 reportFormatError(ss.str());
223 }
224 }
225 // Read to EOL
226 fgets(comment, 100, speFile);
227}
228
233void LoadSPE::reportFormatError(const std::string &what) {
234 g_log.error("Unexpected formatting in file " + m_filename + " : " + what);
235 throw Exception::FileError("Unexpected formatting in file: ", m_filename);
236}
237
238} // namespace Mantid::DataHandling
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#define DECLARE_FILELOADER_ALGORITHM(classname)
DECLARE_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro when wri...
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
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
A property class for workspaces.
Loads an SPE format file into a Mantid workspace.
Definition: LoadSPE.h:30
void readHistogram(FILE *speFile, const API::MatrixWorkspace_sptr &workspace, size_t index)
Reads in the data corresponding to a single spectrum.
Definition: LoadSPE.cpp:183
void init() override
Initialise the algorithm.
Definition: LoadSPE.cpp:71
void reportFormatError(const std::string &what)
Called if the file is not formatted as expected.
Definition: LoadSPE.cpp:233
std::string m_filename
The file to load.
Definition: LoadSPE.h:54
void exec() override
Execute the algorithm.
Definition: LoadSPE.cpp:81
static const double MASK_FLAG
the mask flag (=-1e30) from the SPE specification http://www.mantidproject.org/images/3/3d/Spe_file_f...
Definition: SaveSPE.h:70
Records the filename and the description of failure.
Definition: Exception.h:98
Defines a wrapper around an open file.
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:77
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
@ Output
An output workspace.
Definition: Property.h:54