19#include <boost/tokenizer.hpp>
21#include <boost/algorithm/string.hpp>
26using namespace Kernel;
39 const std::string &filePath = descriptor.
filename();
40 const size_t filenameLength = filePath.size();
44 if (filenameLength > 12 ? (filePath.compare(filenameLength - 12, 12,
"_runinfo.xml") == 0)
45 :
false || filenameLength > 6 ? (filePath.compare(filenameLength - 6, 6,
".peaks") == 0)
46 :
false || filenameLength > 10 ? (filePath.compare(filenameLength - 10, 10,
".integrate") == 0)
49 }
else if (descriptor.
isAscii()) {
50 std::istream &stream = descriptor.
data();
51 std::string firstLine;
54 std::vector<std::string> columns;
55 if (
getCells(firstLine, columns, 16,
true) == 17)
57 if (filePath.compare(filenameLength - 4, 4,
".tbl") == 0) {
66 }
catch (
const std::length_error &) {
80 size_t pos = line.find(
',', 0);
81 if (pos != std::string::npos) {
84 while (pos != std::string::npos) {
85 pos = line.find(
',', pos + 1);
86 if (pos != std::string::npos) {
103 while (quoteOne != std::string::npos && quoteTwo != std::string::npos) {
105 quoteOne = line.find(
'"');
107 quoteOne = line.find(
'"', quoteTwo + 1);
109 if (quoteOne != std::string::npos) {
110 quoteTwo = line.find(
'"', quoteOne + 1);
111 if (quoteTwo != std::string::npos) {
112 std::vector<size_t> quotepair;
113 quotepair.emplace_back(quoteOne);
114 quotepair.emplace_back(quoteTwo);
115 quoteBounds.emplace_back(quotepair);
119 return quoteBounds.size();
133 const std::vector<std::vector<size_t>> "eBounds,
size_t expectedCommas)
const {
135 size_t lastComma = 0;
137 bool firstCheck =
true;
138 bool firstCell =
true;
140 while (pos != std::string::npos) {
142 pos = line.find(
',');
146 pos = line.find(
',', pos + 1);
149 if (pos != std::string::npos) {
150 if (pairID < quoteBounds.size() && pos > quoteBounds.at(pairID).at(0)) {
151 if (pos > quoteBounds.at(pairID).at(1)) {
153 cols.emplace_back(line.substr(quoteBounds.at(pairID).at(0) + 1,
154 quoteBounds.at(pairID).at(1) - (quoteBounds.at(pairID).at(0) + 1)));
159 cols.emplace_back(line.substr(0, pos));
162 auto colVal = line.substr(lastComma + 1, pos - (lastComma + 1));
163 cols.emplace_back(colVal);
168 if (lastComma + 1 < line.length()) {
169 cols.emplace_back(line.substr(lastComma + 1));
171 cols.emplace_back(
"");
175 if (cols.size() != expectedCommas + 1) {
176 std::string message =
"A line must contain " +
std::to_string(expectedCommas) +
" cell-delimiting commas. Found " +
178 throw std::length_error(message);
194size_t LoadTBL::getCells(std::string line, std::vector<std::string> &cols,
size_t expectedCommas,
bool isOldTBL)
const {
198 if (found == expectedCommas) {
202 boost::split(cols, line, boost::is_any_of(
","), boost::token_compress_off);
203 }
else if (found < expectedCommas) {
205 std::string message =
"A line must contain " +
std::to_string(expectedCommas) +
207 throw std::length_error(message);
211 std::vector<std::vector<size_t>> quoteBounds;
215 if (quoteBounds.empty()) {
216 std::string message =
"A line must contain " +
std::to_string(expectedCommas) +
218 throw std::length_error(message);
223 csvParse(line, cols, quoteBounds, expectedCommas);
226 std::vector<std::vector<size_t>> quoteBounds;
228 csvParse(line, cols, quoteBounds, expectedCommas);
229 if (cols.size() > expectedCommas) {
230 for (
size_t i = expectedCommas + 1; i < cols.size(); i++) {
231 cols[expectedCommas].append(boost::lexical_cast<std::string>(
"," + cols[i]));
233 }
else if (cols.size() < expectedCommas) {
234 std::string message =
"A line must contain " +
std::to_string(expectedCommas) +
236 throw std::length_error(message);
242 boost::split(cols, line, boost::is_any_of(
","), boost::token_compress_off);
243 std::string firstEntry = cols[0];
244 if (std::all_of(firstEntry.begin(), firstEntry.end(), ::isdigit)) {
258 "The name of the table file to read, including its full or "
259 "relative path. The file extension must be .tbl");
261 "The name of the workspace that will be created.");
269 std::ifstream file(filename.c_str());
277 std::vector<std::string> columnHeadings;
283 boost::split(columnHeadings, line, boost::is_any_of(
","), boost::token_compress_off);
284 for (
auto entry = columnHeadings.begin(); entry != columnHeadings.end();) {
285 if (entry->empty()) {
287 entry = columnHeadings.erase(entry);
293 if (columnHeadings.empty()) {
295 throw std::runtime_error(
"The file you are trying to load is Empty. \n "
296 "Please load a non-empty TBL file");
299 columnHeadings.clear();
305 std::vector<std::string> rowVec;
309 ws->addColumn(
"str",
"StitchGroup");
310 ws->addColumn(
"str",
"Run(s)");
311 ws->addColumn(
"str",
"ThetaIn");
312 ws->addColumn(
"str",
"TransRun(s)");
313 ws->addColumn(
"str",
"Qmin");
314 ws->addColumn(
"str",
"Qmax");
315 ws->addColumn(
"str",
"dq/q");
316 ws->addColumn(
"str",
"Scale");
317 ws->addColumn(
"str",
"Options");
318 ws->addColumn(
"str",
"HiddenOptions");
320 for (
size_t i = 0; i < ws->columnCount(); i++) {
321 auto col = ws->getColumn(i);
328 std::ifstream fileReopened(filename.c_str());
332 std::string lineRevisited;
335 if (lineRevisited.empty() || lineRevisited ==
",,,,,,,,,,,,,,,,") {
338 getCells(lineRevisited, rowVec, 16, isOld);
339 const std::string scaleStr = rowVec.at(16);
340 const std::string stitchStr = boost::lexical_cast<std::string>(stitchID);
344 if (!rowVec[0].empty() || !rowVec[1].empty() || !rowVec[2].empty() || !rowVec[3].empty() || !rowVec[4].empty()) {
347 for (
int i = 0; i < 5; ++i) {
350 row << rowVec.at(15);
356 if (!rowVec[5].empty() || !rowVec[6].empty() || !rowVec[7].empty() || !rowVec[8].empty() || !rowVec[9].empty()) {
359 for (
int i = 5; i < 10; ++i) {
362 row << rowVec.at(15);
368 if (!rowVec[10].empty() || !rowVec[11].empty() || !rowVec[12].empty() || !rowVec[13].empty() ||
369 !rowVec[14].empty()) {
372 for (
int i = 10; i < 17; ++i) {
386 if (!columnHeadings.empty()) {
389 for (
auto heading = columnHeadings.begin(); heading != columnHeadings.end();) {
390 if (heading->empty()) {
392 heading = columnHeadings.erase(heading);
395 col = ws->addColumn(
"str", *heading);
401 size_t expectedCommas = columnHeadings.size() - 1;
403 if (line.empty() || line ==
",,,,,,,,,,,,,,,,") {
407 getCells(line, rowVec, columnHeadings.size() - 1, isOld);
410 for (
size_t i = 0; i < expectedCommas + 1; ++i) {
#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.
@ Load
allowed here which will be passed to the algorithm
TableRow represents a row in a TableWorkspace.
A property class for workspaces.
void init() override
Declare properties.
bool getColumnHeadings(std::string line, std::vector< std::string > &cols)
Split into Column headings with respect to comma delimiters.
void exec() override
Execute the algorithm.
int confidence(Kernel::FileDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
size_t countCommas(const std::string &line) const
count the number of commas in the line
size_t findQuotePairs(const std::string &line, std::vector< std::vector< size_t > > "eBounds) const
find all pairs of quotes in the line
size_t getCells(std::string line, std::vector< std::string > &cols, size_t expectedCommas, bool isOldTBL) const
Split into columns with respect to the comma delimiters.
void csvParse(const std::string &line, std::vector< std::string > &cols, const std::vector< std::vector< size_t > > "eBounds, size_t expectedCommas) const
Parse more complex CSV, used when the data involves commas in the data and quoted values.
LoadTBL()
Default constructor.
Records the filename and the description of failure.
Defines a wrapper around an open file.
const std::string & filename() const
Access the filename.
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...
std::shared_ptr< Column > Column_sptr
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
MANTID_KERNEL_DLL std::istream & extractToEOL(std::istream &is, std::string &str)
Extract a line from input stream, discarding any EOL characters encountered.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Output
An output workspace.