reader_utils.h
Go to the documentation of this file.
1 /* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
2  * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
3  * Author(s): Clement Maria, Pawel Dlotko, Clement Jamin
4  *
5  * Copyright (C) 2014 Inria
6  *
7  * Modification(s):
8  * - YYYY/MM Author: Description of the modification
9  */
10 
11 #ifndef READER_UTILS_H_
12 #define READER_UTILS_H_
13 
15 #include <gudhi/Debug_utils.h>
16 
17 # include <boost/iterator/function_output_iterator.hpp>
18 #include <boost/graph/adjacency_list.hpp>
19 
20 #include <iostream>
21 #include <fstream>
22 #include <map>
23 #include <limits> // for numeric_limits
24 #include <string>
25 #include <vector>
26 #include <utility> // for pair
27 #include <tuple> // for std::make_tuple
28 
29 namespace Gudhi {
30 
31 // Keep this file tag for Doxygen to parse the code, otherwise, functions are not documented.
32 // It is required for global functions and variables.
33 
46 inline void read_points(std::string file_name, std::vector<std::vector<double>>& points) {
47  std::ifstream in_file(file_name.c_str(), std::ios::in);
48  if (!in_file.is_open()) {
49  std::cerr << "Unable to open file " << file_name << std::endl;
50  return;
51  }
52 
53  std::string line;
54  double x;
55  while (getline(in_file, line)) {
56  std::vector<double> point;
57  std::istringstream iss(line);
58  while (iss >> x) {
59  point.push_back(x);
60  }
61  // Check for empty lines
62  if (!point.empty()) points.push_back(point);
63  }
64  in_file.close();
65 }
66 
83 template <typename Graph_t, typename Filtration_value, typename Vertex_handle>
84 Graph_t read_graph(std::string file_name) {
85  std::ifstream in_(file_name.c_str(), std::ios::in);
86  if (!in_.is_open()) {
87  std::string error_str("read_graph - Unable to open file ");
88  error_str.append(file_name);
89  std::cerr << error_str << std::endl;
90  throw std::invalid_argument(error_str);
91  }
92 
93  typedef std::pair<Vertex_handle, Vertex_handle> Edge_t;
94  std::vector<Edge_t> edges;
95  std::vector<Filtration_value> edges_fil;
96  std::map<Vertex_handle, Filtration_value> vertices;
97 
98  std::string line;
99  int dim;
100  Vertex_handle u, v, max_h = -1;
101  Filtration_value fil;
102  while (getline(in_, line)) {
103  std::istringstream iss(line);
104  while (iss >> dim) {
105  switch (dim) {
106  case 0: {
107  iss >> u;
108  iss >> fil;
109  vertices[u] = fil;
110  if (max_h < u) {
111  max_h = u;
112  }
113  break;
114  }
115  case 1: {
116  iss >> u;
117  iss >> v;
118  iss >> fil;
119  edges.push_back(Edge_t(u, v));
120  edges_fil.push_back(fil);
121  break;
122  }
123  default: { break; }
124  }
125  }
126  }
127  in_.close();
128 
129  if ((size_t)(max_h + 1) != vertices.size()) {
130  std::cerr << "Error: vertices must be labeled from 0 to n-1 \n";
131  }
132 
133  Graph_t skel_graph(edges.begin(), edges.end(), edges_fil.begin(), vertices.size());
134  auto vertex_prop = boost::get(vertex_filtration_t(), skel_graph);
135 
136  typename boost::graph_traits<Graph_t>::vertex_iterator vi, vi_end;
137  auto v_it = vertices.begin();
138  for (std::tie(vi, vi_end) = boost::vertices(skel_graph); vi != vi_end; ++vi, ++v_it) {
139  boost::put(vertex_prop, *vi, v_it->second);
140  }
141 
142  return skel_graph;
143 }
144 
157 template <typename Vertex_handle, typename Filtration_value>
158 bool read_simplex(std::istream& in_, std::vector<Vertex_handle>& simplex, Filtration_value& fil) {
159  int dim = 0;
160  if (!(in_ >> dim)) return false;
161  Vertex_handle v;
162  for (int i = 0; i < dim + 1; ++i) {
163  if (!(in_ >> v)) return false;
164  simplex.push_back(v);
165  }
166  if (!(in_ >> fil)) return false;
167  in_.ignore((std::numeric_limits<std::streamsize>::max)(), '\n'); // ignore until the carriage return
168  return true;
169 }
170 
182 template <typename Simplex_key, typename Filtration_value>
183 bool read_hasse_simplex(std::istream& in_, std::vector<Simplex_key>& boundary, Filtration_value& fil) {
184  int dim;
185  if (!(in_ >> dim)) return false;
186  if (dim == 0) {
187  in_ >> fil;
188  return true;
189  }
190  Simplex_key key;
191  for (int i = 0; i < dim + 1; ++i) {
192  in_ >> key;
193  boundary.push_back(key);
194  }
195  in_ >> fil;
196  return true;
197 }
198 
219 template <typename Filtration_value>
220 std::vector<std::vector<Filtration_value>> read_lower_triangular_matrix_from_csv_file(const std::string& filename,
221  const char separator = ';') {
222 #ifdef DEBUG_TRACES
223  std::clog << "Using procedure read_lower_triangular_matrix_from_csv_file \n";
224 #endif // DEBUG_TRACES
225  std::vector<std::vector<Filtration_value>> result;
226  std::ifstream in;
227  in.open(filename.c_str());
228  if (!in.is_open()) {
229  return result;
230  }
231 
232  std::string line;
233 
234  // the first line is empty, so we ignore it:
235  std::getline(in, line);
236  std::vector<Filtration_value> values_in_this_line;
237  result.push_back(values_in_this_line);
238 
239  int number_of_line = 0;
240 
241  // first, read the file line by line to a string:
242  while (std::getline(in, line)) {
243  // if line is empty, break
244  if (line.size() == 0) break;
245 
246  // if the last element of a string is comma:
247  if (line[line.size() - 1] == separator) {
248  // then shrink the string by one
249  line.pop_back();
250  }
251 
252  // replace all commas with spaces
253  std::replace(line.begin(), line.end(), separator, ' ');
254 
255  // put the new line to a stream
256  std::istringstream iss(line);
257  // and now read the doubles.
258 
259  int number_of_entry = 0;
260  std::vector<Filtration_value> values_in_this_line;
261  while (iss.good()) {
262  double entry;
263  iss >> entry;
264  if (number_of_entry <= number_of_line) {
265  values_in_this_line.push_back(entry);
266  }
267  ++number_of_entry;
268  }
269  if (!values_in_this_line.empty()) result.push_back(values_in_this_line);
270  ++number_of_line;
271  }
272  in.close();
273 
274 #ifdef DEBUG_TRACES
275  std::clog << "Here is the matrix we read : \n";
276  for (size_t i = 0; i != result.size(); ++i) {
277  for (size_t j = 0; j != result[i].size(); ++j) {
278  std::clog << result[i][j] << " ";
279  }
280  std::clog << std::endl;
281  }
282 #endif // DEBUG_TRACES
283 
284  return result;
285 } // read_lower_triangular_matrix_from_csv_file
286 
294 template <typename OutputIterator>
295 void read_persistence_intervals_and_dimension(std::string const& filename, OutputIterator out) {
296 #ifdef DEBUG_TRACES
297  std::clog << "read_persistence_intervals_and_dimension - " << filename << std::endl;
298 #endif // DEBUG_TRACES
299  std::ifstream in(filename);
300  if (!in.is_open()) {
301  std::string error_str("read_persistence_intervals_and_dimension - Unable to open file ");
302  error_str.append(filename);
303  std::cerr << error_str << std::endl;
304  throw std::invalid_argument(error_str);
305  }
306 
307  while (!in.eof()) {
308  std::string line;
309  getline(in, line);
310  if (line.length() != 0 && line[0] != '#') {
311  double numbers[4];
312  int n = sscanf(line.c_str(), "%lf %lf %lf %lf", &numbers[0], &numbers[1], &numbers[2], &numbers[3]);
313 #ifdef DEBUG_TRACES
314  std::clog << "[" << n << "] = ";
315  for (int i = 0; i < n; i++) {
316  std::clog << numbers[i] << ",";
317  }
318  std::clog << std::endl;
319 #endif // DEBUG_TRACES
320  if (n >= 2) {
321  int dim = (n >= 3 ? static_cast<int>(numbers[n - 3]) : -1);
322  *out++ = std::make_tuple(dim, numbers[n - 2], numbers[n - 1]);
323  }
324  }
325  }
326 }
327 
335 inline std::map<int, std::vector<std::pair<double, double>>> read_persistence_intervals_grouped_by_dimension(
336  std::string const& filename) {
337  std::map<int, std::vector<std::pair<double, double>>> ret;
339  filename, boost::make_function_output_iterator([&ret](std::tuple<int, double, double> t) {
340  ret[get<0>(t)].push_back(std::make_pair(get<1>(t), get<2>(t)));
341  }));
342  return ret;
343 }
344 
355 inline std::vector<std::pair<double, double>> read_persistence_intervals_in_dimension(std::string const& filename,
356  int only_this_dim = -1) {
357  std::vector<std::pair<double, double>> ret;
359  filename, boost::make_function_output_iterator([only_this_dim, &ret](std::tuple<int, double, double> t) {
360  if (only_this_dim == get<0>(t) || only_this_dim == -1) ret.emplace_back(get<1>(t), get<2>(t));
361  }));
362  return ret;
363 }
364 
365 } // namespace Gudhi
366 
367 #endif // READER_UTILS_H_
Graph simplicial complex methods.
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14
bool read_hasse_simplex(std::istream &in_, std::vector< Simplex_key > &boundary, Filtration_value &fil)
Read a hasse simplex from a file.
Definition: reader_utils.h:183
Graph_t read_graph(std::string file_name)
Read a graph from a file.
Definition: reader_utils.h:84
std::vector< std::pair< double, double > > read_persistence_intervals_in_dimension(std::string const &filename, int only_this_dim=-1)
Definition: reader_utils.h:355
void read_persistence_intervals_and_dimension(std::string const &filename, OutputIterator out)
Definition: reader_utils.h:295
std::map< int, std::vector< std::pair< double, double > > > read_persistence_intervals_grouped_by_dimension(std::string const &filename)
Definition: reader_utils.h:335
void read_points(std::string file_name, std::vector< std::vector< double >> &points)
Read a set of points to turn it into a vector< vector<double> > by filling points.
Definition: reader_utils.h:46
bool read_simplex(std::istream &in_, std::vector< Vertex_handle > &simplex, Filtration_value &fil)
Read a face from a file.
Definition: reader_utils.h:158
std::vector< std::vector< Filtration_value > > read_lower_triangular_matrix_from_csv_file(const std::string &filename, const char separator=';')
Read a lower triangular distance matrix from a csv file. We assume that the .csv store the whole (squ...
Definition: reader_utils.h:220
Value type for a filtration function on a cell complex.
Definition: FiltrationValue.h:20
Handle type for the vertices of a cell complex.
Definition: VertexHandle.h:15