Weird thing with matlab's plotting - matlab

When I execute this plot function trying to plot my data as a solid red line it will not plot anything.
plot(1:n, exp(x), '-r')
However, if I change the specification from a solid red line to a green line of circles still using the exact same data as so,
plot(1:n, exp(x), 'og')
it will plot! Why??
Here is all the code if needed.
clear all;
close all;
fprintf('\n\nJustin White Th-9\n\n')
x = input('Input the value of x to be approximated: ');
se = input('Input the target approximate perecent relative error, se: ');
[apre, macexp, n] = f_macexpF15(x, se);
macexp = macexp(1:end-1);
plotyy( 1:n, macexp, 1:n, apre);
hold on;
plot(1:n, exp(x), '-r')
And function it calls here
function[apre, macexp, n] = f_macexpF15(x, se)
fprintf('\nJustin White Th-9\n')
apre = 100*ones(1,3);
ms = [36 22 10];
macexp(1) = 1;
j = 1;
n = 1;
%% comments
while apre >= se
macexp(j+1) = macexp(j) + x^j/factorial(j);
apre(j) = 100 * ((macexp(j+1)-macexp(j))/macexp(j+1));
j = j + 1;
n = n + 1;
end
n = n - 1;
end
Thanks in advance

Easy, 1:n is a vector of length n, whereas x is only a scalar value if not entered correctly. So first of all check whether or not both vectors (1:n and x) are of same size.
Why? If you have two entries for the plot command, and one entry is a vector and the other is a scalar, then MATLAB treats that as if you entred n different plot commands (n for the length of the vector).

Related

Animating 3D Random Walk Matlab

I am writing a code to simulate random walk in 3D space on Matlab. However, there seems to be a problem with my number of simulations, M. I want to animate multiple simulations on the same graph but I am only get 1 simulation. My input of M instead becomes the number of steps. How can I fix this code? Thank you.
I want it to look like the animation in this video: https://www.youtube.com/watch?v=7A83lXbs6Ik
But after each simulation is complete, another one starts on the same graph but a different color.
The end result should be like this
final
clc;
clearvars;
N = input('Enter the number of steps in a single run: '); % Length of the x-axis and random walk.
M = input('Enter the number of simulation runs to do: '); % The number of random walks.
x_t(1) = 0;
y_t(1) = 0;
z_t(1) = 0;
for m=1:M
for n = 1:N % Looping all values of N into x_t(n).
A = sign(randn); % Generates either +1/-1 depending on the SIGN of RAND.
x_t(n+1) = x_t(n) + A;
A = sign(randn); % Generates either +1/-1 depending on the SIGN of RAND.
y_t(n+1) = y_t(n) + A;
A = sign(randn);
z_t(n+1) = z_t(n) + A;
end
plot3([x_t(1) x_t(n+1)], [y_t(1) y_t(n+1)], [z_t(1) z_t(n+1)], 'g');
hold on
grid on
x_t = x_t(n+1);
y_t = y_t(n+1);
z_t = z_t(n+1);
drawnow;
end
You are plotting in the wrong place:
clc;
clearvars;
N = 100
M = 5
x_t(1) = 0;
y_t(1) = 0;
z_t(1) = 0;
c=lines(M) % save colors so each m has its own
for m=1:M
for n = 1:N % Looping all values of N into x_t(n).
A = sign(randn); % Generates either +1/-1 depending on the SIGN of RAND.
x_t(n+1) = x_t(n) + A;
A = sign(randn); % Generates either +1/-1 depending on the SIGN of RAND.
y_t(n+1) = y_t(n) + A;
A = sign(randn);
z_t(n+1) = z_t(n) + A;
plot3([x_t(n) x_t(n+1)], [y_t(n) y_t(n+1)], [z_t(n) z_t(n+1)],'color',c(m,:));
hold on
grid on
drawnow;
end
end

How to plot a matlab function for different parameters using hold on command

I have a matlab function that contain some constant parameter, I want to draw that function, on say same figure, using hold on (probably) while changing the value of that constant.
This my code:
close all
clear all
clc
m = 5;
x = 1:1:10;
y = m*x + 10;
h1 = figure;
plot(x,y)
m = 10;
figure(h1);
hold on
plot(x,y,': r')
When I tried using this code, I got two lines coincident on each others; and it looks matlab just used last value for the parameter m how can I make it use different values.
I found some stuff here, but doesn't fulfill my needs.
Any suggestions?
You need to recalculate y as well:
m = 5;
x = 1:1:10;
y = m*x + 10;
h1 = figure;
plot(x,y); hold on;
m = 10;
y = m*x + 10;
figure(h1);
plot(x,y,': r')
Or create an anonymous function:
x = 1:1:10;
f = #(m) m*x + 10;
%// and then:
h1 = figure;
plot(x,f(5) ); hold on;
plot(x,f(10),': r');
Currently, you're only updating m but you also have to calculate y again. This is why it plots exactly the same y (i.e. m is still 5) function when you issue the second plot.
You might want to use a simple for loop for that, like:
m = 5;
x = 1:1:10;
figure;
hold on;
for m=1:1:10
y = m*x + 10;
plot(x,y,': r')
end
In addition to the short answer - improving the plot..
%% Data Preparations
x = 1:10;
ms = 3; % number of different slopes
%% Graph Preparations
hold on;
% Prepare the string cell array
s = cell(1, ms);
% Handle storage
h = zeros(1, ms);
% Plot graphs
for m=1:ms
y = m*x + 10;
h(m)= plot(x,y,'Color',[1/m rand() rand()]);
s{m} = sprintf('Plot of y(m=%d)', m);
end
% Plot all or select the plots to include in the legend
ind = [ms:-1:1] .* ones(1,ms); % plot all
%ind = [ 1 3 4 ]; % plot selected
% Create legend for the selected plots
legend(h(ind), s{ind});
Additional advice: When working with MATLAB and you try to improve the performance of your code, you shoud try to avoid using for-loops since MATLAB is MATrix manipulation and that's what it can do best. Ones you've taken this philosophy in, you'll create the most beautiful code one-liners! ;)
This script is an adoption of Steve Lord's post.

calculating for mean square displacement

clear all; close all; clc;
figure(1)
set(gcf,'Units','normalized','Position',[0 0 1 1])
N = 100;
M = 100;
x(1,M) = 0;
y(1,M) = 0;
for n = 2:1:N
bx = randi([0,1],1,M)*2-1; % binary random number
by = randi([0,1],1,M)*2-1; % binary random number
x(n,:) = x(n-1,:) + bx;
y(n,:) = y(n-1,:) + by;
subplot(1,2,1)
plot(x(:,1),y(:,1),'k')
xlabel('x')
ylabel('y')
axis equal
set(gca,'FontSize',20)
subplot(3,2,6)
plot([0:1:n],sqrt(2*[0:1:n]),'r')
hold on
plot(sqrt(mean(x.^2+y.^2,2)),'k')
xlim([0 N])
xlabel('t')
ylabel('MSD(t)')
set(gca,'FontSize',12)
drawnow()
end
msd = mean(sqrt(2*[0;1;n]));
disp(msd);
msds = mean(sqrt(mean((x.^2+y.^2),2)));
disp(msds);
------ i have tried running and modified the codes above, and fortunately, it was very successful ... its just that the values that will be displayed on "msd" and "msds" have a very large difference .. the values of both must be closer or almost equal .. well, the command i used for calculating both has been successful for the same simulation but its in one-dimensional .. and the above code is two dimensional .. what must i do ??
You have a typo at line 39. Try:
msd = mean(sqrt(2*[0:1:n]));
instead of:
msd = mean(sqrt(2*[0;1;n]));
Then I have the same value for msd and msds.

ezplot not working unless global variable is written

I'm trying to plot the following function
% k-nn density estimation
% localSearcher is a handle class responsible for finding the k closest points to x
function z = k_nearest_neighbor(x, localSearcher)
% Total point count
n = localSearcher.getPointCount();
% Get the indexes of the k closest points to x
% (the k parameter is contained inside the localSearcher class)
idx = localSearcher.search(x);
% k is constant
k = length(idx);
% Compute the volume (i.e. the hypersphere centered in x that encloses every
% sample in idx)
V = localSearcher.computeVolume(x, idx);
% The estimate for the density function is p(x) = k / (n * V)
z = k / (n * V);
end
I know for sure that the above algorithm is correct, because I get a reasonable plot using the following function
% Plot the values of k_nearest_neighbor(x, searcher) by sampling it manually
function manualPlot(samples, searcher)
a = -2;
b = 2;
n = 1000;
h = (b - a) / n;
sp = linspace(a, b, n);
pt = zeros(n);
areas = zeros(n);
estimated_pdf = #(x)k_nearest_neighbor(x, searcher);
area = 0;
for i = 1 : length(sp)
x = sp(i);
pt(i) = estimated_pdf(x);
area = area + h * pt(i);
areas(i) = area;
end
figure, hold on
title('k-nn density estimation');
plot(sp, pt, sp, areas, ':r');
legend({'$p_n(x)$', '$\int_{-2}^{x} p_n(x)\, \, dx$'}, 'Interpreter', 'latex', 'FontSize', 14);
plot(samples,zeros(length(samples)),'ro','markerfacecolor', [1, 0, 0]);
axis auto
end
called by
function test2()
clear all
close all
% Pattern Classification (page 175)
samples = [71 / 800; 128 / 800; 223 / 800; 444 / 800; 475 / 800; 546 / 800; 641 / 800; 780 / 800];
% 3-nn density estimation
searcher = NaiveNearestSearcher(samples, 3);
manualPlot(samples, searcher);
end
which outputs
However, if I try to do the same thing with ezplot
% Plot the values of k_nearest_neighbor using ezplot
function autoPlot(samples, searcher)
estimated_pdf = #(x)k_nearest_neighbor(x, searcher);
figure, hold on
ezplot(estimated_pdf, [-2,2]);
title('k-nn density estimation');
legend({'$p_n(x)$', '$\int_{-2}^{x} p_n(x)\, \, dx$'}, 'Interpreter', 'latex', 'FontSize', 14);
plot(samples,zeros(length(samples)),'ro','markerfacecolor',[1,0,0]);
axis auto
end
I get the following incorrect result
No warnings are issued from the console.
It's like the searcher parameter passed to the anonymous function
estimated_pdf = #(x)k_nearest_neighbor(x, searcher);
ezplot(estimated_pdf, [-2,2]);
goes "out of scope" (or something) before ezplot terminates.
The really weird thing is that adding
function z = k_nearest_neighbor(x, localSearcher)
[... same identical code ... ]
global becauseWhyNotVector;
% becauseWhyNotVector(end + 1) = 1; NOT WORKING, I must use the x variable for some reason
becauseWhyNotVector(end + 1) = x;
end
apparently fixes the problem (!).
Here's the full source code, I'm using MATLAB R2011a.

How can I (efficiently) compute a moving average of a vector?

I've got a vector and I want to calculate the moving average of it (using a window of width 5).
For instance, if the vector in question is [1,2,3,4,5,6,7,8], then
the first entry of the resulting vector should be the sum of all entries in [1,2,3,4,5] (i.e. 15);
the second entry of the resulting vector should be the sum of all entries in [2,3,4,5,6] (i.e. 20);
etc.
In the end, the resulting vector should be [15,20,25,30]. How can I do that?
The conv function is right up your alley:
>> x = 1:8;
>> y = conv(x, ones(1,5), 'valid')
y =
15 20 25 30
Benchmark
Three answers, three different methods... Here is a quick benchmark (different input sizes, fixed window width of 5) using timeit; feel free to poke holes in it (in the comments) if you think it needs to be refined.
conv emerges as the fastest approach; it's about twice as fast as coin's approach (using filter), and about four times as fast as Luis Mendo's approach (using cumsum).
Here is another benchmark (fixed input size of 1e4, different window widths). Here, Luis Mendo's cumsum approach emerges as the clear winner, because its complexity is primarily governed by the length of the input and is insensitive to the width of the window.
Conclusion
To summarize, you should
use the conv approach if your window is relatively small,
use the cumsum approach if your window is relatively large.
Code (for benchmarks)
function benchmark
clear all
w = 5; % moving average window width
u = ones(1, w);
n = logspace(2,6,60); % vector of input sizes for benchmark
t1 = zeros(size(n)); % preallocation of time vectors before the loop
t2 = t1;
th = t1;
for k = 1 : numel(n)
x = rand(1, round(n(k))); % generate random row vector
% Luis Mendo's approach (cumsum)
f = #() luisMendo(w, x);
tf(k) = timeit(f);
% coin's approach (filter)
g = #() coin(w, u, x);
tg(k) = timeit(g);
% Jubobs's approach (conv)
h = #() jubobs(u, x);
th(k) = timeit(h);
end
figure
hold on
plot(n, tf, 'bo')
plot(n, tg, 'ro')
plot(n, th, 'mo')
hold off
xlabel('input size')
ylabel('time (s)')
legend('cumsum', 'filter', 'conv')
end
function y = luisMendo(w,x)
cs = cumsum(x);
y(1,numel(x)-w+1) = 0; %// hackish way to preallocate result
y(1) = cs(w);
y(2:end) = cs(w+1:end) - cs(1:end-w);
end
function y = coin(w,u,x)
y = filter(u, 1, x);
y = y(w:end);
end
function jubobs(u,x)
y = conv(x, u, 'valid');
end
function benchmark2
clear all
w = round(logspace(1,3,31)); % moving average window width
n = 1e4; % vector of input sizes for benchmark
t1 = zeros(size(n)); % preallocation of time vectors before the loop
t2 = t1;
th = t1;
for k = 1 : numel(w)
u = ones(1, w(k));
x = rand(1, n); % generate random row vector
% Luis Mendo's approach (cumsum)
f = #() luisMendo(w(k), x);
tf(k) = timeit(f);
% coin's approach (filter)
g = #() coin(w(k), u, x);
tg(k) = timeit(g);
% Jubobs's approach (conv)
h = #() jubobs(u, x);
th(k) = timeit(h);
end
figure
hold on
plot(w, tf, 'bo')
plot(w, tg, 'ro')
plot(w, th, 'mo')
hold off
xlabel('window size')
ylabel('time (s)')
legend('cumsum', 'filter', 'conv')
end
function y = luisMendo(w,x)
cs = cumsum(x);
y(1,numel(x)-w+1) = 0; %// hackish way to preallocate result
y(1) = cs(w);
y(2:end) = cs(w+1:end) - cs(1:end-w);
end
function y = coin(w,u,x)
y = filter(u, 1, x);
y = y(w:end);
end
function jubobs(u,x)
y = conv(x, u, 'valid');
end
Another possibility is to use cumsum. This approach probably requires fewer operations than conv does:
x = 1:8
n = 5;
cs = cumsum(x);
result = cs(n:end) - [0 cs(1:end-n)];
To save a little time, you can replace the last line by
%// clear result
result(1,numel(x)-n+1) = 0; %// hackish way to preallocate result
result(1) = cs(n);
result(2:end) = cs(n+1:end) - cs(1:end-n);
If you want to preserve the size of your input vector, I suggest using filter
>> x = 1:8;
>> y = filter(ones(1,5), 1, x)
y =
1 3 6 10 15 20 25 30
>> y = (5:end)
y =
15 20 25 30