Mantid
Loading...
Searching...
No Matches
SaveDiffFittingAscii.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
10#include "MantidAPI/TableRow.h"
15#include "Poco/File.h"
16#include <boost/tokenizer.hpp>
17#include <fstream>
18
19namespace Mantid::DataHandling {
20
21using namespace Kernel;
22using namespace Mantid::API;
23
24// Register the algorithm into the algorithm factory
26
27
28SaveDiffFittingAscii::SaveDiffFittingAscii() : Mantid::API::Algorithm(), m_sep(','), m_counter(0) {
29 useAlgorithm("EnggSaveSinglePeakFitResultsToHDF5", 1);
30}
31
34
35 declareProperty(std::make_unique<WorkspaceProperty<ITableWorkspace>>("InputWorkspace", "", Direction::Input),
36 "The name of the workspace containing the data you want to "
37 "save to a TBL file");
38
39 // Declare required parameters, filename with ext {.his} and input
40 // workspace
41 const std::vector<std::string> exts{".txt", ".csv", ""};
42 declareProperty(std::make_unique<API::FileProperty>("Filename", "", API::FileProperty::Save, exts),
43 "The filename to use for the saved data");
44
45 declareProperty("RunNumber", "",
46 "Run number list of the focused files, which is used to generate the "
47 "parameters table workspace");
48
49 declareProperty("Bank", "",
50 "Bank number list of the focused files, which is used to generate "
51 "the parameters table workspace");
52
53 std::vector<std::string> formats;
54
55 formats.emplace_back("AppendToExistingFile");
56 formats.emplace_back("OverwriteFile");
57 declareProperty("OutMode", "AppendToExistingFile", std::make_shared<Kernel::StringListValidator>(formats),
58 "Over write the file or append data to existing file");
59}
60
65
66 // Retrieve the input workspace
68 const ITableWorkspace_sptr tbl_ws = getProperty("InputWorkspace");
69 if (!tbl_ws)
70 throw std::runtime_error("Please provide an input table workspace to be saved.");
71
72 std::vector<API::ITableWorkspace_sptr> input_ws;
73 input_ws.emplace_back(std::dynamic_pointer_cast<DataObjects::TableWorkspace>(tbl_ws));
74
75 processAll(input_ws);
76}
77
79
80 try {
81
82 std::string name = getPropertyValue("InputWorkspace");
83
85
86 std::vector<API::ITableWorkspace_sptr> input_ws;
87 input_ws.reserve(inputGroup->getNumberOfEntries());
88 for (int i = 0; i < inputGroup->getNumberOfEntries(); ++i) {
89 input_ws.emplace_back(std::dynamic_pointer_cast<ITableWorkspace>(inputGroup->getItem(i)));
90 }
91
92 processAll(input_ws);
93 } catch (std::runtime_error &rexc) {
94 g_log.error(std::string("Error while processing a group of workspaces. Details: ") + rexc.what() + '\n');
95 }
96
97 return true;
98}
99
100void SaveDiffFittingAscii::processAll(const std::vector<API::ITableWorkspace_sptr> &input_ws) {
101
102 const std::string filename = getProperty("Filename");
103 const std::string outMode = getProperty("OutMode");
104 std::string runNumList = getProperty("RunNumber");
105 std::string bankList = getProperty("Bank");
106
107 Poco::File pFile = (filename);
108 bool exist = pFile.exists();
109
110 bool appendToFile = false;
111 if (outMode == "AppendToExistingFile")
112 appendToFile = true;
113
114 // Initialize the file stream
115 std::ofstream file(filename.c_str(), (appendToFile ? std::ios::app : std::ios::out));
116
117 if (!file) {
118 throw Exception::FileError("Unable to create file: ", filename);
119 }
120
121 if (exist && !appendToFile) {
122 g_log.warning() << "File " << filename << " exists and will be overwritten."
123 << "\n";
124 }
125
126 if (exist && appendToFile) {
127 file << "\n";
128 }
129
130 // reset counter
131 m_counter = 0;
132
133 std::vector<std::string> splitRunNum = splitList(runNumList);
134 std::vector<std::string> splitBank = splitList(bankList);
135
136 // Create a progress reporting object
137 Progress progress(this, 0.0, 1.0, input_ws.size());
138
139 size_t breaker = input_ws.size();
140 if (outMode == "AppendToExistingFile" && input_ws.size() == 1)
141 breaker = 1;
142
143 for (size_t i = 0; i < breaker; ++i) {
144
145 std::string runNum = splitRunNum[m_counter];
146 std::string bank = splitBank[m_counter];
147
148 if (!runNum.empty() || !bank.empty())
149 writeInfo(runNum, bank, file);
150
151 // write header
152 std::vector<std::string> columnHeadings = input_ws[i]->getColumnNames();
153 writeHeader(columnHeadings, file);
154
155 // write out the data form the table workspace
156 size_t columnSize = columnHeadings.size();
157 writeData(input_ws[i], file, columnSize);
158
159 if (input_ws.size() > 1 && (i + 1) != input_ws.size()) {
160 file << '\n';
161 }
162 }
163 progress.report();
164}
165
166std::vector<std::string> SaveDiffFittingAscii::splitList(std::string strList) {
167 std::vector<std::string> splitList;
168 strList.erase(std::remove(strList.begin(), strList.end(), ' '), strList.end());
169 boost::split(splitList, strList, boost::is_any_of(","));
170
171 return splitList;
172}
173
174void SaveDiffFittingAscii::writeInfo(const std::string &runNumber, const std::string &bank, std::ofstream &file) {
175
176 file << "run number: " << runNumber << '\n';
177 file << "bank: " << bank << '\n';
178 m_counter++;
179}
180
181void SaveDiffFittingAscii::writeHeader(const std::vector<std::string> &columnHeadings, std::ofstream &file) {
182 for (const auto &heading : columnHeadings) {
183 // if last header in the table workspace, put eol
184 if (&heading == &columnHeadings.back()) {
185 writeVal(heading, file, true);
186 } else {
187 writeVal(heading, file, false);
188 }
189 }
190}
191
193 const size_t columnSize) {
194
195 for (size_t rowIndex = 0; rowIndex < workspace->rowCount(); ++rowIndex) {
196 TableRow row = workspace->getRow(rowIndex);
197 for (size_t columnIndex = 0; columnIndex < columnSize; columnIndex++) {
198
199 const auto row_str = boost::lexical_cast<std::string>(row.Double(columnIndex));
200 g_log.debug() << row_str << std::endl;
201
202 if (columnIndex == columnSize - 1)
203 writeVal(row_str, file, true);
204 else
205 writeVal(row_str, file, false);
206 }
207 }
208}
209
210void SaveDiffFittingAscii::writeVal(const std::string &val, std::ofstream &file, const bool endline) {
211 std::string valStr = boost::lexical_cast<std::string>(val);
212
213 // checking if it needs to be surrounded in
214 // quotes due to a comma being included
215 size_t comPos = valStr.find(',');
216 if (comPos != std::string::npos) {
217 file << '"' << val << '"';
218 } else {
219 file << boost::lexical_cast<std::string>(val);
220 }
221
222 if (endline) {
223 file << '\n';
224 } else {
225 file << m_sep;
226 }
227}
228
229std::map<std::string, std::string> SaveDiffFittingAscii::validateInputs() {
230 std::map<std::string, std::string> errors;
231
232 bool is_grp = true;
233
234 // check for null pointers - this is to protect against workspace groups
235 const std::string inputWS = getProperty("InputWorkspace");
236
238 API::WorkspaceGroup_const_sptr inGrp = std::dynamic_pointer_cast<const API::WorkspaceGroup>(inWks);
239
240 const ITableWorkspace_sptr tbl_ws = getProperty("InputWorkspace");
241 if (tbl_ws) {
242 is_grp = false;
243 }
244
245 if (!inGrp && !tbl_ws) {
246 std::string message = "The current version of this algorithm only "
247 "supports input workspaces of type TableWorkspace and WorkspaceGroup";
248 errors["InputWorkspace"] = message;
249 }
250
251 const std::string file = getProperty("Filename");
252 if (file.empty()) {
253 errors["Filename"] = "File name directory cannot be empty";
254 }
255
256 std::string runNumber = getPropertyValue("RunNumber");
257 std::vector<std::string> splitRunNum = splitList(runNumber);
258
259 std::string bankNumber = getPropertyValue("Bank");
260 std::vector<std::string> splitBank = splitList(bankNumber);
261
262 if (bankNumber.empty()) {
263 if (!runNumber.empty())
264 errors["Bank"] = "Please provide a valid bank list";
265 } else if (runNumber.empty()) {
266 errors["RunNumber"] = "Please provide a valid run number list";
267 } else if (!is_grp) {
268 if (splitRunNum.size() > 1) {
269 errors["RunNumber"] = "One run number should be provided when a Table"
270 "workspace is selected";
271 }
272 if (splitBank.size() > 1) {
273 errors["Bank"] = "One bank should be provided when a Table"
274 "Workspace is selected";
275 }
276 } else {
277 if (splitRunNum.size() != inGrp->size()) {
278 errors["RunNumber"] = "Run number list size should match the number of "
279 "TableWorkspaces in the GroupWorkspace selected";
280 }
281 if (splitBank.size() != inGrp->size()) {
282 errors["Bank"] = "Bank list size should match the number of "
283 "TableWorkspaces in the GroupWorkspace selected";
284 }
285 }
286
287 return errors;
288}
289
290} // namespace Mantid::DataHandling
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:85
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
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Kernel::Logger & g_log
Definition: Algorithm.h:451
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
@ Save
to specify a file to write to, the file may or may not exist
Definition: FileProperty.h:49
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
TableRow represents a row in a TableWorkspace.
Definition: TableRow.h:39
double & Double(size_t col)
Returns a reference to the element in position col if its type is double.
Definition: TableRow.h:137
Class to hold a set of workspaces.
A property class for workspaces.
void init() override
Initialisation code.
void writeHeader(const std::vector< std::string > &columnHeadings, std::ofstream &file)
std::vector< std::string > splitList(std::string strList)
void writeData(const API::ITableWorkspace_sptr &workspace, std::ofstream &file, const size_t columnSize)
std::map< std::string, std::string > validateInputs() override
Cross-check properties with each other.
void writeInfo(const std::string &runNumber, const std::string &bank, std::ofstream &file)
void writeVal(const std::string &val, std::ofstream &file, const bool endline)
bool processGroups() override
Process two groups and ensure the Result string is set properly on the final algorithm.
void processAll(const std::vector< API::ITableWorkspace_sptr > &input_ws)
Main exec routine, called for group or individual workspace processing.
const std::string name() const override
Algorithm's name.
Records the filename and the description of failure.
Definition: Exception.h:98
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
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
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< const WorkspaceGroup > WorkspaceGroup_const_sptr
shared pointer to Mantid::API::WorkspaceGroup, pointer to const version
Helper class which provides the Collimation Length for SANS instruments.
@ Input
An input workspace.
Definition: Property.h:53