Solarian Programmer

My programming ramblings

Transferring data between Matlab and Armadillo

Posted on April 12, 2017 by Paul

In this article, I will show you how to move data between Matlab and Armadillo, specifically how to move matrices between the two. If you need an introduction in how to install Armadillo on your system, check my previous article.

Easiest approach is to transfer data between Matlab and Armadillo using text files. For example, the next Matlab code will generate some data and save it in a text file that can be loaded from Armadillo:

1 A = rand(4,5);
2 
3 % Save the matrix A to "matlab_data.txt" the content of the file is overwritten
4 dlmwrite('matlab_data.txt', A, 'delimiter', '\t', 'precision', 16);

Reading the matrix from matlab_data.txt in Armadillo can be done with:

1 arma::Mat<double> A;
2 A.load("matlab_data.txt");

The above procedure works well if you need to transfer one or two matrices from Matlab to Armadillo, but it doesn’t scale. Imagine that you need to move many small matrices of various dimensions. Using a separate text file for every one of them is not only tedious and error prone, it is also a relatively slow process.

The .load() function from Armadillo also works with C++ streams, e.g.:

1 std::ifstream file("matlab_data.txt")
2 
3 arma::Mat<double> A;
4 A.load(file);

This last approach can be generalized for the case when you need to transfer more than one matrix from Matlab. The idea is to use some kind of delimiters between two records, read the content of the first record (matrix) in a C++ stringstream after which you can use the .load() function from Armadillo to get the data as a matrix in memory.

Here is a simple Matlab function that will let you save a matrix in a text file using start and end text delimiters:

1 function append_value(file, name, value)
2     dlmwrite(file, ['Start_' name], 'delimiter', '', '-append');
3     dlmwrite(file, value, 'delimiter', '\t', 'precision', 16, '-append');
4     dlmwrite(file, ['End_' name], 'delimiter', '', '-append');
5 end

An example of using the above function to save a few matrices in a text file:

1 A = rand(4,5);
2 % Save A to "matlab_data_v2.txt" between the delimiters "Start_A" ... "End_A"
3 append_value('matlab_data_v2.txt', 'A', A);
4 
5 B = rand(3,3);
6 append_value('matlab_data_v2.txt', 'B', B);

This is the content of matlab_data_v2.txt on my machine (obviously this will be different for every run of the Matlab code):

 1 Start_A
 2 0.6557406991565868	0.6787351548577735	0.6554778901775566	0.27692298496089	0.6948286229758171
 3 0.03571167857418955	0.7577401305783335	0.1711866878115618	0.04617139063115394	0.3170994800608605
 4 0.8491293058687771	0.7431324681249162	0.7060460880196088	0.09713178123584754	0.9502220488383549
 5 0.9339932477575506	0.3922270195341682	0.03183284637742068	0.8234578283272926	0.03444608050290876
 6 End_A
 7 Start_B
 8 0.4387443596563982	0.7951999011370632	0.4455862007108995
 9 0.3815584570930084	0.1868726045543786	0.6463130101112646
10 0.7655167881490024	0.4897643957882311	0.7093648308580726
11 End_B

The C++ code can simply read the data file line by line and accumulate the data between the delimiters in a strinstream, e.g.:

 1 #include <iostream>
 2 #include <fstream>
 3 #include <string>
 4 #include <armadillo>
 5 
 6 // Extract the data as an Armadillo matrix Mat of type T, if there is no data the matrix will be empty
 7 template<typename T>
 8 arma::Mat<T> load_mat(std::ifstream &file, const std::string &keyword) {
 9 	std::string line;
10 	std::stringstream ss;
11 	bool process_data = false;
12 	bool has_data = false;
13 	while (std::getline(file, line)) {
14 		if (line.find(keyword) != std::string::npos) {
15 			process_data = !process_data;
16 			if (process_data == false) break;
17 			continue;
18 		}
19 		if (process_data) {
20 			ss << line << '\n';
21 			has_data = true;
22 		}
23 	}
24 
25 	arma::Mat<T> val;
26 	if (has_data) {
27 		val.load(ss);
28 	}
29 	return val;
30 }
31 
32 int main() {
33 	std::ifstream file("matlab_data_v2.txt");
34 
35 	arma::Mat<double> A = load_mat<double>(file, "A");
36 	arma::Mat<double> B = load_mat<double>(file, "B");
37 
38 	std::cout << A << "\n\n";
39 	std::cout << B << "\n";
40 
41 	file.close();
42 	return 0;
43 }

A more general approach is to use binary files to transfer data between Matlab and Armadillo, this is left as an exercise for the reader. Hint: read about Matlab’s fread, fwrite functions and their C++ counterparts.

If you are interested to learn more about the new C++11/C++14 syntax, I would recommend reading The C++ Programming Language by Bjarne Stroustrup.

or, Professional C++ by M. Gregoire, N. A. Solter, S. J. Kleper:


Show Comments