Persistence 1D incl. Reconstruct1D  1.3
Finding extrema in one dimensional data, filtering them by persistence and reconstructing smooth functions
persistence1d_driver.cpp
Go to the documentation of this file.
1 /*! \file persistence1d_driver.cpp
2  * Use this program to run Persistence1D on data in text files.
3  *
4  * This file contains a sample code for using Persistence1D on data in text files, and
5  * can be used to directly run Persistence1D on data in a single text file.
6  *
7  * Command line: persistence1d_driver.exe <filename> [threshold] [-MATLAB]
8  * - filename is the path to a data text file.
9  * Data is assumed to be formatted as a single float-compatible value per row.
10  * - [Optional] threshold is a floating point value. Acceptable threshold value >= 0
11  * - [Optional] -MATLAB - output indices match Matlab 1-indexing convention.
12  * Output: - Indices of extrema, written to a text file, one value per row.
13  Indices of paired extrema are written in consecutive rows.
14  * Indices are ordered according to their persistence, from most to least persistence.
15  * Even rows contain indices of minima.
16  * Odd rows contain indices of maxima.
17  * The global minimum is written in the last line. It is not paired with a maximum.
18  * Hence, we have an odd number of lines in the output.
19  * Output filename: <filename>_res.txt
20  *
21  */
22 
23 
24 #include "persistence1d.hpp"
25 
26 #include <fstream>
27 #include <string>
28 #include <cstring>
29 
30 #define MATLAB "-MATLAB"
31 
32 using namespace std;
33 using namespace p1d;
34 
35 
36 /*!
37  Tries to open the input file and read its contents to a float vector.
38 
39  Input is assumed to be formatted as one number per line, in float compatible notation.
40 
41  Ignores any lines which do not conform to this assumption.
42 
43  Number of data entries is assumed to be smaller than vector's class maximum size - this is not checked!
44 
45  @param[in] filename Name of input file with float data.
46  @param[out] data Data is written to this vector.
47 */
48 bool ReadFileToVector(char* filename, vector<float>& data);
49 /*!
50  Writes indices of extrema features to file, sorted according to their persistence.
51 
52  If no features were found, writes an empty file.
53 
54  Overwrites any existing file with the same name.
55 
56  @param[in] filename Name of output file.
57  @param[in] pairs Pairs of extrema to write.
58  @param[in] idxGlobalMin Index of the global minimum.
59 
60 */
61 void WriteExtremaToFile(char* filename, vector<TPairedExtrema> pairs, const int idxGlobalMin);
62 /*!
63  Parses user command line.
64  Checks if the user set a threshold value or wants MATLAB indexing.
65 */
66 bool ParseCmdLine(int argc, char* argv[], float &threshold, bool & matlabIndexing);
67 
68 /*!
69  Main function - reads a file specified as a command line argument. runs persistence,
70  writes the indices of extrema to a file called inputfilename_res.txt.
71 
72  Overwrites files with the same name.
73 
74  Input file name is assumed to end with a three letter extension.
75 */
76 int main(int argc, char* argv[])
77 {
78  vector<float> data;
79  vector<int> indices;
80  float threshold;
81  vector <TPairedExtrema> pairs;
82  bool matlabIndexing;
83  Persistence1D p;
84 
85  if (argc < 2)
86  {
87  cout << "No filename" << endl;
88  cout << "Usage: " << argv[0] << " <filename> [threshold] [-MATLAB]" << endl;
89  return false;
90  }
91 
92  //filename processing, easier done here.
93  char * filename = argv[1];
94  char * outfilename = new char[strlen(filename) + strlen("_res.txt")];
95  strcpy(outfilename, filename);
96 
97  outfilename[strlen(filename)-4] = '\0';
98  strcat(outfilename, "_res.txt");
99 
100  if (!ParseCmdLine(argc, argv, threshold, matlabIndexing))
101  {
102  cout << "Usage: " << argv[0] << " <filename> [threshold] [-MATLAB]" << endl;
103  return -1;
104  }
105 
106  if(!ReadFileToVector(filename, data))
107  {
108  cout << "Error reading data to file." << endl;
109  return -2;
110  }
111 
112  p.RunPersistence(data);
113  p.GetPairedExtrema(pairs, threshold , matlabIndexing);
114  const int idxGlobalMin = p.GetGlobalMinimumIndex(matlabIndexing);
115  WriteExtremaToFile(outfilename, pairs, idxGlobalMin);
116 
117  delete outfilename;
118 
119  return 0;
120 }
121 
122 bool ReadFileToVector (char * filename, vector<float> & data)
123 {
124  ifstream datafile;
125 
126  //check the datadfile actually exists
127  datafile.open(filename, ifstream::in);
128 
129 
130  if(!datafile)
131  {
132  cout << "Cannot open file " << filename << " for reading" << endl;
133  return false;
134  }
135 
136  float currdata;
137 
138  while(datafile >> currdata)
139  {
140  data.push_back(currdata);
141  }
142 
143  datafile.close();
144  return true;
145 }
146 void WriteExtremaToFile(char* filename, vector<TPairedExtrema> pairs, const int idxGlobalMin)
147 {
148  ofstream datafile;
149  datafile.open(filename);
150 
151  if (!datafile)
152  {
153  cout << "Cannot open file " << filename << " for writing." << endl;
154  return;
155  }
156 
157  for (vector<TPairedExtrema>::iterator p = pairs.begin(); p != pairs.end(); p++)
158  {
159  datafile << to_string((long long)(*p).MinIndex) << endl;
160  datafile << to_string((long long)(*p).MaxIndex) << endl;
161  }
162 
163  datafile << to_string((long long)idxGlobalMin) << endl;
164 
165  datafile.close();
166 }
167 bool ParseCmdLine(int argc, char* argv[], float &threshold, bool & matlabIndexing)
168 {
169  bool noErrors = true;
170 
171  threshold = 0.0;
172  matlabIndexing = false;
173 
174  //now let's find out if anyone wants MATLAB indexing or threshold values
175  for (int counter = 2; counter < argc ; counter ++)
176  {
177  if (argv[counter][0]=='-' && matlabIndexing == false)
178  {
179  if (strcmp(argv[counter],"-MATLAB") == 0 ||
180  strcmp(argv[counter],"-Matlab") == 0 ||
181  strcmp(argv[counter],"-matlab") == 0 )
182  {
183  //turn on matlab indexing
184  matlabIndexing = true;
185  }
186  else
187  {
188  cout << "Possibly misspelled Matlab flag or negative values for threshold." << endl;
189  noErrors = false;
190  }
191  }
192  else if ( argv[counter][0] == '0') //different from nullptr
193  {
194  //this doesn't throw exceptions, AKAIK
195  threshold = (float)atof(argv[counter]);
196 
197  //string begins with 0,
198  //so it's ok that atof returns 0
199  //not much can be done about other errors, will set threshold to 0
200 
201  //check that value is positive - this really should not happen
202  if (threshold < 0)
203  {
204  cout << "Error. Threshold value should be >= 0. Rerun with valid threshold value or leave out to get all features.\n";
205  noErrors = false;
206  }
207  }
208  else
209  {
210  //this doesn't throw exceptions, AKAIK
211  threshold = (float)atof(argv[counter]);
212 
213  //the string does not include a 0, but atof returns 0.
214  //string cannot be converted to threshold value
215  if (threshold == 0.0)
216  {
217  cout << "Cannot convert threshold value to number.\n" << endl;
218  noErrors = false;
219  }
220  else if (threshold < 0)
221  {
222  cout << "Error. Threshold value should be >= 0. Rerun with valid threshold value or leave out to get all features.\n";
223  noErrors = false;
224  }
225  }
226 
227  }
228  return noErrors;
229 }
bool ReadFileToVector(char *filename, vector< float > &data)
Tries to open the input file and read its contents to a float vector.
bool ParseCmdLine(int argc, char *argv[], float &threshold, bool &matlabIndexing)
Parses user command line.
void WriteExtremaToFile(char *filename, vector< TPairedExtrema > pairs, const int idxGlobalMin)
Writes indices of extrema features to file, sorted according to their persistence.
int GetGlobalMinimumIndex(const bool matlabIndexing=false) const
Returns the index of the global minimum.
bool RunPersistence(const std::vector< float > &InputData)
Call this function with a vector of one dimensional data to find extrema features in the data.
Finds extrema and their persistence in one-dimensional data.
bool GetPairedExtrema(std::vector< TPairedExtrema > &pairs, const float threshold=0, const bool matlabIndexing=false) const
Use this method to get the results of RunPersistence.
int main(int argc, char *argv[])
Main function - reads a file specified as a command line argument.
Actual code.