Reading text file to matrix in Matlab, with unknown line length - matlab

I have a text file, that is formatted somewhat like this:
1 2 3 4 5 6
7 8 9
0 11 2 32 45 6 6
1 2
I want to read each row and plot a line for each row.The x axes is [1:row.length],the y axes is each row.

fid = fopen('dat.txt');
line = fgetl(fid);
% if you want everything on the same axis, set it up here
axis([0,20,-10,10])
hold all
while ischar(line)
yy = str2num(line);
xx = 1:length(yy);
plot(xx,yy)
line = fgetl(fid);
end
hold off
fclose(fid);
Note that feof() is not so good with fgetl(), see here.

The simplest way to do it is to test for specific characters. Check for the new line character to determine if you're at the end of the current row and the end of file function to see if you're at the end of the file.
Take a look at: http://www.mathworks.com/help/matlab/ref/feof.html

Related

approach to save and load a 3D matrix

I need to save a 3D matrix in a text file that will be loaded in Matlab (which I don't master). My first idea was to do it with a .csv like this, (consider a 3x3x3 matrix):
row 1: v[0][0][0],v[0][0][1] ,v[0][0][2]
row 2: v[0][1][0],v[0][1][1] ,v[0][1][2]
row 3: v[0][2][0],v[0][2][1] ,v[0][2][2]
row4: v[1][0][0],v[1][0][1] ,v[1][0][2]
...
Like this, I must inform the user separately about the number of x an y dimensions. Not too clean, but not a big drama.
My question is, how could I load and plot in Matlab a dataset like this? Values are 1/0.
Is there any smarter way of doing this. I am exporting from Java.
Thanks!
I can't think of a way that you can omit storing the dimensions of the matrix (at least two of them should be mentioned). But when it comes to storing values in a file, I suggest that you do not bother to even write them in tabular format. All you need to know about MATLAB is the order of elements in a matrix. Take a look at this example:
%% create a 3d matrix
% a = 1+randi(5);
% b = 1+randi(5);
% c = 1+randi(5);
a = 2; b = 3; c = 4;
M = reshape(1:a*b*c, a, b, c)
This is how the matrix looks like:
M(:,:,1) =
1 3 5
2 4 6
M(:,:,2) =
7 9 11
8 10 12
M(:,:,3) =
13 15 17
14 16 18
M(:,:,4) =
19 21 23
20 22 24
Now let's write it in a text file:
%% writing matrix in the text file,
% translate it to your target language
fid = fopen('matrix.txt', 'w');
fprintf(fid, '%d,%d,%d\n', a, b, c);
for k=1:c
for j=1:b
for i=1:a
fprintf(fid, '%-.8g\n', M(i, j, k));
end
end
end
fclose(fid);
This is the contents of the file:
2,3,4
1
2
3
4
...
21
22
23
24
Now, to read the file:
%% read the file back in MATLAB
fid = fopen('matrix.txt', 'r');
sz = str2num(fscanf(fid, '%s\n', 1)); % read dimensions
M2 = reshape(fscanf(fid, '%f\n', inf), sz); % read values
fclose(fid);
%% test the imported matrix
disp(sz)
if all(all(all(M == M2)))
disp('OK')
else
disp('Test failed.')
end

MATLAB Best way to extract data from text files and convert rows to vectors?

I'm having a lot of issues trying to extract the data from the attached text file ('scratch.txt'). My goal is to convert every row in the text file to a 1xn vector where n is the number of variables in the text file row. I also need to make sure that every value extracted into these vectors is an 8 byte floating point.
This is what I have so far but I don't know how to convert what I currently have as the output into a matrix:
fid = fopen('scratch.txt');
tline = fgetl(fid);
while ischar(tline)
disp(tline)
tline = fgetl(fid);
end
Currently this is what I get as the output:
4 3
1 10
2 30
3 20
4 0
1 4 1
2 1 3
3 3 2
1.e7 1.339 .5
4
1 5 3 4
1
7 5.0
Use str2num to convert tline into a numeric row vector.
Since you have varying number of elements in each row, you cannot convert your data into a matrix: matrix (by definition) has the same number of elements in each row.
What you can do, is store the row in a cell array.
res = {};
fid = fopen('scratch.txt');
tline = fgetl(fid);
while ischar(tline)
res{end+1} = str2num(tline);
tline = fgetl(fid);
end

Matlab random sampling

I am trying to exercise myself in Matlab. I am trying to select randomly two lines from a file named data.dat.
My data.dat file looks like this:
12 4 6.1 7
14 4 8.4 62
7 56.1 75 98
9.7 54 12 35
2 4 8 7.8
To select 2 lines randomly from the data.dat here is how I am proceeding:
close all;
clear all;
%----------------------%
% Choose random lines
%----------------------%
M = load('data.dat');
N=2; %number_of_lines
file_number = 2; %save each two lines in new file: selection_1, selection_2
Now I am saving the two selected lines in new files sequentially.
for k = 1:file_number
i = randi(length(M),N);
B=M(i,:)
filename=['samples_',int2str(k),'_mc.dat']
save (filename, 'B', '-ascii')
clear B;
end
I don't know why but I have more than 2 lines in each new files. Could you please explain me where did I made a mistake.
I think you are making a mistaking when you generate the random numbers, as indicated by GameOfThrows.
i = randi(length(M),N); % gives you a matrix NxN of numbers
i = randi(length(M),[N,1]); % gives you a column of N numbers

How to read a line from a text file for input in matlab

I am generating some 3D points and saving in a text file. Next I want to take those points as input for another code. here is my text file:
*******OUTPUT 1 for p=0.01 5x5x5********
1 1 4 ;3 2 4 ;
*******OUTPUT 2 for p=0.01 5x5x5********
2 1 3 ;1 4 4 ;
*******OUTPUT 3 for p=0.01 5x5x5********
2 1 3 ;1 4 4 ;
For output 1 p=0.01 (1,1,4) and (3,2,4) are my points. I want to match the output number and p value and then grab those points(for that output number and p value) as my input of another code.I want to do something like below:
if(*******OUTPUT %d for p=%0.2f 5x5x5*******)
points = will take the points after that line
end
But do not know how to do that.Any help will be appreciated.
This code will extract the output value, p value and the points into three separate arrays.
output=[];
p=[];
points=[];
% open file
fid = fopen('test.txt');
% read the file line by line
tline = fgetl(fid);
% if the line is not empty
while ischar(tline)
% if it is the 'output' line
if strcmp(tline(1:13),'*******OUTPUT')
% extract the output number from the string
output = [output, sscanf(tline,'%*s %i %*s%*f %*s')];
% extract p value
p = [p, sscanf(tline,'%*s %*i%*8c%f %*s')];
% if it is the 'points' line
else
% extract points, sscanf output is transposed
points = [points; sscanf(tline,'%i %i %i%*2c%i %i %i %*s')'];
end
tline = fgetl(fid);
end
% close file
fclose(fid);
Once you have the values extracted, you can do whatever you need to do with it.

Using Matlab to make modification to a text file

Essentially I am writing a Matlab file to change the 2nd, 3rd and 4th numbers in the line below "STR" and above "CON" in the text file (which is given below and is called '0.dat'). Currently, my Matlab code makes no changes to the text file.
Text File
pri
3
len 0.03
vic 5 5
MAT
1 147E9 0.3 0 4.9E9 8.5E9
LAY
1 0.000125 1 45
2 0.000125 1 0
3 0.000125 1 -45
4 0.000125 1 90
5 0.000125 1 45
WAL
1 1 2 3 4 5
PLATE
1 0.005 1 1
STR
1 32217.442335442 3010.34241024889 2689.48842888812
CON
1 2 1 2 3 1 3 4 1 4 5 1 5 6 1 6 7 1
ATT
1 901 7 901
LON
34
POI
123456
1 7
X 0.015
123456
2 6
X 0.00381966011250105 0.026180339887499
123456
3 5
X 0.000857864376269049 0.0291421356237309
123456
4
X 0
PLO
2 3
CRO
0
RES
INMOD=1
END
Matlab code:
impafp = importdata('0.dat','\t');
afp = impafp.textdata;
fileID = fopen('0.dat','r+');
for i = 1:length(afp)
if (strncmpi(afp{i},'con',3))
newNx = 100;
newNxy = 50;
newNy = 500;
myformat = '%0.6f %0.9f %0.9f %0.9f\n';
newData = [1 newNx newNxy newNy];
afp{i-1} = fprintf(fileID, myformat, newData);
fclose(fileID);
end
end
From the help for importdata:
For ASCII files and spreadsheets, importdata expects to find numeric
data in a rectangular form (that is, like a matrix). Text headers can
appear above or to the left of numeric data. To import ASCII files
with numeric characters anywhere else, including columns of character
data or formatted dates or times, use TEXTSCAN instead of import data.
Indeed, if you print out the value of afp, you'll see that it just contains the first line. You were also not performing any operation that was writing to a file. And you were not closing the file ID if the if state wasn't triggered.
Here is one way to do this with textscan (which is probably faster too):
% Read in data as strings using textscan
fid = fopen('0.dat','r');
afp = textscan(fid,'%s','Delimiter','');
fclose(fid);
isSTR = strncmpi(afp{:},'str',3); % True for all lines starting with STR
isCON = strncmpi(afp{:},'con',3); % True for all lines starting with CON
% Find indices to replace - create logical indices
% True if line before is STR and line after is CON
% Offset isSTR and isCON by 2 elements in opposite directions to align
% Use & to perform vectorized AND
% Pad with FALSE on either side to make output the same length as afp{1}{:}
datIDX = [false;(isSTR(1:end-2)&isCON(3:end));false];
% Overwrite data using sprintf
myformat = '%0.6f %0.9f %0.9f %0.9f';
newNx = 100;
newNxy = 50;
newNy = 500;
newData = [1 newNx newNxy newNy];
afp{1}{datIDX} = sprintf(myformat, newData); % Set only elements that pass test
% Overwrite old file using fprintf (or change filename to new one)
fid = fopen('0.dat','w');
fprintf(fid,'%s\r\n',afp{1}{1:end-1});
fprintf(fid,'%s',afp{1}{end}); % Avoid blank line at end
fclose(fid);
If you're unfamiliar with logical indexing, you might read this blog post and this.
I would recommend just reading the entire file in, finding which lines contain your "keywords", modifying specific lines, and then writing it back out to a file, which can have the same name or a different one.
file = fileread('file.dat');
parts = regexp(file,'\n','split');
startIndex = find(~cellfun('isempty',regexp(parts,'STR')));
endIndex = find(~cellfun('isempty',regexp(parts,'CON')));
ind2Change = startIndex+1:endIndex-1;
tempCell{1} = sprintf('%0.6f %0.9f %0.9f %0.9f',[1,100,50,500]);
parts(ind2Change) = deal(tempCell);
out = sprintf('%s\n',parts{:});
out = out(1:end-1);
fh = fopen('file2.dat','w');
fwrite(fh,out);
fclose(fh);