Created
April 7, 2021 21:13
-
-
Save jwpeterson/6b812271ee7dc31a24b1a60b8fe3edde to your computer and use it in GitHub Desktop.
Convert the output of PetscMatrix::print_matlab() to a format which can be used in Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// C++ header files | |
#include <string> | |
#include <iostream> | |
#include <fstream> | |
#include <sstream> | |
#include <iomanip> | |
#include <cstdlib> // std::exit | |
#include <getopt.h> // getopt_long() | |
void usage(const char * progname) | |
{ | |
std::cerr << "Usage: " << progname << " -i <filename>" << std::endl; | |
} | |
int main(int argc, char** argv) | |
{ | |
// options descriptor - this associates "long" and "short" command line options. | |
static struct option longopts[] = | |
{ | |
{"input-file", required_argument, NULL, 'i'}, | |
{"help", no_argument, NULL, 'h'}, | |
{ NULL, 0, NULL, 0 } | |
}; | |
std::string infile_name; | |
// Parse command line options using getopt_long() | |
int ch = -1; | |
while ((ch = getopt_long(argc, argv, "hi:", longopts, NULL)) != -1) | |
{ | |
switch (ch) | |
{ | |
case 'i': | |
{ | |
infile_name = optarg; | |
break; | |
} | |
case 'h': | |
{ | |
usage(argv[0]); | |
std::exit(1); | |
} | |
default: | |
// We could error here, print a usage command, or just ignore unrecognized arguments... | |
std::cerr << "Unrecognized argument: " << optarg << std::endl; | |
usage(argv[0]); | |
} | |
} // end while | |
// Check for valid input filename | |
if (infile_name.empty()) | |
{ | |
usage(argv[0]); | |
std::exit(1); | |
} | |
// Open example file for reading | |
std::ifstream infile(infile_name); | |
// File we will write the results to. By default it is the same | |
// basename as the input file but with a .py extension. | |
std::string outfile_name = infile_name; | |
outfile_name.erase(outfile_name.find_last_of(".")); | |
outfile_name += ".py"; | |
// Don't try to overwrite the input | |
if (outfile_name == infile_name) | |
{ | |
std::cerr << "Error: input and output filenames cannot match." << std::endl; | |
std::exit(1); | |
} | |
std::ofstream outfile(outfile_name); | |
outfile << std::scientific << std::setprecision(16); | |
// The number of rows and cols in the input matrix | |
unsigned int nrows = 0; | |
unsigned int ncols = 0; | |
// Parse file line by line | |
std::string line; | |
// Used for formatted parsing of a single line | |
std::stringstream line_stream; | |
// Used for reading strings line by line | |
std::string dummy; | |
unsigned int row = 0; | |
unsigned int col = 0; | |
double val = 0.; | |
// Write "header" to Python file | |
outfile << "import matplotlib.pyplot as plt" << std::endl; | |
outfile << "from scipy.sparse import coo_matrix" << std::endl; | |
outfile << "array = [" << std::endl; | |
while (true) | |
{ | |
// Try to read something. This may set EOF! | |
std::getline(infile, line); | |
if (infile) | |
{ | |
// Debugging: print line to file | |
// std::cout << line << std::endl; | |
// 1.) Process line which tells the matrix size and looks like this | |
// % Size = 30 30 | |
if (line.find("Size") != std::string::npos) | |
{ | |
// Create a stream object out of the current line | |
line_stream.clear(); | |
line_stream.str(line); | |
line_stream >> dummy >> dummy >> dummy >> nrows >> ncols; | |
} | |
// 2.) Process a line that starts with a number. It should have three entries | |
if (line.find_first_of("0123456789") == 0) | |
{ | |
line_stream.clear(); | |
line_stream.str(line); | |
line_stream >> row >> col >> val; | |
// Check that it worked | |
if (row == 0 || col == 0) | |
{ | |
std::cerr << "Error reading row and/or column indices" << std::endl; | |
std::exit(1); | |
} | |
// Write zero-based (!) indices to output file separated by commas | |
outfile << row-1 << "," << col-1 << "," << val << "," << std::endl; | |
} | |
// Go to next line | |
continue; | |
} | |
if (infile.eof()) | |
break; | |
// If we made it here, there was an error | |
std::cerr << "Error while parsing file (be sure file exists)." << std::endl; | |
std::exit(1); | |
} | |
// Close array | |
outfile << "]" << std::endl; | |
// Check that we read a valid number of rows and columns | |
if (nrows == 0 || ncols == 0) | |
{ | |
std::cerr << "Error reading number of rows and cols in matrix" << std::endl; | |
std::exit(1); | |
} | |
// Write "footer" to Python file | |
outfile << "rows = array[0::3]" << std::endl; | |
outfile << "cols = array[1::3]" << std::endl; | |
outfile << "data = array[2::3]" << std::endl; | |
outfile << "mat = coo_matrix((data, (rows, cols)), shape=(" << nrows << "," << ncols << "))" << std::endl; | |
outfile << "fig = plt.figure()" << std::endl; | |
outfile << "ax1 = fig.add_subplot(111)" << std::endl; | |
outfile << "ax1.spy(mat, markersize=1)" << std::endl; // non-zero values with |Z|>precision will be plotted, default is precision=0.0 | |
outfile << "plt.savefig('spy_nonzero.pdf', format='pdf')" << std::endl; | |
outfile << "ax1.spy(mat, precision='present', markersize=1)" << std::endl; // plot all "present" values (even zeros) | |
outfile << "plt.savefig('spy_present.pdf', format='pdf')" << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment