Issues printing a character string in Matlab - matlab

I'm new to MATLAB and I'm having problems printing a character array to a file. I only get the first character printed out. I read lines from a file and build an matrix of matrices. One matrix is an array of character vectors. Here's how I read the data
tline = fgetl(iin);
t_current = tline(9:34);
...
data.t = [data.t; t_current];
Then later I do this:
npts = length(data.t);
fid1 = fopen(fname, 'w');
fprintf(fid1, 'Day Rank\n');
fprintf(fid1, '------- -------\n');
for k = 1:npts
time_str = data.t(k);
fprintf(fid1, '%s %f3\n',time_str, data.rank(k));
end
fclose(fid1);
data.t is <10082,26 char> and looks something like this:
val =
2015-07-16T03:28:36.410305
2015-07-16T03:29:00.000000
...
All I get with the fprintf is a '2'. I tried to use convertCharsToStrings but that failed with an error message: Undefined function 'convertCharsToStrings' for input arguments of type
'char'.
This must be something simple I'm missing.
Thanks,
-Mike

Since "data.t is <10082,26 char>", try this:
...
for k = 1:npts
time_str = data.t(k, :);
...
If you do not use the , :, Matlab will use linear indexing for the matrix as opposed to subscripts.

It turns out I needed to use a different format for getting the time string:
time_str=data.t(k,1:end)

Related

Reading dat file into matrix in matlab with different different amounts of data each row

I'm trying to write a matlab function that will load a data into a matrix. The problem is the data has one more value each row. So I can't use load unfortunately, so I'm trying to use fgetl.
The data looks like:
143234
454323 354654
543223 343223 325465
etc
What I did is create a matrix of zeros, the dimensions being the height and the longest string of data. To put the data into the matrix I used fgetl to read each row and then used textscan to split the data up at whitespace. Then I used str2num (I think this is where the error is) to convert the string to a number.
First heres my code:
%READTRI Opens the triangle dat file and turns it into a matrix
fid = fopen('triangledata.dat');
%create matrix of zeros for the data to be retrieved
trimat = zeros(15,15);
%Check to see if the file loaded properly
if fid == -1
disp('File load error')
else
%if it does, continue
%read each line of data into a
while feof(fid) == 0
%run through line by line
aline = fgetl(fid);
%split aline into parts by whitespace
splitstr = textscan(aline,'%s','delimiter',' ');
%This determines what row of the matrix the for loop writes to
rowCount = 1;
%run through cell array to get the numbers out and write them to
%the matrix
for i = 1:length(splitstr)
%convert to number
num = str2num(splitstr{i});
%write num to matrix
trimat(rowCount, i) = num;
end
%iterate rowCount
rowCount = rowCount + 1;
end
%close the file
closeresult = fclose(fid);
%check for errors
if closeresult == 0
disp('File close successful')
else
disp('File close not successful')
end
end
end
The error I'm getting is:
Error using str2num (line 33)
Requires string or character array input.
Error in readTri (line 32)
num = str2num(splitstr{i});
What bothers me is that when I try, in the interactive console the same thing that goes on in the loop i.e. import aline, split it into a cell array using textscan, then use num2str to convert it to a integer. Everything works. So either the way I'm using num2str is wrong or the for loop is doing something funky.
I was just hoping for ideas, there is a LOT of data so adding zeros to make load work is not possible.
thanks for reading!
You can use dlmread instead of load or fgetl
It automatically returns a matrix with zeros whenever the line is not as long as the longest.
Just do
matrix = dlmread('triangledata.dat');
Why not using textscan?
fid = fopen('test.txt','r');
C = textscan(fid, '%f%f%f');
fclose(fid);
res = cell2mat(C)
The result is
res =
143234 NaN NaN
454323 354654 NaN
543223 343223 325465
where missing values are NaN.

matlab reading variables with varying lengths into the workspace

This is a follow up question to
Reading parameters from a text file into the workspace
I am wondering, how would I read the following:
% ---------------------- details --------------------------
%---------------------------------------------------------------
% location:
lat = 54.35
lon = -2.9833
%
Eitan T suggested using:
fid = fopen(filename);
C = textscan(fid, '%[^= ]%*[= ]%f', 'CommentStyle', '%')
fclose(fid);
to obtain the information from the file and then
lat = C{2}(strcmp(C{1}, 'lat'));
lon = C{2}(strcmp(C{1}, 'lon'));
to obtain the relevant parameters. How could I alter this to read the following:
% ---------------------- details --------------------------
%---------------------------------------------------------------
% location:
lat = 54.35
lon = -2.9833
heights = 0, 2, 4, 7, 10, 13, 16, 19, 22, 25, 30, 35
Volume = 6197333, 5630000, 4958800, 4419400, 3880000, 3340600,
3146800, 2780200, 2413600, 2177000, 1696000, 811000
%
where the variable should contain all of the data points following the equal sign (up until the start of the next variable, Volume in this case)?
Thanks for your help
Here's one method, which uses some filthy string hacking and eval to get the result. This works on your example, but I wouldn't really recommend it:
fid = fopen('data.txt');
contents = textscan(fid, '%s', 'CommentStyle', '%', 'Delimiter', '\n');
contents = contents{1};
for ii = 1:length(contents)
line = contents{ii};
eval( [strrep(line, '=', '=['), '];'] ) # convert to valid Matlab syntax
end
A better method would be to read each of the lines using textscan
for ii = 1:length(contents)
idx = strfind(contents{ii}, ' = ');
vars{ii} = contents{ii}(1:idx-1);
vals(ii) = textscan(contents{ii}(idx+3:end), '%f', 'Delimiter', ',');
end
Now the variables vars and vals have the names of your variables, and their values. To extract the values you could do something like
ix = strmatch('lat', vars, 'exact');
lat = vals{ix};
ix = strmatch('lon', vars, 'exact');
lon = vals{ix};
ix = strmatch('heights', vars, 'exact');
heights = vals{ix};
ix = strmatch('Volume', vars, 'exact');
volume = vals{ix};
This can be accomplished using a 2-step approach:
Read the leading string (first element), equals sign (ignored), and the rest of the line as a string (second element)
Convert these strings-of-the-rest-of-the-lines to floats (second element)
There is however a slight drawback here; your lines seem to follow two formats; one is the one described in step 1), the other is a continuation of the previous line, which contains numbers.
Because of this, an extra step is required:
Read the leading string (first element), equals sign (ignored), and the rest of the line as a string (second element)
This will fail when the "other format" is encountered. Detect this, correct this, and continue
Convert these strings-of-the-rest-of-the-lines to floats (second element)
I think this will do the trick:
fid = fopen('data.txt');
C = [];
try
while ~feof(fid)
% Read next set of data, assuming the "first format"
C_new = textscan(fid, '%[^= ]%*[= ]%s', 'CommentStyle', '%', 'Delimiter', '');
C = [C; C_new]; %#ok
% When we have non-trivial data, check for the "second format"
if ~all(cellfun('isempty', C_new))
% Second format detected!
if ~feof(fid)
% get the line manually
D = fgetl(fid);
% Insert new data from fgetl
C{2}(end) = {[C{2}{end} C{1}{end} D]};
% Correct the cell
C{1}(end) = [];
end
else
% empty means we've reached the end
C = C(1:end-1,:);
end
end
fclose(fid);
catch ME
% Just to make sure to not have any file handles lingering about
fclose(fid);
throw(ME);
end
% convert second elements to floats
C{2} = cellfun(#str2num, C{2}, 'UniformOutput', false);
If you can get rid of the multi-line Volume line, what you have written is valid matlab. So, just invoke the parameter file as a matlab script using the run command.
run(scriptName)
Your only other alternative, as others have shown, is to write what will end up looking like a bastardized Matlab parser. There are definitely better ways to spend your time than doing that!

Reading a text file and plotting it in 3D

I want to read in a text file that contains some strings but mostly numbers. I want to be able to ignore the strings and only look at the numbers. I want to plot those values on a 3D plane. The data looks like this:
Tech4:<152.266724,173.189377,27.995975>
<117.880638,156.116531,27.999983>
<129.849899,59.195660,27.999983>
<249.321121,60.605404,27.999983>
<224.120361,139.072739,28.000668>
<171.188950,143.490921,56.933430>
<171.188950,143.490921,83.548088>
<171.188950,143.490921,27.999985>
I believe to read in a file is just:
File = textread('testFile.txt');
How can I only look at those values and then plot it.
Thanks!
fid = fopen([pathname,filename]);
tline = fgetl(fid);
CX = [];
CY = [];
CZ = [];
while ischar(tline)
% skip < and >
tline = substr(tline, 1, length(tline)-2)
% extract numbers
temp = textscan(tline,'%n%n%n', 'delimiter',',');
CX(end+1,:) = [temp(1)];
CY(end+1,:) = [temp(2)];
CZ(end+1,:) = [temp(3)];
tline = fgetl(fid);
end
fclose(fid);
and then plot it using
plot3(CX, CY, CZ)
function call.
Add the check for "Tech4:" at the beginning however...
I think you can also directly use textscan in a one-liner:
fid = fopen('testFile.txt');
data = textscan(fid,'%*s%f,%f,%f');
fclose(fid);
this loads the values from all rows with the specified format into the variable data.
no matlab around to test it out though.
fscanf is an option to, the same kind of parameters as textscan.
EDIT: typo, you want to detect floats (%f) of course, and not integers (%d)
EDIT2: got matlab and tested it out, this works here for your sample input ^^
fid = fopen('testFile.txt');
data = textscan(fid,'%*s%f%f%f','Delimiter',',<>')
fclose(fid);

Matlab -- Conversion to double from cell is not possible

Can someone tell me why I am receiving this error --
??? The following error occurred converting from cell to
double:
Error using ==> double
Conversion to double from cell is not possible.
Error in ==> test at 18
CX(end+1,:) = temp(1);
Here is the code:
file = fopen('C:\Program Files (x86)\Notepad++\testFile.txt'); % open text file
tline = fgetl(file); % read line by line and remove new line characters
%declare empty arrays
CX = [];
CY = [];
CZ = [];
while ischar(tline) % true if tline is a character array
temp = textscan(fid,'%*s%f%f%f','Delimiter',',<>'); % loads the values from all rows with the specified format into the variable data
CX(end+1,:) = temp(1);
CY(end+1,:) = temp(2);
CZ(end+1,:) = temp(3);
tline = fgetl(file);
end
fclose(file); % close the file
plot3(CX, CY, CZ) % plot the data and label the axises
xlabel('x')
ylabel('y')
zlabel('z')
grid on
axis square
Quick guess: does using curly braces help?
CX(end+1,:) = temp{1}
Use cell2mat to convert from a cell array (what textscan returns) to a numeric array, which you can use (like append to, in your case) with other numeric arrays.
I would also recommend using vertcat rather than the approach you've taken to concatenating:
CX = vertcat(CX, cell2mat(temp(1)));
Or, you could read all 3 values in to a row and concatentate into a N-by-3 matrix instead... lots of options.

Matlab how to ignore the first index=1

The code below gives me error = Subscript indices must either be real positive integers or logicals.Because the first index using FIND function is i=1, the i-1 gives negative value. How to ignore when i==1 without using the LOOP function
fid=fopen('data.txt');
A=textscan(fid,'%f%f%f%f');
fclose(fid);
in = cell2mat(A);
i = find(in(1:end,2)>20 & in(1:end,2) <50);
out=in;
s(i)=sqrt((out(i,3)-out(i-1,3))*(out(i,3)-out(i-1,3))+(out(i,4)-out(i-1,4))*(out(i,4)-out(i-1,4)));
fid = fopen('newData.txt','wt');
format short g;
fprintf(fid,'%g\t%g\t%g\t%g\n',out',s'); %'# Write the data to the file
fclose(fid);
you can try something like this:
i = find(in(1:end,2)>20 & in(1:end,2) <50);
i = i(find( i > 1));
By the way, be careful of using i as a regular variable because you're overriding the default value of:
i = sqrt(-1)