I want to read COMPLEX data present in a txt file into 1D array in MATLAB. I'm novice in MATLAB. Please help me out.
Excuse me for the ambiguous question. Sincere Apologies..
Actually I have a .txt file containing strings that represents complex numbers(Single line in .txt file represents ) for eg:
1+3i
i
-1-i
.
.
.
So on...
I want to read the same in 1 * N Matrix (where N represents number of complex numbers in .txt file) in MATLAB. How I may do so?
I assume you mean you have a text file with two columns, the real and imaginary parts. In which case, you can do this:
>> type cplx.txt % real and imaginary parts are two columns
1 2
3 4
5 6
>> rawData = dlmread('cplx.txt')
rawData =
1 2
3 4
5 6
>> complexData = complex(rawData(:, 1), rawData(:, 2))
complexData =
1.0000 + 2.0000i
3.0000 + 4.0000i
5.0000 + 6.0000i
EDIT
Ok, with that file format, you should be able to use TEXTSCAN.
>> type cplx2.txt
1+3i
1i
2
4-4i
>> fid = fopen('cplx2.txt', 'rt');
>> x = textscan(fid, '%f');
>> fclose(fid);
>> x{1}
ans =
1.000000000000000 + 3.000000000000000i
0.000000000000000 + 1.000000000000000i
2.000000000000000 + 0.000000000000000i
4.000000000000000 - 4.000000000000000i
Note that TEXTSCAN can't handle a line that consists of 'i' on its own. Which is a shame.
Related
I have a huge text file in the following format:
1 2
1 3
1 10
1 11
1 20
1 376
1 665255
2 4
2 126
2 134
2 242
2 247
First column is the x coordinate while second column is the y coordinate.
It indicates that if I had to construct a Matrix
M = zeros(N, N);
M(1, 2) = 1;
M(1, 3) = 1;
.
.
M(2, 247) = 1;
This text file is huge and can't be brought to main memory at once. I must read it line by line. And save it in a sparse matrix.
So I need the following function:
function mat = generate( path )
fid = fopen(path);
tline = fgetl(fid);
% initialize an empty sparse matrix. (I know I assigned Mat(1, 1) = 1)
mat = sparse(1);
while ischar(tline)
tline = fgetl(fid);
if ischar(tline)
C = strsplit(tline);
end
mat(C{1}, C{2}) = 1;
end
fclose(fid);
end
But unfortunately besides the first row it just puts trash in my sparse mat.
Demo:
1 7
1 9
2 4
2 9
If I print the sparse mat I get:
(1,1) 1
(50,52) 1
(49,57) 1
(50,57) 1
Any suggestions ?
Fixing what you have...
Your problem is that C is a cell array of characters, not numbers. You need to convert the strings you read from the file into integer values. Instead of strsplit you can use functions like str2num and str2double. Since tline is a space-delimited character array of integers in this case, str2num is the easiest to use to compute C:
C = str2num(tline);
Then you just index C like an array instead of a cell array:
mat(C(1), C(2)) = 1;
Extra tidbit: If you were wondering how your demo code still worked even though C contained characters, it's because MATLAB has a tendency to automatically convert variables to the correct type for certain operations. In this case, the characters were converted to their double ASCII code equivalents: '1' became 49, '2' became 50, etc. Then it used these as indices into mat.
A simpler alternative...
You don't even have to bother with all that mess above, since you can replace your entire function with a much simpler approach using dlmread and sparse like so:
data = dlmread(filePath);
mat = sparse(data(:, 1), data(:, 2), 1);
clear data; % Save yourself some memory if you don't need it any more
I have four streams of complex numbers in four columns of a text file
I have to read them into a MATLAB matrix in the same format.
I tried the following, but it does not work
fid = fopen('~/<path-to-file>/<fileName>.txt','r');
out = textscan(fid, '(%f,%f) \b\t(%f,%f) \b\t(%f,%f) \b\t(%f,%f) \n','CollectOutput',1);
tapWeights = [out{1} + 1i*out{2} out{3} + 1i*out{4} out{5} + 1i*out{6} out{7} + 1i*out{8}];
fclose(fid);
Note that help options for textscan lists \b\t as the white space delimiter.
The following is the output I get,
>> out
out =
[1x8 double]
>> out{1}
ans =
1 0 NaN NaN NaN NaN NaN NaN
What am I missing here?
Unless I missed something, a simple regexp, str2double, cellfun and reshape does the trick (assuming that the structure of the matrix is known in order to reshape it.
s='(1.00000000,0.00000000) (1.00000000,0.00000000) (-0.00000004,1.00000000) (-0.00000004,-1.00000000) (0.66912299,0.74315202) (0.66912299,0.74315202) (-0.74315202,0.66912293) (0.74315202,-0.66912305) (-0.10454900,0.99452001) (-0.10454900,0.99452001) (-0.99452001,-0.10454904) (0.99452001,0.10454895) (-0.80903500,0.58776098) (-0.80903500,0.58776098) (-0.58776093,-0.80903500) (0.58776104,0.80903500) (-0.97813898,-0.20795099) (-0.97813898,-0.20795099) (0.20795104,-0.97813898) (-0.20795095,0.97813898) (-0.49995700,-0.86605000) (-0.49995700,-0.86605000) (0.86605000,-0.49995697) (-0.86605000,0.49995703) (0.30907401,-0.95103800) (0.30907401,-0.95103800) (0.95103800,0.30907404) (-0.95103800,-0.30907398) (0.91357303,-0.40667400) (0.91357303,-0.40667400) (0.40667397,0.91357303) (-0.40667403,-0.91357303) (0.30893400,0.95108300)';
a=reshape(cellfun(#(x) str2double(x{1})+str2double(x{2})*1j,regexp(s,'[(]([^,]*),([^)]*)[)]','tokens')),3,[])'
I think the solution will be quite simple for somebody with some MATLAB knowhow however I do not know how to do it.
I have a binary file that I am reading with fread and I am reading the first 4 bytes of this file followed by the next 2 bytes.
I basically want this process of reading 4 bytes followed by 2 bytes repeated till the end of the file is reached.
So the number of bytes read is 4,2,4,2,4,2......
I have the following to read the first pair of data and I want this to repeat.
fileID = fopen('MyBinaryFile');
4bytes = fread(fileID, 4);
fseek(fileID, 4, 0);
2bytes = fread(fileID, 2);
Thanks in advance for any help and suggestions
I take it this is a variant of your former question MATLAB reading a mixed data type binary file.
Your goal is to read a binary file containing mixed data type. In your case it contains 2 columns:
1x single value (4 bytes) and 1x int16 value (2 bytes).
There are several ways to read this type of file. They differ in speed because some ways minimize disk access but require more temporary memory, and other way use just the memory needed but require more disk access (= slower).
Ultimately, the 3 ways I'm going to show you produce exactly the same result.
The direct answer to this question is the version #3 below, but I encourage you to have a look at the 2 other options described here, they are both really worth understanding.
For the purpose of the example, I had to create a binary file as you described. This is done this way:
%% // write example file
A = single(linspace(-3,1,11)) ; %// a few "float" (=single) data
B = int16(-5:5) ; %// a few "int16" data
fileID = fopen('testmixeddata.bin','w');
for il=1:11
fwrite(fileID,A(il),'single');
fwrite(fileID,B(il),'int16');
end
fclose(fileID);
This create a 2 column binary file, the columns being:
11 values of type float going from -3 to 1.
11 values of type int16 going from -5 to +5.
For future reference:
>> disp(A)
-3.0000 -2.6000 -2.2000 -1.8000 -1.4000 -1.0000 -0.6000 -0.2000 0.2000 0.6000 1.0000
>> disp(B)
-5 -4 -3 -2 -1 0 1 2 3 4 5
In each of the solution below, the first column will be read in a variable called varSingle, and the second column in a variable called varInt16.
1) Read all data in one go - convert to proper type after
%% // SOLUTION 1 (fastest) : Read all data in one go - convert to proper type after
fileID = fopen('testmixeddata.bin');
R = fread(fileID,'uint8=>uint8') ; %// read all values, most basic data type (unsigned 8 bit integer)
fclose(fileID);
colSize = [4 2] ; %// number of byte for each column [4 byte single, 2 byte int16]
R = reshape( R , sum(colSize) , [] ) ; %// reshape data into a matrix (6 is because 4+2byte=6 byte per column)
temp = R(1:4,:) ; %// extract data for first column into temporary variable (OPTIONAL)
varSingle = typecast( temp(:) , 'single' ) ; %// convert into "single/float"
temp = R(5:end,:) ; %// extract data for second column
varInt16 = typecast( temp(:) , 'int16' ) ; %// convert into "int16"
This is my favourite method. Specially for speed because it minimizes the read/seek operations on disk, and most post calculations are done in memory (much much faster than disk operations).
Note that the temporary variable I used was only for clarity/verbose, you can avoid it altogether if you get your indexing into the raw data right.
The key thing to understand is the use of the typecast function. And the good news is it got even faster since 2014b.
2) Read column by column (using "skipvalue") - 2 pass approach
%% // SOLUTION 2 : Read column by column (using "skipvalue") - 2 pass approach
col1size = 4 ; %// size of data in column 1 (in [byte])
col2size = 2 ; %// size of data in column 2 (in [byte])
fileID = fopen('testmixeddata.bin');
varSingle = fread(fileID,'*single',col2size) ; %// read all "float" values, skipping all "int16"
fseek(fileID,col1size,'bof') ; %// rewind to beginning of column 2 at the top of the file
varInt16 = fread(fileID,'*int16',col1size) ; %// read all "int16" values, skipping all "float"
fclose(fileID);
That works too. It works fine ... but it is going to be slower than method 1 above, because you will have to scan the file twice. It may be a good option if the file is very large and method 1 above fail because of an out of memory error.
3) Read element by element
%% // SOLUTION 3 : Read element by element (slow - not recommended)
fileID = fopen('testmixeddata.bin');
varSingle=[];varInt16=[];
while ~feof(fileID)
try
varSingle(end+1) = fread(fileID, 1, '*single' ) ;
varInt16(end+1) = fread(fileID, 1, '*int16' ) ;
catch
disp('reached End Of File')
end
end
fclose(fileID);
That does work too, and if you were writing C code it would be more than ok. But in Matlab this is not the recommended way to go (your choice ultimately)
As promised, the 3 methods above will give you exactly what we wrote in the file at the beginning:
>> disp(varSingle)
-3.0000 -2.6000 -2.2000 -1.8000 -1.4000 -1.0000 -0.6000 -0.2000 0.2000 0.6000 1.0000
>> disp(varInt16)
-5 -4 -3 -2 -1 0 1 2 3 4 5
fileID = fopen('MyBinaryFile');
kk=1;
while ~feof(fileID)
bytes4(kk) = fread(fileID, 4);
fseek(fileID, 4, 0);
bytes2(kk) = fread(fileID, 2);
kk=kk+1;
end
the while loop condition is ~feof, which stands for End-Of-File. So as long as you haven't reached the end of your file it runs.
I added the kk just so you store everything and not just overwrite them each loop iteration.
If you want to get the data without loops, there are MATLABish ways to that:
%'Sizes'
T = 4; %'Time record size'
D = 2; %'Date record size'
R = T+D; %'Record size'
%'Open file'
f = fopen('MyBinaryFile', 'rb');
if f < 0
error('Could not open file.');
end;
%'Read the entire file at once, and close file'
buf = fread(f, Inf, '*uint8');
fclose(f);
%'Ignore the last unpadded bytes, and reshape by the size of 1 record'
buf = reshape(buf(1:R*fix(numel(buf)/R)), R, []);
%'Pinpoint the data'
time_bytes = buf( 1: T, :);
date_bytes = buf(T+1:T+D, :);
Another question on fprintf
I have a matrix s(n,5) that I want to shorten (just take columns 3,4 and 5) into s1(n,3) and save with a different name.
s1=s(:,3:5);
txtfilename = [Filename '-1.txt'];
% Open a file for writing
fid = fopen(txtfilename, 'w');
% print values in column order
% two values appear on each row of the file
fprintf(fid, '%f %f %f\n', s1);
fclose(fid);
I don't think I understood the way to use fprintf and rewrite my new matrix, because it is sorting the values.
Thanks for your help
The problem is that MATLAB stores data in column-major order, meaning that when you do s1(:), the first three values are the first three values in the first column not the first row. (This is how fprintf will read values out of s1.) For example:
>> M = magic(3)
M =
8 1 6
3 5 7
4 9 2
>> M(:)
ans =
8
3
4
1
5
9
6
7
2
You can simply transpose the matrix to output the way you want:
fprintf(fid, '%f %f %f\n', s1.');
I've got a large text file with some headers and numerical data. I want to ignore the header lines and specifically output the data in columns 2 and 4.
Example data
[headers]
line1
line2
line3
[data]
1 2 3 4
5 6 7 8
9 10 11 12
I've tried using the following code:
FID = fopen('datafile.dat');
data = textscan(FID,'%f',4,'delimiter',' ','headerLines',4);
fclose(FID);
I only get an output of 0x1 cell
Try this:
FID = fopen('datafile.dat');
data = textscan(FID,'%f %f %f %f', 'headerLines', 6);
fclose(FID);
data will be a 1x4 cell array. Each cell will contain a 3x1 array of double values, which are the values in each column of your data.
You can access the 2nd and 4th columns of your data by executing data{2} and data{4}.
With your original code, the main issue is that the data file has 6 header lines but you've specified that there are only 4.
Additionally, though, you'll run into problems with the specification of the number of times to match the formatSpec. Take for instance the following code
data = textscan(FID,'%f',4);
which specifies that you will attempt to match a floating-point value 4 times. Keep in mind that after matching 4 values, textscan will stop. So for the sake of simplicity, let's imagine that your data file only contained the data (i.e. no header lines), then you would get the following results when executing that code, multiple times:
>> FID = fopen('datafile_noheaders.dat');
>> data_line1 = textscan(FID,'%f', 4)
data_line1 =
[4x1 double]
>> data_line1{1}'
ans =
1 2 3 4
>> data_line2 = textscan(FID,'%f', 4)
data_line2 =
[4x1 double]
>> data_line2{1}'
ans =
5 6 7 8
>> data_line3 = textscan(FID,'%f', 4)
data_line3 =
[4x1 double]
>> data_line3{1}'
ans =
9 10 11 12
>> data_line4 = textscan(FID,'%f', 4)
data_line4 =
[0x1 double]
>> fclose(FID);
Notice that textscan picks up where it "left off" each time it is called. In this case, the first three times that textscan is called it returns one row from your data file (in the form of a cell containing a 4x1 column of data). The fourth call returns an empty cell. For the usecase you described, this format is not particularly helpful.
The example given at the top should return data in a format that is much easier to work with for what you are trying to accomplish. In this case it will match four floating point values in each of your rows of data, and will continue with each line of text until it can no longer match this pattern.