plot some data such as pairs in matlab - matlab

I want to plot some data, but I can't.
It is assumed that we have 820 rows in 2 columns, representing the x and y coordinates.
My code is as follows:
load('MyMatFileName.mat');
[m , n]=size(inputs);
s = zeros(m,2);
for m=1:820
if inputs(m,end-1)<2 & inputs(m,end)<2
x = inputs(m,end-1)
y = inputs(m,end)
plot(x,y,'r','LineWidth',1.5)
hold on
end
end

I've edited your code and added comments to explain the changes you could make, but see below I've also re-written your code to be more like how it should be done:
load('MyMatFileName.mat'); % It's assumed "inputs" is in here
% You don't use the second size output, so use a tilde ~
[m, ~] = size(inputs);
%s = zeros(m,2); % You never use s...
% Use a different variable for the loop, as m is already the size variable
% I've assumed you wanted ii=1:m rather than m=1:820
figure
hold on % Use hold on and hold off around all of your plotting
for ii=1:m
if inputs(m,end-1)<2 && inputs(m,end)<2 % Use double ampersand for individual comparison
x = inputs(m,end-1)
y = inputs(m,end)
% Include the dot . to specify you want a point, not a line!
plot(x, y, 'r.','LineWidth',1.5)
end
end
hold off
A better way of doing this whole operation in Matlab would be to vectorise your code:
load('MyMatFileName.mat');
[m, ~] = size(inputs);
x = inputs(inputs(:,end-1) < 2 & inputs(:,end) < 2, end-1);
y = inputs(inputs(:,end-1) < 2 & inputs(:,end) < 2, end);
plot(x, y, 'r.', 'linewidth', 1.5);
Note that this will plot points, if you want to plot the line, use
plot(x, y, 'r', 'linewidth', 1.5); % or plot(x, y, 'r-', 'linewidth', 1.5);

Related

How to plot multiple lines in one plot and save them

Question 1 SOLVED
I am working on the following simulation:
x = [8 9 7 6 5];`
if isvector(x)
for i=1:length(x)
% simulation gives me a matrix y,t,z, (c by 5)
% where size(y,1)=size(z,1)=size(t,1)= lenght(x)=5
% size(y,2)=c
% a plot will collect all lines:
% for x=8 there are 3 lines ( the first row of each matrix `y`, `t`, `z`
% for x=9 there are 3 lines ( the second row of each matrix `y`, `t`, `z`
% ...
% for x=5 there are 3 lines ( the 5th row of each matrix `y`, `t`, `z`
end
end
Let me show an example:
y = rand(5,8)
t = rand(5,8)
z = rand(5,8)
To plot I have started with:
% I was using the initial loop:
if isvector(x)
for i=1:length(x)
% simulation gives me a matrix y,t,z, (c by 5)
%% plots
h(1)=figure;
plot (c,y(i,:));
grid on;
hold on;
plot (c,t(i,:));
plot (c,z(i,:));
hold off;
end
end
As a result, MATLAB gives me 3 figures, but I have expected only one figure with multiple lines. I start from the inside of the initial loop and create a new loop, but it doesn't help me. How to fix it? How to plot all lines (in this example, all 15 lines (#x(i) = 5, #array = 3))?
If you need that loop for further analysis, just move the figure() outside the loop. Otherwise, you could also plot all lines from a single plot() call:
x = [8 9 7 6 5];
c = 1:8;
y = rand(5, 8);
t = rand(5, 8);
z = rand(5, 8);
% Loop approach, move figure() outside the loop
if isvector(x)
figure(1);
hold on;
for i = 1:length(x)
plot(c, y(i, :));
plot(c, t(i, :));
plot(c, z(i, :));
end
hold off;
grid on;
end
% Plot everything with one plot() call
if isvector(x)
figure(2);
plot(c, [y; t; z]);
grid on;
end
The outputs are the same except for the lines' color, which is due to the order of the plotting (first line of y, t, z, second line of ..., and so on vs. all lines from y, all lines from t, and so on.
Hope that helps!
EDIT: To plot all three lines for each x(i) in separate figures, you could use this loop approach:
x = [8 9 7 6 5];
c = 1:8;
y = rand(5, 8);
t = rand(5, 8);
z = rand(5, 8);
if isvector(x)
for i = 1:length(x)
figure(i);
hold on;
plot(c, y(i, :));
plot(c, t(i, :));
plot(c, z(i, :));
hold off;
grid on;
end
end

Edit the x limits of least squares line

I created two scatter plots and then used lsline to add regression lines for each plot. I used this code:
for i=1:2
x = ..;
y = ..;
scatter(x, y, 50, 'MarkerFaceColor',myColours(i, :));
end
h_lines = lsline;
However, the darker line extends far beyond the last data point in that scatter plot (which is at around x=0.3):
lsline doesn't seem to have properties that allow its horizontal range to be set. Is there a workaround to set this separately for the two lines, in Matlab 2016a?
For a single data set
This is a workaround rather than a solution. lsline internally calls refline, which plots a line filling the axis as given by their current limits (xlim and ylim). So you can change those limits to the extent you want for the line, call lsline, and then restore the limits.
Example:
x = randn(1,100);
y = 2*x + randn(1,100); % random, correlated data
plot(x, y, '.') % scatter plot
xlim([-1.5 1.5]) % desired limit for line
lsline % plot line
xlim auto % restore axis limit
For several data sets
In this case you can apply the same procedure for each data set sequentially, but you need to keep only one data set visible when you call lsline; otherwise when you call it to create the second line it will also create a new version of the first (with the wrong range).
Example:
x = randn(1,100); y = 2*x + randn(1,100); % random, correlated data
h = plot(x, y, 'b.'); % scatter plot
axis([min(x) max(x) min(y) max(y)]) % desired limit for line
lsline % plot line
xlim auto % restore axis limit
hold on
x = 2*randn(1,100) - 5; y = 1.2*x + randn(1,100) + 6; % random, correlated data
plot(x, y, 'r.') % scatter plot
axis([min(x) max(x) min(y) max(y)]) % desired limit for line
set(h, 'HandleVisibility', 'off'); % hide previous plot
lsline % plot line
set(h, 'HandleVisibility', 'on'); % restore visibility
xlim auto % restore axis limit
Yet another solution: implement your own hsline. It's easy!
In MATLAB, doing a least squares fit of a straight line is trivial. Given column vectors x and y with N elements, b = [ones(N,1),x] \ y; are the parameters to the best fit line. [1,x1;1,x2]*b are the y locations of two points along the line with x-coordinates x1 and x2. Thus you can write (following Luis' example, and getting the exact same output):
N = 100;
x = randn(N,1); y = 2*x + randn(N,1); % random, correlated data
h = plot(x, y, 'b.'); % scatter plot
hold on
b = [ones(N,1),x] \ y;
x = [min(x);max(x)];
plot(x,[ones(2,1),x] * b, 'b-')
x = 2*randn(N,1) - 5; y = 1.2*x + randn(N,1) + 6; % random, correlated data
plot(x, y, 'r.') % scatter plot
b = [ones(N,1),x] \ y;
x = [min(x);max(x)];
plot(x,[ones(2,1),x] * b, 'r-')
You can get the points that define the line using
h_lines =lsline;
h_lines(ii).XData and h_lines(ii).YData will contain 2 points that define the lines for each ii=1,2 line. Use those to create en equation of a line, and plot the line in the range you want.

How to customize contour lines in Matlab?

I am preparing a contour map where I am supposed to highlight the contour line for a specific level. For Example, my contour line values are lying between -1 and 1 and I want to highlight the line corresponding to the value 0. I tried to do this using the following procedure,
[M,c]=contourf(longitude,latitude,delta',-1:0.2:1);
s=size(c.LevelList,2);
for i=1:s
if (c.LevelList(i)==0)
c.LevelWidth=2;
end;
end;
However, it does nothing to the contour map. Can anyone please help me with the appropriate procedure?
I would suggest simply using contour on your desired levels to highlight after the initial contourf, like so:
% Input.
x = linspace(-2*pi, 2*pi, 101);
y = x + pi;
[X, Y] = meshgrid(x, y);
Z = 0.5 * (sin(X) + cos(Y));
% Levels to plot with contourf.
levelsf = -1:0.2:1;
% Levels to highlight.
levels = [0 0.3];
figure(1);
hold on;
% Contourf all levels.
contourf(X, Y, Z, levelsf);
% Highlight levels with simple contour.
contour(X, Y, Z, levels, 'r', 'LineWidth', 2);
hold off;
For highlighting levels = [0 0.3], you'll get:

Animating plot with matlab / octave

I'm trying to animate a plot for this equation see below I'm trying to animate it for b when 300>= b <= 486
clear all, clc,clf,tic
m=3.73;
a=480;
b=486;
r=1;
fs=44100;
x=linspace(0,2*pi,fs)';
y=m^3*cos(sqrt(a*r*x)).^(0.77)/r + m^3*cos(sqrt(b*r*x)).^(0.77)/r-20;
normalize_y=(y/max(abs(y))*0.8);
plot(x,y)
I'm using octave 3.8.1 which is a clone of matlab
Put your plotting code in a for loop with b as the iterating variable, then place a pause for a small amount of time. After, plot your graph, then use drawnow to refresh the plot. In other words, try this code. I've placed %// Change comments in your code where I have introduced new lines:
m=3.73;
a=480;
r=1;
fs=44100;
x=linspace(0,2*pi,fs)';
figure;
for b = 300 : 486 %// Change
y=m^3*cos(sqrt(a*r*x)).^(0.77)/r + m^3*cos(sqrt(b*r*x)).^(0.77)/r-20;
normalize_y=(y/max(abs(y))*0.8);
pause(0.1); %// Change
plot(x,y);
title(['b = ' num2str(b)]); %// Change
drawnow; %// Change
end
As a bonus, I've put what the current value of b is at each drawing of the plot. BTW, I don't know why normalize_y is in your code when you aren't using it. Do you mean to plot normalize_y instead of y? Just an after thought. Anyway, try that out and see how it looks. Good luck!
Another solution would be to use the handle of a plot and then only update the 'YData'-property of a plot. That is especially useful for more complex plots where there are more than 1 line but you only want to change one line. Also Axis-labels are not overwritten then, which generally prevents alot of overhead.
In Matlabcode it could look like this:
% // Parameter and x-range
m=3.73;
a=480;
r=1;
fs=44100;
x=linspace(0,2*pi,fs)';
% // function to compute y for given x and parameter b
f = #(x, b) m^3*cos(sqrt(a*r*x)).^(0.77)/r + m^3*cos(sqrt(b*r*x)).^(0.77)/r-20;
% // first plot out of loop (to get plot handle)
figure;
b = 300;
y = f(x, b);
handle = plot(x, y);
xlabel('x') % // only set once
ylabel('y=f(x,b)') % // only set once
title(['b = ' num2str(b)]);
pause(0.1);
% // animate for b = 301 to 86
for b = 301:486 %// Change
set(handle, 'YData', f(x, b)) % set new y-data in plot handle
pause(0.1); %// update plot
title(['b = ' num2str(b)]); %// update title
end
This will work with octave 3.8.1
% // Parameter and x-range
m=3.73;
a=480;
r=1;
fs=44100;
x=linspace(0,2*pi,fs)';
% // function to compute y for given x and parameter b
f = #(x, b) m^3*cos(sqrt(a*r*x)).^(0.77)/r + m^3*cos(sqrt(b*r*x)).^(0.77)/r-20;
% // first plot out of loop (to get plot handle)
figure;
b = 300;
y = f(x, b);
handle = plot(x, y);
xlabel('x') % // only set once
ylabel('y=f(x,b)') % // only set once
title(['b = ' num2str(b)]);
pause(0.1);
% // animate for b = 301 to 86
for b = 301:486 %// Change
%set(handle, 'YData', f(x, b)) % set new y-data in plot handle
%To work with octave 3.8.1 use the line below
set(handle, 'YData', real (f(x, b)))
pause(0.1); %// update plot
title(['b = ' num2str(b)]); %// update title
end

Draw log graph curve on Matlab by clicking?

I'd like to draw a curve on an empty (semilog-y) graph by clicking the points I want it to run through, on the X-Y plane.
Is there a function for this?
edit: I'm trying to do this by obtaining the position of last pointer click -
axis([0 3000 0 1000]);
co=get(gcf, 'CurrentPoint');
It seems to return the cursor position at the time of execution, but it does not change later.
edit2: Here's what works for me. The actual drawing I can do by using the arrays of points collected.
clear
clc
h=plot(0);
grid on;
xlim([0 3000]);
ylim([0 1000]);
datacursormode on;
% Enlarge figure to full screen.
screenSize = get(0,'ScreenSize');
set(gcf, 'units','pixels','outerposition', screenSize);
hold on;
% Print the x,y coordinates - will be in plot coordinates
x=zeros(1,10); y=zeros(1,10);
for p=1:10;
[x(p),y(p)] = ginput(1) ;
% Mark where they clicked with a cross.
plot(x(p),y(p), 'r+', 'MarkerSize', 20, 'LineWidth', 3);
% Print coordinates on the plot.
label = sprintf('(%.1f, %.1f)', x(p), y(p));
text(x(p)+20, y(p), label);
end
Not really, but now there is:
function topLevel
%// parameters
xrange = [0 100];
yrange = [1e-4 1e4];
%// initialize figure, plot
figure, clf, hold on
plot(NaN, NaN);
axis([xrange yrange]);
set(gca, 'YScale', 'log')
t = text(sum(xrange)/2, sum(yrange)/2, ...
'<< Need at least 3 points >>',...
'HorizontalAlignment', 'center');
%// Main loop
xs = []; p = [];
ys = []; P = [];
while true
%// Get new user-input, and collect all of them in a list
[x,y] = ginput(1);
xs = [xs; x]; %#ok<AGROW>
ys = [ys; y]; %#ok<AGROW>
%// Plot the selected points
if ishandle(p)
delete(p); end
p = plot(xs, ys, 'rx');
axis([xrange yrange]);
%// Fit curve through user-injected points
if numel(xs) >= 3
if ishandle(t)
delete(t); end
%// Get parameters of best-fit in a least-squares sense
[A,B,C] = fitExponential(xs,ys);
%// Plot the new curve
xp = linspace(xrange(1), xrange(end), 100);
yp = A + B*exp(C*xp);
if ishandle(P)
delete(P); end
P = plot(xp,yp, 'b');
end
end
%// Fit a model of the form y = A + B·exp(C·x) to data [x,y]
function [A, B, C] = fitExponential(x,y)
options = optimset(...
'maxfunevals', inf);
A = fminsearch(#lsq, 0, options);
[~,B,C] = lsq(A);
function [val, B,C] = lsq(A)
params = [ones(size(x(:))) x(:)] \ log(abs(y-A));
B = exp(params(1));
C = params(2);
val = sum((y - A - B*exp(C*x)).^2);
end
end
end
Note that as always, fitting an exponential curve can be tricky; the square of the difference between model and data is exponentially much greater for higher data values than for lower data values, so there will be a strong bias to fit the higher values better than the lower ones.
I just assumed a simple model and used a simple solution, but this gives a biased curve which might not be "optimal" in the sense that you need it to be. Any decent solution really depends on what you want specifically, and I'll leave that up to you ^_^