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/Axis.h"
18
19#include <algorithm>
20#include <cstring>
21#include <fstream>
22
23namespace Mantid::DataHandling {
24// Register the algorithm into the algorithm factory
25DECLARE_ALGORITHM(LoadSpec)
26
27using namespace Kernel;
28using namespace API;
29
31LoadSpec::LoadSpec() = default;
32
35 const std::vector<std::string> exts{".dat", ".txt"};
36 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, exts),
37 "The name of the text file to read, including its full or "
38 "relative path. The file extension must be .txt or .dat.");
39 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
40 "The name of the workspace that will be created, filled with the read-in "
41 "data and stored in the [[Analysis Data Service]].");
42
43 std::vector<std::string> units = UnitFactory::Instance().getKeys();
44 units.insert(units.begin(), "MomemtumTransfer");
45 declareProperty("Unit", "Energy", std::make_shared<Kernel::StringListValidator>(units),
46 "The unit to assign to the X axis (anything known to the "
47 "[[Unit Factory]] or \"Dimensionless\")");
48}
49
54 std::string filename = getProperty("Filename");
55 std::ifstream file(filename.c_str());
56
57 file.seekg(0, std::ios::end);
58 Progress progress(this, 0.0, 1.0, static_cast<int>(file.tellg()));
59 file.seekg(0, std::ios::beg);
60
61 std::string str;
62 std::vector<double> input;
63
64 const size_t nSpectra = readNumberOfSpectra(file);
65 auto localWorkspace =
66 std::dynamic_pointer_cast<MatrixWorkspace>(WorkspaceFactory::Instance().create("Workspace2D", nSpectra, 2, 1));
67
68 localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create(getProperty("Unit"));
69
70 file.clear(); // end of file has been reached so we need to clear file state
71 file.seekg(0, std::ios::beg); // go back to beginning of file
72
73 int specNum = -1; // spectrum number
74 while (getline(file, str)) {
75 progress.report(static_cast<int>(file.tellg()));
76
77 // line with data, need to be parsed by white spaces
78 readLine(str, input);
79
80 if (str.empty() && specNum != -1) {
81 auto histogram = localWorkspace->histogram(specNum);
82 readHistogram(input, histogram);
83 localWorkspace->setHistogram(specNum, histogram);
84 }
85
86 if (str.empty()) {
87 specNum++;
88 input.clear();
89 }
90
91 } // end of read file
92
93 try {
94 if (nSpectra == 0)
95 throw "Undefined number of spectra";
96
97 if (static_cast<size_t>(specNum) == (nSpectra - 1)) {
98 auto histogram = localWorkspace->histogram(specNum);
99 readHistogram(input, histogram);
100 localWorkspace->setHistogram(specNum, histogram);
101 }
102 } catch (...) {
103 }
104
105 setProperty("OutputWorkspace", localWorkspace);
106}
107
114size_t LoadSpec::readNumberOfSpectra(std::ifstream &file) const {
115 // determine the number of lines starting by #L
116 // as there is one per set of data
117 size_t spectra_nbr = 0;
118 std::string str;
119 while (getline(file, str)) {
120 if (str.empty())
121 continue;
122 if (str[0] == '#' && str[1] == 'L') {
123 spectra_nbr++;
124 }
125 }
126 return spectra_nbr;
127}
128
135void LoadSpec::readLine(const std::string &line, std::vector<double> &buffer) const {
136 if (!line.empty() && line[0] != '#') {
138 const std::string sep = " ";
140 buffer.reserve(buffer.size() + tok.size());
141 std::transform(tok.cbegin(), tok.cend(), std::back_inserter(buffer),
142 [](const auto &beg) { return std::stod(beg); });
143 }
144}
145
152void LoadSpec::readHistogram(const std::vector<double> &input, HistogramData::Histogram &histogram) const {
153 std::vector<double> x, y, e;
154
155 auto isHist = input.size() % 3 > 0;
156 auto nElements = (isHist) ? input.size() - 1 : input.size() - 2;
157
158 x.reserve(nElements);
159 y.reserve(nElements);
160 e.reserve(nElements);
161
162 for (size_t index = 0; index < nElements; index++) {
163 x.emplace_back(input[index]);
164 index++;
165 y.emplace_back(input[index]);
166 index++;
167 e.emplace_back(input[index]);
168 }
169
170 histogram.resize(y.size());
171
172 if (isHist) {
173 // we're loading binned data
174 // last value is final x bin
175 x.emplace_back(input.back());
176 histogram.setBinEdges(x);
177 } else {
178 histogram.setPoints(x);
179 }
180
181 histogram.setCounts(y);
182 histogram.setCountStandardDeviations(e);
183}
184
185} // namespace Mantid::DataHandling
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
int nSpectra
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
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
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.
void exec() override
Executes the algorithm.
Definition: LoadSpec.cpp:53
void init() override
Initialisation method.
Definition: LoadSpec.cpp:34
void readHistogram(const std::vector< double > &input, HistogramData::Histogram &histogram) const
Helper method for reading a single histogram.
Definition: LoadSpec.cpp:152
void readLine(const std::string &line, std::vector< double > &buffer) const
Helper method for reading a line from the file.
Definition: LoadSpec.cpp:135
size_t readNumberOfSpectra(std::ifstream &file) const
Helper method for reading the number of spectra from the file.
Definition: LoadSpec.cpp:114
LoadSpec()
Empty constructor.
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::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