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;
53 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 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(line.substr(lastComma + 1, pos - (lastComma + 1)));
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
void csvParse(const std::string &line, std::vector< std::string > &cols, 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.
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.
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.