Mantid
Loading...
Searching...
No Matches
LoadSpec.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 +
7//----------------------------------------------------------------------
8// Includes
9//----------------------------------------------------------------------
11#include "MantidAPI/Algorithm.h"
12#include "MantidAPI/Axis.h"
20
21#include <algorithm>
22#include <cstring>
23#include <fstream>
24
25namespace Mantid::DataHandling {
26// Register the algorithm into the algorithm factory
28
29using namespace Kernel;
30using namespace API;
31
33LoadSpec::LoadSpec() = default;
34
42 if (!descriptor.isAscii())
43 return 0;
44
45 auto &file = descriptor.data();
46
47 int confidence(0);
48 size_t axiscols(0), datacols(0);
49 std::string str;
51 const std::string sep = " ";
52 bool snsspec(false);
53
54 while (std::getline(file, str)) {
55 // File is opened in binary mode so getline will leave a \r at the end of an
56 // empty line if it exists
57 if (str.empty() || str == "\r")
58 continue;
59
60 try {
61 // if it's comment line
63 if (str.at(0) == '#') {
64 if (str.at(1) == 'L') {
65 axiscols = tok.count();
66 // if the file contains a comment line starting with "#L" followed
67 // by three columns this could be loadsnsspec file
68 if (axiscols > 2) {
69 snsspec = true;
70 }
71 }
72 } else {
73 // check first data line is a 3 column line
74 datacols = tok.count();
75 break;
76 }
77 } catch (std::out_of_range &) {
78 }
79 }
80 if (snsspec && datacols == 3) // three column data
81 {
82 confidence = 80;
83 }
84 return confidence;
85}
86
89 const std::vector<std::string> exts{".dat", ".txt"};
90 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, exts),
91 "The name of the text file to read, including its full or "
92 "relative path. The file extension must be .txt or .dat.");
93 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
94 "The name of the workspace that will be created, filled with the read-in "
95 "data and stored in the [[Analysis Data Service]].");
96
97 std::vector<std::string> units = UnitFactory::Instance().getKeys();
98 units.insert(units.begin(), "MomemtumTransfer");
99 declareProperty("Unit", "Energy", std::make_shared<Kernel::StringListValidator>(units),
100 "The unit to assign to the X axis (anything known to the "
101 "[[Unit Factory]] or \"Dimensionless\")");
102}
103
108 std::string filename = getProperty("Filename");
109 std::ifstream file(filename.c_str());
110
111 file.seekg(0, std::ios::end);
112 Progress progress(this, 0.0, 1.0, static_cast<int>(file.tellg()));
113 file.seekg(0, std::ios::beg);
114
115 std::string str;
116 std::vector<double> input;
117
118 const size_t nSpectra = readNumberOfSpectra(file);
119 auto localWorkspace =
120 std::dynamic_pointer_cast<MatrixWorkspace>(WorkspaceFactory::Instance().create("Workspace2D", nSpectra, 2, 1));
121
122 localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create(getProperty("Unit"));
123
124 file.clear(); // end of file has been reached so we need to clear file state
125 file.seekg(0, std::ios::beg); // go back to beginning of file
126
127 int specNum = -1; // spectrum number
128 while (getline(file, str)) {
129 progress.report(static_cast<int>(file.tellg()));
130
131 // line with data, need to be parsed by white spaces
132 readLine(str, input);
133
134 if (str.empty() && specNum != -1) {
135 auto histogram = localWorkspace->histogram(specNum);
136 readHistogram(input, histogram);
137 localWorkspace->setHistogram(specNum, histogram);
138 }
139
140 if (str.empty()) {
141 specNum++;
142 input.clear();
143 }
144
145 } // end of read file
146
147 try {
148 if (nSpectra == 0)
149 throw "Undefined number of spectra";
150
151 if (static_cast<size_t>(specNum) == (nSpectra - 1)) {
152 auto histogram = localWorkspace->histogram(specNum);
153 readHistogram(input, histogram);
154 localWorkspace->setHistogram(specNum, histogram);
155 }
156 } catch (...) {
157 }
158
159 setProperty("OutputWorkspace", localWorkspace);
160}
161
168size_t LoadSpec::readNumberOfSpectra(std::ifstream &file) const {
169 // determine the number of lines starting by #L
170 // as there is one per set of data
171 size_t spectra_nbr = 0;
172 std::string str;
173 while (getline(file, str)) {
174 if (str.empty())
175 continue;
176 if (str[0] == '#' && str[1] == 'L') {
177 spectra_nbr++;
178 }
179 }
180 return spectra_nbr;
181}
182
189void LoadSpec::readLine(const std::string &line, std::vector<double> &buffer) const {
190 if (!line.empty() && line[0] != '#') {
192 const std::string sep = " ";
194 buffer.reserve(buffer.size() + tok.size());
195 std::transform(tok.cbegin(), tok.cend(), std::back_inserter(buffer),
196 [](const auto &beg) { return std::stod(beg); });
197 }
198}
199
206void LoadSpec::readHistogram(const std::vector<double> &input, HistogramData::Histogram &histogram) const {
207 std::vector<double> x, y, e;
208
209 auto isHist = input.size() % 3 > 0;
210 auto nElements = (isHist) ? input.size() - 1 : input.size() - 2;
211
212 x.reserve(nElements);
213 y.reserve(nElements);
214 e.reserve(nElements);
215
216 for (size_t index = 0; index < nElements; index++) {
217 x.emplace_back(input[index]);
218 index++;
219 y.emplace_back(input[index]);
220 index++;
221 e.emplace_back(input[index]);
222 }
223
224 histogram.resize(y.size());
225
226 if (isHist) {
227 // we're loading binned data
228 // last value is final x bin
229 x.emplace_back(input.back());
230 histogram.setBinEdges(x);
231 } else {
232 histogram.setPoints(x);
233 }
234
235 histogram.setCounts(y);
236 histogram.setCountStandardDeviations(e);
237}
238
239} // namespace Mantid::DataHandling
std::map< DeltaEMode::Type, std::string > index
int64_t nSpectra
#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.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
@ Load
allowed here which will be passed to the algorithm
Helper class for reporting progress from algorithms.
Definition Progress.h:25
A property class for workspaces.
void exec() override
Executes the algorithm.
Definition LoadSpec.cpp:107
void init() override
Initialisation method.
Definition LoadSpec.cpp:88
void readHistogram(const std::vector< double > &input, HistogramData::Histogram &histogram) const
Helper method for reading a single histogram.
Definition LoadSpec.cpp:206
void readLine(const std::string &line, std::vector< double > &buffer) const
Helper method for reading a line from the file.
Definition LoadSpec.cpp:189
int confidence(Kernel::FileDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
Definition LoadSpec.cpp:41
size_t readNumberOfSpectra(std::ifstream &file) const
Helper method for reading the number of spectra from the file.
Definition LoadSpec.cpp:168
LoadSpec()
Empty constructor.
Defines a wrapper around an open file.
static bool isAscii(const std::string &filename, const size_t nbytes=256)
Returns true if the file is considered ascii.
std::istream & data()
Access the open file stream.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
@ TOK_IGNORE_EMPTY
ignore empty tokens
std::size_t size() const noexcept
Get the total number of tokens.
ConstIterator cend() const
Const iterator referring to the past-the-end element in the container.
ConstIterator cbegin() const
Const iterator referring to first element in the container.
std::size_t count() const
Get the total number of tokens.
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.
@ Output
An output workspace.
Definition Property.h:54