reading binary data in MATLAB - c++

I am trying to read binary data using Matlab but when I wrote the code, and the data I have is not right.
The binary file is written:
ofstream outfile2 (outfilename2.c_str() , ofstream::binary);
...
vector<complex<double> > Cxy(2560);
... // data collected from the device.
for(unsigned j = 0; j < 2560; j++)
{
outfile2.write((const char*)&Cxy[j], sizeof(Cxy[j]));
outfile2.flush();
}
when I read the data using:
double fft_len = 256*10;
std::vector<std::complex<double> > vtr(fft_len);
vtr.resize(fft_len);
{
std::ifstream input("data.bin", std::ifstream::binary);
for (int i=0; i< fft_len; ++i)
input.read((char *)&vtr[i],sizeof(vtr[i]));
}
for (size_t i=0; i<vtr.size(); ++i)
std::cout << vtr[i] << endl; // data look like: //(1.31649816e+07,3.97112323e+06)
I used copy & paste data into matlab, then plot it out.
I also want to try different way to read data by using Matlab directly:
filename = 'data.bin';
fid = fopen(filename);
fseek(fid,4*2560,'bof');
y = fread(fid,[2,inf],'long');
x = complex(y(1,:),y(2,:));
plot(abs(x));
figure, plot(abs(x));
but the length of x only 104 but not 2560 as I expected.
So any one can help?
Thank you so much.

Related

Reading Column Specific Data in C++ [duplicate]

I have a text file that has values and I want to put them into a 2D vector.
I can do it with arrays but I don't know how to do it with vectors.
The vector size should be like vector2D[nColumns][nLines] that I don't know in advance. At the most I can have in the text file the number of columns, but not the number of lines.
The number of columns could be different, from one .txt file to another.
.txt example:
189.53 -1.6700 58.550 33.780 58.867
190.13 -3.4700 56.970 42.190 75.546
190.73 -1.3000 62.360 34.640 56.456
191.33 -1.7600 54.770 35.250 65.470
191.93 -8.7500 58.410 33.900 63.505
with arrays I do it like this:
//------ Declares Array for values ------//
const int nCol = countCols; // read from file
float values[nCol][nLin];
// Fill Array with '-1'
for (int c = 0; c < nCol; c++) {
for (int l = 0; l < nLin; l++) {
values[c][l] = -1;
}
}
// reads file to end of *file*, not line
while (!inFile.eof()) {
for (int y = 0; y < nLin; y++) {
for (int i = 0; i < nCol; i++) {
inFile >> values[i][y];
}
i = 0;
}
}
Instead of using
float values[nCol][nLin];
use
std::vector<std::vector<float>> v;
You have to #include<vector> for this.
Now you don't need to worry about size.
Adding elements is as simple as
std::vector<float> f; f.push_back(7.5); v.push_back(f);
Also do not use .eof() on streams, because it doesn't set it until after the end has been reached and so it will attempt to read the end of the file.
while(!inFile.eof())
Should be
while (inFile >> values[i][y]) // returns true as long as it reads in data to values[x][y]
NOTE: Instead of vector, you can also use std::array, which is apparently the best thing after sliced bread.
My suggestion:
const int nCol = countCols; // read from file
std::vector<std::vector<float>> values; // your entire data-set of values
std::vector<float> line(nCol, -1.0); // create one line of nCol size and fill with -1
// reads file to end of *file*, not line
bool done = false;
while (!done)
{
for (int i = 0; !done && i < nCol; i++)
{
done = !(inFile >> line[i]);
}
values.push_back(line);
}
Now your dataset has:
values.size() // number of lines
and can be adressed with array notation also (besides using iterators):
float v = values[i][j];
Note: this code does not take into account the fact that the last line may have less that nCol data values, and so the end of the line vector will contain wrong values at end of file. You may want to add code to clear the end of the line vector when done becomes false, before you push it into values.

Troubles displaying 2d array read from txt file (C++)

I'm having troubles doing a loop for a really basic console game that uses ASCII characters. I want to store the txt file (the map) into a 2d array and then I want to output the 2d array on the console.
You can see 2 loops under here, one for inputting the txt file into a 2d array and the other for outputting the 2d array on the screen.
void Level::load_level() {
Level gameLevel;
ifstream inFile;
gameLevel.map;
inFile.open("level1.txt");
if (inFile.fail()) {
perror("level1.txt");
system("PAUSE");
}
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 74; j++) {
inFile >> map[i][j];
}
}
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 74; j++) {
printf("%c", map[i][j]);
}
printf("\n");
}
inFile.close();
}
So, here is what my txt file looks like:
And here is what my console displays:
It seems like the data in the 2d array isn't store correctly, what should I do in order to keep one loop reading data from the file into a 2d array and another loop displaying the 2d array correctly? I don't know if I made that clear.
Thanks and sorry for my lack of skill(I'm a beginner).

(C++) Is there a way to create different matrices in a loop?

I'm writing a code that reads a text file to create a matrix dinamically. I will then get the information from this matrix to write it in another text file.
I put in a 'for' loop that will create a matrix for each chunk of text that it reads, here it is:
for (cont = 0; cont < nPares; cont++){
ResultFile >> FlowOri;
ResultFile >> FlowDest;
ResultFile >> nPaths;
ResultFile >> largestPath;
double** iPathMatrix = (double**) new double[nPaths];
for (i = 0; i < nPaths; i++) {
iPathMatrix[i] = (double*) new double[largestPath + 2];
}
for (i = 0; i < nPaths; i++) {
for (j = 0; j < largestPath + 2; j++) {
ResultFile >> iPathMatrix[i][j];
}
}
for (i = 0; i < nPaths; i++) {
for (j = 0; j < largestPath + 2; j++) {
cout << iPathMatrix[i][j] << " ";
}
cout << "\n";
}
free(iPathMatrix);
}
'ResultFile' is an ifstream.
That 'cout' near the end was put there to check if it was creating the matrices as intended, which it is.
As you can see, I'm creating the matrix and then freeing the memory at the end of the loop to create it again, since it will have the same name. I can probably figure a way to work with this, but it'd be way easier if I could create a different matrix with each loop, perhaps naming each with the 'FlowOri' and 'FlowDest' variables, if that's possible, and after the loop stops, access them and write in my output file.
Is there a way to do it? How would I reference it afterwards?
As you can see, I'm creating the matrix and then freeing the memory at
the end of the loop to create it again,
No you aren't (at least not correctly). Each new[] must be paired with a delete[], so the correct code is
for (i = 0; i < nPaths; i++) {
delete[] iPathMatrix[i];
}
delete[] iPathMatrix;
Now since you are programming C++, you could avoid this by using vectors.
std::vector<std::vector<double>> iPathMatrix(nPaths, std::vector<double>(largestPath + 2));
Now you don't need to allocate or free anything, but the rest of your code is unchanged.
Now as for your actual question. If I understand it correctly you want to associate a matrix with the value of the flowOri variable. That's easy to do, you should use a std::map.
You haven't said what type flowOri is, I'm going to assume it's a std::string but you should be able to get this to work whatever type it is.
#include <vector>
#include <map>
#include <string>
// lets give a shorter name for the vector type
using MatrixRowType = std::vector<double>;
using MatrixType = std::vector<MatrixRowType>;
// and this is the map type that holds the matrices
using MatrixMapType = std::map<std::string, MatrixType>;
...
MatrixMapType matrixMap;
for (cont = 0; cont < nPares; cont++){
// read stuff
ResultFile >> FlowOri;
...
// read the matrix
MatrixType iPathMatrix(nPaths, MatrixRowType(largestPath + 2));
...
// save the matrix in the map keyed by FlowOri
matrixMap[FlowOri] = iPathMatrix;
}
Now later when you want to retrieve a matirx you just write matrixMap[something] where something is a variable with the name of the matrix you want to retrieve.
Variable names only have a meaning for the programmer and disappear from the executable unless you use a debug mode, so C++ does not allow to create dynamically named variables. Anyway even with languages that allow it, it is a terrible design.
But you can always create an array (or better a vector) of any object type. So if you want to store everything in the loop and process later the whole data, you could use a 3 level vector. With the magic of references, little has to be changed from your code:
std::vector<std::vector<std::vector<double>>> matrixes(nPares);
for (auto& iPathMatrix : matrixes) { // iPathMatrix is a reference inside matrixes
ResultFile >> FlowOri;
ResultFile >> FlowDest;
ResultFile >> nPaths;
ResultFile >> largestPath;
iPathMatrix = std::vector<std::vector<double>>(nPaths);
for (i = 0; i < nPaths; i++) {
iPathMatrix[i] = std::vector<double>(largestPath + 2];
}
for (i = 0; i < nPaths; i++) {
for (j = 0; j < largestPath + 2; j++) {
ResultFile >> iPathMatrix[i][j];
}
}
}
// control:
for (int i = 0; i < nPares; i++) {
for (int j = 0; j < matrixes[i].size(); j++) {
for (int k = 0; k < matrixes[i][j].size(); k++) {
std::cout << matrixes[i][j][k] << " ";
}
std::cout << '\n';
}
std::cout << '\n';
}
matrixes now contain all of your data

Filling multidimensional matrix from file is slow on Windows

I wrote a C++ (Rcpp) function to read and fill a multidimensional matrix from a file containing only numbers. When I run it on Linux it works fine and it is pretty fast. However, the same code is much slower (by a factor of 200) on a Windows machine with the same spec. Anyone can spot the problem?
void read_ed0moins_lut_(const char *filename, float downward_irradiance_table_as_output[NBWL][NTHETAS][NO3][NTAUCLD][NALB]) {
std::ifstream infile;
infile.open(filename);
float tmp;
for (int theta = 0; theta < NTHETAS; theta++) {
for (int ozone = 0; ozone < NO3; ozone++) {
for (int taucl = 0; taucl < NTAUCLD; taucl++) {
for (int albedo = 0; albedo < NALB; albedo++) {
for (int wavelength = 0; wavelength < NBWL; wavelength++) {
infile >> tmp; // This line is very slow on Windows
downward_irradiance_table_as_output[wavelength][theta][ozone][taucl][albedo] = tmp;
}
}
}
}
}
// Close file
infile.close();
}
Here are some ideas:
Build in Release mode (with optimization enabled, -O2 flag)
Enable ifstream buffering:
std::ifstream infile(filename);
char buffer[65536];
infile.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
Arrange your array's dimensions in the order of the loops:
downward_irradiance_table_as_output[NTHETAS][NO3][NTAUCLD][NALB][NBWL]
so that you get row-major-order traversal, which is more cache-friendly.

transforming c++ array to matlab big matrix using file

In my code i'm changing my array (int*) and then I want to compare it into the matlab results.
since my array is big 1200 X 1000 element. this takes forever to load it into matlab
i'm trying to copy the printed output file into matlab command line...
for (int i = 0; i < _roiY1; i++)
{
for (int j = 0; j < newWidth; j++)
{
channel_gr[i*newWidth + j] = clipLevel;
}
}
ofstream myfile;
myfile.open("C:\\Users\\gdarmon\\Desktop\\OpenCVcliptop.txt");
for (int i = 0; i < newHeight ; i++)
{
for (int j = 0; j < newWidth; j++)
{
myfile << channel_gr[i * newWidth + j] << ", ";
}
myfile<<";" <<endl;
}
is there a faster way to create a readable matrix data from c++? into matlab?
The simplest answer is that it's much quicker to transfer the data in binary form, rather than - as suggested in the question - rendering to text and having Matlab parse it back to binary. You can achieve this by using fwrite() at the C/C++ end, and fread() at the Matlab end.
int* my_data = ...;
int my_data_count = ...;
FILE* fid = fopen('my_data_file', 'wb');
fwrite((void*)my_data, sizeof(int), my_data_count, fid);
fclose(fid);
In Matlab:
fid = fopen('my_data_file', 'r');
my_data = fread(fid, inf, '*int32');
fclose(fid);
It's maybe worth noting that you can call C/C++ functions from within Matlab, so depending on what you are doing that may be an easier architecture (look up "mex files").
Don't write the output as text.
Write your matrix into your output file the way Matlab likes to read: big array of binary.
ofstream myfile;
myfile.open("C:\\Users\\gdarmon\\Desktop\\OpenCVcliptop.txt", ofstream::app::binary);
myfile.write((char*) channel_gr, newHeight*newWidth*sizeof(channel_gr[0]));
You may want to play some games on output to get the array ordered column-row rather than row-column because of the way matlab likes to see data. I remember orders of magnitude improvements in performance when writing mex file plug-ins for file readers, but it's been a while since I've done it.