/* This file is part of the Gudhi Library. The Gudhi library
* (Geometric Understanding in Higher Dimensions) is a generic C++
* library for computational topology.
*
* Author(s): Pawel Dlotko
*
* Copyright (C) 2017 INRIA (France)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef READ_PERSISTENCE_FROM_FILE_H_
#define READ_PERSISTENCE_FROM_FILE_H_
#include
#include
#include
#include
#include
namespace Gudhi {
namespace Persistence_representations {
/**
* Universal procedure to read files with persistence. It ignores the lines starting from # (treat them as comments).
* It reads the fist line which is not a comment and assume that there are some numerical entries over there. The
*program assume
* that each other line in the file, which is not a comment, have the same number of numerical entries (2, 3 or 4).
* If there are two numerical entries per line, then the function assume that they are birth/death coordinates.
* If there are three numerical entries per line, then the function assume that they are: dimension and birth/death
*coordinates.
* If there are four numerical entries per line, then the function assume that they are: the characteristic of a filed
*over which
* persistence was computed, dimension and birth/death coordinates.
* The 'inf' string can appear only as a last element of a line.
* The procedure returns vector of persistence pairs.
**/
std::vector > read_persistence_intervals_in_one_dimension_from_file(
std::string const& filename, int dimension = -1, double what_to_substitute_for_infinite_bar = -1) {
bool dbg = false;
std::ifstream in;
in.open(filename);
// checking if the file exist:
if (!in.good()) {
std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n";
throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n";
}
std::string line;
std::vector > barcode;
int number_of_entries_per_line = -1;
while (!in.eof()) {
getline(in, line);
if (dbg) std::cerr << "Reading line : " << line << std::endl;
if (!(line.length() == 0 || line[0] == '#')) {
// If we do not know how many entries per line we have, we check it in below.
if (number_of_entries_per_line == -1) {
number_of_entries_per_line = 0;
std::string line_copy(line);
if (line_copy.find("inf") != std::string::npos) {
size_t np = line_copy.find("inf");
// replace symbols 'inf' in line_copy with white spaces:
line_copy[np] = ' ';
line_copy[np + 1] = ' ';
line_copy[np + 2] = ' ';
number_of_entries_per_line = 1;
}
// check how many entries we have in the line.
std::stringstream ss(line_copy);
double number;
std::vector this_line;
while (ss >> number) {
this_line.push_back(number);
}
number_of_entries_per_line += (int)this_line.size();
if (dbg) {
std::cerr << "number_of_entries_per_line : " << number_of_entries_per_line
<< ". This number was obtained by analyzing this line : " << line << std::endl;
}
if ((number_of_entries_per_line < 2) || (number_of_entries_per_line > 4)) {
std::cerr << "The input file you have provided have wrong number of numerical entries per line. The program "
"will now terminate. \n";
throw "The input file you have provided have wrong number of numerical entries per line. The program will now terminate. \n";
}
}
// In case there is an 'inf' string in this line, we are dealing with this situation in below.
if (line.find("inf") != std::string::npos) {
if (dbg) {
std::cerr << "This line: " << line << " contains infinite interval. \n";
}
// first we substitute inf by white spaces:
size_t np = line.find("inf");
line[np] = ' ';
line[np + 1] = ' ';
line[np + 2] = ' ';
if (what_to_substitute_for_infinite_bar != -1) {
double beginn, field, dim;
std::stringstream lineSS(line);
if (number_of_entries_per_line == 4) lineSS >> field;
if (number_of_entries_per_line >= 3) {
lineSS >> dim;
} else {
dim = dimension;
}
lineSS >> beginn;
if (dim == dimension) {
if (beginn > what_to_substitute_for_infinite_bar) {
barcode.push_back(std::make_pair(what_to_substitute_for_infinite_bar, beginn));
} else {
barcode.push_back(std::make_pair(beginn, what_to_substitute_for_infinite_bar));
}
if (dbg) {
std::cerr << "this is the line that is going to the output : " << beginn << " , "
<< what_to_substitute_for_infinite_bar << std::endl;
}
}
} else {
// this is a line with infinity. Since the variable what_to_substitute_for_infinite_bar have not been set up,
// it means that this line will be skipped.
if (dbg) {
std::cerr << "We will skip it \n";
}
}
continue;
} else {
// Then, we read the content of the line. We know that it do not contain 'inf' substring.
std::stringstream lineSS(line);
double beginn, endd, field, dim;
if (number_of_entries_per_line == 4) lineSS >> field;
if (number_of_entries_per_line >= 3) {
lineSS >> dim;
} else {
dim = dimension;
}
lineSS >> beginn;
lineSS >> endd;
if (beginn > endd) {
std::swap(beginn, endd);
}
if (dim == dimension) {
barcode.push_back(std::make_pair(beginn, endd));
if (dbg) {
std::cerr << "This is a line that is going to the output : " << beginn << " , " << endd << std::endl;
}
} else {
if ((number_of_entries_per_line == 3) && (dimension == -1)) {
barcode.push_back(std::make_pair(beginn, endd));
}
}
}
} else {
if (dbg) {
std::cerr << "This is a comment line \n";
}
}
}
in.close();
if (dbg) std::cerr << "End of reading \n";
return barcode;
} // read_persistence_intervals_in_one_dimension_from_file
} // namespace Persistence_representations
} // namespace Gudhi
#endif // READ_PERSISTENCE_FROM_FILE_H_