Alexandria  2.27.0
SDC-CH common library for the Euclid project
AsciiParser.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2022 Euclid Science Ground Segment
3  *
4  * This library is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License as published by the Free
6  * Software Foundation; either version 3.0 of the License, or (at your option)
7  * any later version.
8  *
9  * This library is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
26 #include "XYDataset/AsciiParser.h"
29 #include "StringFunctions.h"
30 #include "Table/AsciiReader.h"
31 #include <boost/algorithm/string.hpp>
32 #include <boost/lexical_cast.hpp>
33 #include <fstream>
34 #include <iostream>
35 
36 namespace Euclid {
37 namespace XYDataset {
38 
39 //
40 // Get dataset name from ASCII file
41 //
43  // The data set name can be a parameter with keyword NAME
44  std::string dataset_name = getParameter(file, "NAME");
45 
46  if (dataset_name == "") {
47  // IF not present chack the first non-empty line (Backward comatibility)
48  std::ifstream sfile(file);
49  std::string line{};
50  // Check dataset name is in the file
51  // Convention: read until found first non empty line, removing empty lines.
52  while (line.empty() && sfile.good()) {
53  std::getline(sfile, line);
54  }
55 
56  regex::regex expression(m_regex_name);
57  regex::smatch s_match;
58  if (regex::regex_match(line, s_match, expression)) {
59  dataset_name = s_match[1].str();
60  } else {
61  // Dataset name is the filename without extension and path
62  std::string str{};
63  str = removeAllBeforeLastSlash(file);
64  dataset_name = removeExtension(str);
65  }
66  }
67 
68  return dataset_name;
69 }
70 
72  std::ifstream sfile(file);
73  if (!sfile) {
74  throw Elements::Exception() << "File does not exist : " << file;
75  }
76 
77  std::string value{};
78  std::string line{};
79  std::string dataset_name{};
80  std::string reg_ex_str = "^\\s*#\\s*" + key_word + "\\s*:\\s*(.+)\\s*$";
81  regex::regex expression(reg_ex_str);
82 
83  while (sfile.good()) {
84  std::getline(sfile, line);
85  regex::smatch s_match;
86  if (!line.empty() && regex::regex_match(line, s_match, expression)) {
87  if (value != "") {
88  value += ";";
89  }
90  std::string new_val = s_match[1].str();
91  boost::trim(new_val);
92  value += new_val;
93  }
94  }
95  return value;
96 }
97 
98 //
99 // Get dataset from ASCII file
100 //
102 
103  std::unique_ptr<XYDataset> dataset_ptr{};
104  std::ifstream sfile(file);
105  // Check file exists
106  if (sfile) {
107  // Read file into a Table object
108  auto table = Table::AsciiReader{sfile}.fixColumnTypes({typeid(double), typeid(double)}).read();
109  // Put the Table data into vector pair
110  std::vector<std::pair<double, double>> vector_pair(table.size());
111  std::transform(table.begin(), table.end(), vector_pair.begin(), [](const Table::Row& row) {
112  return std::make_pair(boost::get<double>(row[0]), boost::get<double>(row[1]));
113  });
114  dataset_ptr = make_unique<XYDataset>(std::move(vector_pair));
115  }
116 
117  return dataset_ptr;
118 }
119 
121  bool is_a_dataset_file = false;
122  std::ifstream sfile(file);
123  // Check file exists
124  if (sfile) {
125  std::string line{};
126  // Convention: read until found first non empty line, removing empty lines.
127  // Escape also the dataset name and comment lines
128  regex::regex expression("\\s*#.*");
129  regex::smatch s_match;
130  while ((line.empty() || regex::regex_match(line, s_match, expression)) && sfile.good()) {
131  std::getline(sfile, line);
132  }
133  if (sfile.good()) {
134  // We should have 2 double values only on one line
135  try {
136  std::stringstream ss(line);
137  std::string empty_string;
138  std::string d1;
139  std::string d2;
140  ss >> d1 >> d2 >> empty_string;
141  boost::lexical_cast<double>(d1);
142  boost::lexical_cast<double>(d2);
143  if (!empty_string.empty()) {
144  is_a_dataset_file = false;
145  } else {
146  is_a_dataset_file = true;
147  }
148  } catch (...) {
149  is_a_dataset_file = false;
150  }
151  } // Eof sfile.good()
152  } // Eof sfile
153  return is_a_dataset_file;
154 }
155 
156 } // namespace XYDataset
157 } // end of namespace Euclid
T begin(T... args)
TableReader implementation for reading ASCII tables from streams.
Definition: AsciiReader.h:87
Represents one row of a Table.
Definition: Row.h:57
std::string getParameter(const std::string &file, const std::string &key_word) override
Get the parameter identified by a given key_word value from a file.
Definition: AsciiParser.cpp:71
bool isDatasetFile(const std::string &file) override
Check that the ASCII file is a dataset file(with at least one line with 2 double values)
std::unique_ptr< XYDataset > getDataset(const std::string &file) override
Get a XYDataset object reading data from an ASCII file.
std::string getName(const std::string &file) override
Get the dataset name of a ASCII file.
Definition: AsciiParser.cpp:42
T empty(T... args)
T getline(T... args)
T good(T... args)
T move(T... args)
std::string removeExtension(const std::string &input_str)
std::string removeAllBeforeLastSlash(const std::string &input_str)
T str(T... args)
T transform(T... args)