FML
FileUtils.cpp
Go to the documentation of this file.
1#include "FileUtils.h"
2#include <cassert>
3#include <fstream>
4#include <iostream>
5#include <random>
6#include <sstream>
7
8namespace FML {
9 namespace FILEUTILS {
10
11 // Read a regular ascii files with nskip header lines and containing ncol collums
12 // nestimated_lines is the amount we allocate for originally. Reallocated if file is larger
13 // Not perfect for realy large files due to all the allocations we have to do
15 int ncols,
16 std::vector<int> cols_to_keep,
17 int nskip,
18 size_t nestimated_lines) {
19
20 // Sanity check
21 assert(cols_to_keep.size() > 0 and nskip >= 0 and ncols > 0);
22 for (auto & i : cols_to_keep)
23 assert(i < ncols and i >= 0);
24
25 // Open file
26 std::ifstream fp(filename.c_str());
27 if (!fp) {
28 throw std::runtime_error("[read_regular_ascii] Failed to open [" + filename + "]\n");
29 }
30
31 // Allocate memory for reading
32 int ntokeep = int(cols_to_keep.size());
33 DVector2D result;
34 result.reserve(nestimated_lines);
35
36 // For reading the file
37 DVector newline(ntokeep);
38 DVector temp(ncols);
39
40 // Read and skip header lines
41 for (int i = 0; i < nskip; i++) {
42 std::string line;
43 std::getline(fp, line);
44#ifdef DEBUG_READASCII
45 std::cout << "Skipping headerline: " << line << "\n";
46#endif
47 }
48
49 // Read first entry and check that it has the right number of columns
50 std::string line;
51 std::getline(fp, line);
52 std::stringstream ss;
53 ss << line;
54 int count = 0;
55 while (ss >> line) {
56 temp[count] = std::stod(line);
57 ++count;
58 }
59 for (int i = 0; i < ntokeep; i++)
60 newline[i] = temp[cols_to_keep[i]];
61 result.push_back(newline);
62 if (count != ncols) {
63 throw std::runtime_error("Found ncols " + std::to_string(count) + " which differs from specified " +
64 std::to_string(ncols) + "\n");
65 }
66
67 // Read the rest of the file
68 while (1) {
69 fp >> temp[0];
70 if (fp.eof())
71 break;
72 for (int i = 1; i < ncols; i++)
73 fp >> temp[i];
74 for (int i = 0; i < ntokeep; i++)
75 newline[i] = temp[cols_to_keep[i]];
76#ifdef DEBUG_READASCII
77 if (result.size() < 10) {
78 std::cout << "Line " << result.size() - 1 << " : ";
79 for (auto e : result[result.size() - 1])
80 std::cout << e << " ";
81 std::cout << std::endl;
82 }
83#endif
84 result.push_back(newline);
85 }
86 return result;
87 }
88
89 // Read a regular ascii files with nskip header lines and containing ncol collums
90 // nestimated_lines is the amount we allocate for originally. Reallocated if file is larger
91 // Not perfect for realy large files due to all the allocations we have to do
93 int ncols,
94 std::vector<int> cols_to_keep,
95 int nskip,
96 size_t nestimated_lines,
97 double fraction_to_read,
98 unsigned int randomSeed) {
99 std::mt19937 generator(randomSeed);
100 auto udist = std::uniform_real_distribution<double>(0.0, 1.0);
101
102 // Sanity check
103 assert(cols_to_keep.size() > 0 and nskip >= 0 and ncols > 0);
104 for (auto & i : cols_to_keep)
105 assert(i < ncols and i >= 0);
106
107 // Open file
108 std::ifstream fp(filename.c_str());
109 if (!fp) {
110 throw std::runtime_error("[read_regular_ascii] Failed to open [" + filename + "]\n");
111 }
112
113 // Allocate memory for reading
114 int ntokeep = int(cols_to_keep.size());
115 DVector2D result;
116 result.reserve(nestimated_lines);
117
118 // For reading the file
119 DVector newline(ntokeep);
120 DVector temp(ncols);
121
122 // Read and skip header lines
123 for (int i = 0; i < nskip; i++) {
124 std::string line;
125 std::getline(fp, line);
126#ifdef DEBUG_READASCII
127 std::cout << "Skipping headerline: " << line << "\n";
128#endif
129 }
130
131 // Read first entry and check that it has the right number of columns
132 std::string line;
133 std::getline(fp, line);
134 std::stringstream ss;
135 ss << line;
136 int count = 0;
137 while (ss >> line) {
138 temp[count] = std::stod(line);
139 ++count;
140 }
141 for (int i = 0; i < ntokeep; i++)
142 newline[i] = temp[cols_to_keep[i]];
143 result.push_back(newline);
144 if (count != ncols) {
145 throw std::runtime_error("Found ncols " + std::to_string(count) + " which differs from specified " +
146 std::to_string(ncols) + "\n");
147 }
148
149 // Read the rest of the file
150 while (1) {
151 fp >> temp[0];
152 if (fp.eof())
153 break;
154 for (int i = 1; i < ncols; i++)
155 fp >> temp[i];
156 for (int i = 0; i < ntokeep; i++)
157 newline[i] = temp[cols_to_keep[i]];
158#ifdef DEBUG_READASCII
159 if (result.size() < 10) {
160 std::cout << "Line " << result.size() - 1 << " : ";
161 for (auto e : result[result.size() - 1])
162 std::cout << e << " ";
163 std::cout << std::endl;
164 }
165#endif
166 if (fraction_to_read >= 1.0)
167 result.push_back(newline);
168 else if (udist(generator) < fraction_to_read)
169 result.push_back(newline);
170 }
171 return result;
172 }
173
174 /// Read a regular file and extract two columns (numbering starting with 0)
175 std::pair<DVector, DVector> read_file_and_extract_two_columns(std::string filename, int col1, int col2) {
176 auto data = loadtxt(filename);
177
178 DVector x, y;
179 for (auto & row : data) {
180 x.push_back(row[col1]);
181 y.push_back(row[col2]);
182 }
183 return {x, y};
184 }
185
186 /// Similar to pythons loadtxt function
187 /// Gives warning if file is not regular
188 /// Skips lines starting with #, ! or /
189 DVector2D loadtxt(std::string filename, int nreserve_rows, int nreserve_cols) {
190
191 // Open file
192 std::ifstream fp(filename.c_str());
193 if (!fp) {
194 throw std::runtime_error("[loadtxt] Failed to open [" + filename + "]\n");
195 }
196
197 // Allocate memory for reading
198 DVector2D result;
199 result.reserve(nreserve_rows);
200
201 // Read the file line by line
202 while (true) {
203
204 // Read line
205 std::string line;
206 std::getline(fp, line);
207
208 if (!fp)
209 break;
210
211 // Skip line if # or ! or /
212 if (line[0] == '#' or line[0] == '!' or line[0] == '/')
213 continue;
214
215 // Read line as a set of doubles
216 std::stringstream ss;
217 std::vector<double> row;
218 row.reserve(nreserve_cols);
219 ss << line;
220 while (ss >> line) {
221 row.push_back(std::stod(line));
222 }
223
224 // Add to result
225 result.push_back(row);
226 }
227
228 // Check if the result is regular
229 size_t size = result.size();
230 if (size > 0) {
231 size_t ncol1 = result[0].size();
232 size_t ncolmin = ncol1;
233 size_t ncolmax = 0;
234 for (size_t j = 1; j < size; j++) {
235 ncolmin = std::min(ncolmin, result[j].size());
236 ncolmax = std::max(ncolmax, result[j].size());
237 }
238 if (ncolmin != ncolmax) {
239 std::cout << "[loadtxt] Warning the file " + filename + " is not regular\n";
240 std::cout << "The minimum number of columns is " << ncolmin << "\n";
241 std::cout << "The maximum number of columns is " << ncolmax << "\n";
242 }
243 }
244
245 return result;
246 }
247
248 } // namespace FILEUTILS
249} // namespace FML
const std::string filename
Definition: Main.cpp:63
FML::INTERPOLATION::SPLINE::DVector2D DVector2D
Definition: CAMBReader.h:15
std::pair< DVector, DVector > read_file_and_extract_two_columns(std::string filename, int col1, int col2)
Read a regular file and extract two columns (numbering starting with 0)
Definition: FileUtils.cpp:175
DVector2D loadtxt(std::string filename, int nreserve_rows, int nreserve_cols)
Similar to pythons loadtxt function Gives warning if file is not regular Skips lines starting with #,...
Definition: FileUtils.cpp:189
FML::INTERPOLATION::SPLINE::DVector DVector
Definition: CAMBReader.h:13
DVector2D read_regular_ascii_subsampled(std::string filename, int ncols, std::vector< int > cols_to_keep, int nskip, size_t nestimated_lines, double fraction_to_read, unsigned int randomSeed)
As above, but include every line read with probabillity fraction_to_read.
Definition: FileUtils.cpp:92
DVector2D read_regular_ascii(std::string filename, int ncols, std::vector< int > cols_to_keep, int nskip, size_t nestimated_lines)
Read a regular ascii files with nskip header lines and containing ncol collums nestimated_lines is th...
Definition: FileUtils.cpp:14
Definition: CAMBReader.h:10
return y
Definition: Global.h:265
std::mt19937 generator
Definition: Global.cpp:45
data
Definition: test.py:10
x
Definition: test.py:18