PolyFEM
Loading...
Searching...
No Matches
MatrixIO.cpp
Go to the documentation of this file.
1#include "MatrixIO.hpp"
2
4
5#include <igl/list_to_matrix.h>
6
7#include <iostream>
8#include <h5pp/h5pp.h>
9
10#include <fstream>
11#include <iomanip> // setprecision
12#include <vector>
13#include <filesystem>
14
15namespace polyfem::io
16{
17 template <typename T>
18 bool read_matrix(const std::string &path, Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &mat)
19 {
20 std::string extension = std::filesystem::path(path).extension().string();
21 std::transform(extension.begin(), extension.end(), extension.begin(),
22 [](unsigned char c) { return std::tolower(c); });
23
24 if (extension == ".txt")
25 {
26 return read_matrix_ascii(path, mat);
27 }
28 else if (extension == ".bin")
29 {
30 return read_matrix_binary(path, mat);
31 }
32 else
33 {
34 bool success = read_matrix_ascii(path, mat);
35 if (!success)
36 success = read_matrix_binary(path, mat); // Try with the binary format reader
37 return success;
38 }
39 }
40
41 template <typename Mat>
42 bool write_matrix(const std::string &path, const Mat &mat)
43 {
44 std::string extension = std::filesystem::path(path).extension().string();
45 std::transform(extension.begin(), extension.end(), extension.begin(),
46 [](unsigned char c) { return std::tolower(c); });
47
48 if (extension == ".txt")
49 {
50 return write_matrix_ascii(path, mat);
51 }
52 else if (extension == ".bin")
53 {
54 return write_matrix_binary(path, mat);
55 }
56 else
57 {
58 logger().warn("Uknown output matrix format (\"{}\"). Using ASCII format.");
59 return write_matrix_ascii(path, mat);
60 }
61 }
62
63 template <typename Mat>
64 bool write_matrix(const std::string &path, const std::string &key, const Mat &mat, const bool replace)
65 {
66 h5pp::File hdf5_file(path, replace ? h5pp::FileAccess::REPLACE : h5pp::FileAccess::READWRITE);
67 hdf5_file.writeDataset(mat, key);
68
69 return true;
70 }
71
72 template <typename Mat>
73 bool read_matrix(const std::string &path, const std::string &key, Mat &mat)
74 {
75 h5pp::File hdf5_file(path, h5pp::FileAccess::READONLY);
76 if (!hdf5_file.linkExists(key))
77 return false;
78 mat = hdf5_file.readDataset<Mat>(key);
79 return true;
80 }
81
82 template <typename T>
83 bool read_matrix_ascii(const std::string &path, Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &mat)
84 {
85 std::fstream file;
86 file.open(path.c_str());
87
88 if (!file.good())
89 {
90 logger().error("Failed to open file: {}", path);
91 file.close();
92
93 return false;
94 }
95
96 std::string s;
97 std::vector<std::vector<T>> matrix;
98
99 while (getline(file, s))
100 {
101 if (s.empty())
102 continue;
103 std::stringstream input(s);
104 T temp;
105 matrix.emplace_back();
106
107 std::vector<T> &currentLine = matrix.back();
108
109 while (input >> temp)
110 currentLine.push_back(temp);
111 }
112
113 if (!igl::list_to_matrix(matrix, mat))
114 {
115 logger().error("list to matrix error");
116 file.close();
117
118 return false;
119 }
120
121 return true;
122 }
123
124 template <typename Mat>
125 bool write_matrix_ascii(const std::string &path, const Mat &mat)
126 {
127 std::ofstream out(path);
128 if (!out.good())
129 {
130 logger().error("Failed to write to file: {}", path);
131 out.close();
132
133 return false;
134 }
135
136 out.precision(15);
137 out << mat;
138 out.close();
139
140 return true;
141 }
142
143 template <typename T>
144 bool read_matrix_binary(const std::string &path, Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &mat)
145 {
146 typedef typename Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>::Index Index;
147
148 std::ifstream in(path, std::ios::in | std::ios::binary);
149 if (!in.good())
150 {
151 logger().error("Failed to open file: {}", path);
152 in.close();
153
154 return false;
155 }
156
157 Index rows = 0, cols = 0;
158 in.read((char *)(&rows), sizeof(Index));
159 in.read((char *)(&cols), sizeof(Index));
160
161 mat.resize(rows, cols);
162 in.read((char *)mat.data(), rows * cols * sizeof(T));
163 in.close();
164
165 return true;
166 }
167
168 template <typename Mat>
169 bool write_matrix_binary(const std::string &path, const Mat &mat)
170 {
171 typedef typename Mat::Index Index;
172 typedef typename Mat::Scalar Scalar;
173 std::ofstream out(path, std::ios::out | std::ios::binary);
174
175 if (!out.good())
176 {
177 logger().error("Failed to write to file: {}", path);
178 out.close();
179
180 return false;
181 }
182
183 const Index rows = mat.rows(), cols = mat.cols();
184 out.write((const char *)(&rows), sizeof(Index));
185 out.write((const char *)(&cols), sizeof(Index));
186 out.write((const char *)mat.data(), rows * cols * sizeof(Scalar));
187 out.close();
188
189 return true;
190 }
191
192 bool write_sparse_matrix_csv(const std::string &path, const Eigen::SparseMatrix<double> &mat)
193 {
194 std::ofstream csv(path, std::ios::out);
195
196 if (!csv.good())
197 {
198 logger().error("Failed to write to file: {}", path);
199 csv.close();
200
201 return false;
202 }
203
204 csv << std::setprecision(std::numeric_limits<long double>::digits10 + 2);
205
206 csv << fmt::format("shape,{},{}\n", mat.rows(), mat.cols());
207 csv << "Row,Col,Val\n";
208 for (int k = 0; k < mat.outerSize(); ++k)
209 {
210 for (Eigen::SparseMatrix<double>::InnerIterator it(mat, k); it; ++it)
211 {
212 csv << it.row() << "," // row index
213 << it.col() << "," // col index (here it is equal to k)
214 << it.value() << "\n";
215 }
216 }
217 csv.close();
218
219 return true;
220 }
221
222 template <typename T>
224 const std::string &path, const json &import, Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &mat)
225 {
226 bool success;
227 if (import.contains("offset"))
228 {
229 const int offset = import["offset"];
230
231 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> tmp;
232 success = read_matrix(path, tmp);
233 if (success)
234 {
235 assert(mat.rows() >= offset && mat.cols() >= 1);
236 mat.block(0, 0, offset, 1) = tmp.block(0, 0, offset, 1);
237 }
238 }
239 else
240 {
241 success = read_matrix(path, mat);
242 }
243 return success;
244 }
245
246 // template instantiation
247 template bool read_matrix<int>(const std::string &, Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic> &);
248 template bool read_matrix<double>(const std::string &, Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> &);
249
250 template bool read_matrix<Eigen::MatrixXi>(const std::string &, const std::string &, Eigen::MatrixXi &);
251 template bool read_matrix<Eigen::MatrixXd>(const std::string &, const std::string &, Eigen::MatrixXd &);
252
253 template bool write_matrix<Eigen::MatrixXd>(const std::string &, const Eigen::MatrixXd &);
254 template bool write_matrix<Eigen::MatrixXf>(const std::string &, const Eigen::MatrixXf &);
255 template bool write_matrix<Eigen::VectorXd>(const std::string &, const Eigen::VectorXd &);
256 template bool write_matrix<Eigen::VectorXf>(const std::string &, const Eigen::VectorXf &);
257
258 template bool write_matrix<Eigen::MatrixXd>(const std::string &, const std::string &, const Eigen::MatrixXd &, const bool);
259 template bool write_matrix<Eigen::MatrixXf>(const std::string &, const std::string &, const Eigen::MatrixXf &, const bool);
260 template bool write_matrix<Eigen::VectorXd>(const std::string &, const std::string &, const Eigen::VectorXd &, const bool);
261 template bool write_matrix<Eigen::VectorXf>(const std::string &, const std::string &, const Eigen::VectorXf &, const bool);
262
263 template bool read_matrix_ascii<int>(const std::string &, Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic> &);
264 template bool read_matrix_ascii<double>(const std::string &, Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> &);
265
266 template bool write_matrix_ascii<Eigen::MatrixXd>(const std::string &, const Eigen::MatrixXd &);
267 template bool write_matrix_ascii<Eigen::MatrixXf>(const std::string &, const Eigen::MatrixXf &);
268 template bool write_matrix_ascii<Eigen::VectorXd>(const std::string &, const Eigen::VectorXd &);
269 template bool write_matrix_ascii<Eigen::VectorXf>(const std::string &, const Eigen::VectorXf &);
270
271 template bool read_matrix_binary<int>(const std::string &, Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic> &);
272 template bool read_matrix_binary<double>(const std::string &, Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> &);
273
274 template bool write_matrix_binary<Eigen::MatrixXd>(const std::string &, const Eigen::MatrixXd &);
275 template bool write_matrix_binary<Eigen::MatrixXf>(const std::string &, const Eigen::MatrixXf &);
276 template bool write_matrix_binary<Eigen::VectorXd>(const std::string &, const Eigen::VectorXd &);
277 template bool write_matrix_binary<Eigen::VectorXf>(const std::string &, const Eigen::VectorXf &);
278
279 template bool import_matrix<int>(const std::string &path, const json &import, Eigen::MatrixXi &mat);
280 template bool import_matrix<double>(const std::string &path, const json &import, Eigen::MatrixXd &mat);
281
282} // namespace polyfem::io
template bool import_matrix< double >(const std::string &path, const json &import, Eigen::MatrixXd &mat)
template bool write_matrix< Eigen::VectorXd >(const std::string &, const Eigen::VectorXd &)
template bool read_matrix_binary< int >(const std::string &, Eigen::Matrix< int, Eigen::Dynamic, Eigen::Dynamic > &)
template bool write_matrix< Eigen::VectorXf >(const std::string &, const Eigen::VectorXf &)
bool read_matrix(const std::string &path, Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &mat)
Reads a matrix from a file. Determines the file format based on the path's extension.
Definition MatrixIO.cpp:18
template bool write_matrix_ascii< Eigen::VectorXd >(const std::string &, const Eigen::VectorXd &)
bool read_matrix_binary(const std::string &path, Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &mat)
Definition MatrixIO.cpp:144
template bool import_matrix< int >(const std::string &path, const json &import, Eigen::MatrixXi &mat)
template bool write_matrix_binary< Eigen::MatrixXd >(const std::string &, const Eigen::MatrixXd &)
template bool write_matrix_binary< Eigen::MatrixXf >(const std::string &, const Eigen::MatrixXf &)
bool import_matrix(const std::string &path, const json &import, Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &mat)
Definition MatrixIO.cpp:223
template bool write_matrix_ascii< Eigen::MatrixXf >(const std::string &, const Eigen::MatrixXf &)
template bool write_matrix_binary< Eigen::VectorXd >(const std::string &, const Eigen::VectorXd &)
template bool write_matrix< Eigen::MatrixXf >(const std::string &, const Eigen::MatrixXf &)
bool write_matrix_binary(const std::string &path, const Mat &mat)
Definition MatrixIO.cpp:169
bool read_matrix_ascii(const std::string &path, Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &mat)
Definition MatrixIO.cpp:83
template bool write_matrix< Eigen::MatrixXd >(const std::string &, const Eigen::MatrixXd &)
bool write_matrix_ascii(const std::string &path, const Mat &mat)
Definition MatrixIO.cpp:125
template bool read_matrix_binary< double >(const std::string &, Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > &)
template bool read_matrix< Eigen::MatrixXd >(const std::string &, const std::string &, Eigen::MatrixXd &)
bool write_sparse_matrix_csv(const std::string &path, const Eigen::SparseMatrix< double > &mat)
Definition MatrixIO.cpp:192
template bool read_matrix< int >(const std::string &, Eigen::Matrix< int, Eigen::Dynamic, Eigen::Dynamic > &)
template bool read_matrix< Eigen::MatrixXi >(const std::string &, const std::string &, Eigen::MatrixXi &)
template bool write_matrix_binary< Eigen::VectorXf >(const std::string &, const Eigen::VectorXf &)
template bool read_matrix< double >(const std::string &, Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > &)
template bool write_matrix_ascii< Eigen::VectorXf >(const std::string &, const Eigen::VectorXf &)
template bool read_matrix_ascii< double >(const std::string &, Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > &)
template bool read_matrix_ascii< int >(const std::string &, Eigen::Matrix< int, Eigen::Dynamic, Eigen::Dynamic > &)
template bool write_matrix_ascii< Eigen::MatrixXd >(const std::string &, const Eigen::MatrixXd &)
bool write_matrix(const std::string &path, const Mat &mat)
Writes a matrix to a file. Determines the file format based on the path's extension.
Definition MatrixIO.cpp:42
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:42
nlohmann::json json
Definition Common.hpp:9