Why MATLAB is only plotting maximum three functions - matlab

I'm trying to plot multiple Fourier series approximations for the function f(x)=(x^2-pi^2)^3, but for some reason my MATLAB will only plot maximum two of the approximations (along with the original f). How can I get it to plot 4 or more? My code for the series is
function [Y]=fourier(X)
N=input('enter the value of N:' )
SN=-16*pi^6/35;
for n=1:N
SN=SN+96*(-1)^n/n^5*(15/n-pi^2).*cos(n*X);
end
Y=SN;
and using
plot(X,Y1,'b',X,Y2,'r',X,Y3,'m',X,Y4,'g')
(where Yi=fourier(X), X=[-pi:0.01:pi] are the various approximations for different N) isn't working; nor is plotting them one by one.
Many thanks in advance for any help that anyone can offer - as you may have noticed I'm a very amateur programmer!!

I have no problems.
I modified your fourier function to accept input N:
function Y = fourier(X,N)
SN = -16*pi^6/35;
for n = 1:N
SN = SN+96*(-1)^n/n^5*(15/n-pi^2).*cos(n*X);
end
Y = SN;
Then, I get the 4 lines:
X = (-pi:0.01:pi)';
Y = [fourier(X,1), fourier(X,2), fourier(X,3), fourier(X,4)];
plot(X,Y)
legend 1 2 3 4
set(gca, 'Xlim',[-3.3, -2.3], 'Ylim',[-60,79])

Related

Plotting an exponential function in matlab

I would like to develop some intuition for this language. Specifically about plotting functions on some interval. Here is a concrete example I am trying to work out. Plot exp(x) over the closed interval [-2,2]. Here exp(x) is Matlab notation for e^x, I think. This is the script based on a guide I just read :
x = [ -2 , 2 ];
y = exp(x);
plot(x,y)
The result is not an exponential curve, but a straight line. What is wrong with this script? And also, if anyone can recommend a good guide for this, I would appreciate it very much. Google results I found only have worked examples.
Two methods of adjusting the number of points plotted (samples) of the function are to either specify the interval between the points or the number of points to be plotted. The plot() function will plot the vectors x and y which will plot the number of points equal to the length of vector x. Similar idea to an Excel sheet scatter plot that is joined with line.
Setting the Interval Between the Plotting Points
X_Minimum = -2;
X_Maximum = 2;
Plotting_Interval = 0.25;
x = (X_Minimum: Plotting_Interval: X_Maximum);
y = exp(x);
plot(x,y,'o-');
title(num2str(Plotting_Interval) + " Interval Between Points");
Setting the Number of Plotting Points
X_Minimum = -2;
X_Maximum = 2;
Number_Of_Points = 18;
x = linspace(X_Minimum,X_Maximum,Number_Of_Points);
y = exp(x);
plot(x,y,'o-');
title(num2str(Number_Of_Points) + " Points Plotted");
Ran using MATLAB R2019b
This is because you only input two point into the function plot():(-2,exp(-2)),(2,exp(2))
.In matlab,the x &y of plot(x,y) are vector of the points you have but not their intervals.

Matlab fit poisson function to histogram

I am trying to fit a Poisson function to a histogram in Matlab: the example calls for using hist() (which is deprecated) so I want to use histogram() instead, especially as you cannot seem to normalize a hist(). I then want to apply a poisson function to it using poisspdf() or any other standard function (preferably no toolboxes!). The histogram is probability scaled, which is where the issue with the poisson function comes from AFAIK.
clear
clc
lambda = 5;
range = 1000;
rangeVec = 1:range;
randomData = poissrnd(lambda, 1, range);
histoFigure = histogram(randomData, 'Normalization', 'probability');
hold on
poissonFunction = poisspdf(randomData, lambda);
poissonFunction2 = poisspdf(histoFigure, lambda);
plot(poissonFunction)
plot(poissonFunction2)
I have tried multiple different methods of creating the poisson function + plotting and neither of them seems to work: the values within this function are not consistent with the histogram values as they differ by several decimals.
This is what the image should look like
however currently I can only get the bar graphs to show up correctly.
You're not specifing the x-data of you're curve. Then the sample number is used and since you have 1000 samples, you get the ugly plot. The x-data that you use is randomData. Using
plot(randomData, poissonFunction)
will lead to lines between different samples, because the samples follow each other randomly. To take each sample only once, you can use unique. It is important that the x and y values stay connected to each other, so it's best to put randomData and poissonFunction in 1 matrix, and then use unique:
d = [randomData;poissonFunction].'; % make 1000x2 matrix to find unique among rows
d = unique(d,'rows');
You can use d to plot the data.
Full code:
clear
clc
lambda = 5;
range = 1000;
rangeVec = 1:range;
randomData = poissrnd(lambda, 1, range);
histoFigure = histogram(randomData, 'Normalization', 'probability');
hold on
poissonFunction = poisspdf(randomData, lambda);
d = [randomData; poissonFunction].';
d = unique(d, 'rows');
plot(d(:,1), d(:,2))
With as result:

MATLAB: polyval function graphs multiple lines for N>1

I am trying to graph a polynomial function using the following code:
y = polyfit(P,C,3);
Line = polyval(y, P);
y =
2.0372e-14 -4.0614e-09 0.0002 2.6060
figure
plot(P,C,'.')
hold on
plot(P, Line, '-')
legend('Observations','y')
axis([0 90000 0 10])
The problem is, it produces multiple lines like this:
This problem does not occur if I set N = 1 or y = polyfit(P,C,1);. In that case I get a proper graph with one line:
How can I graph just 1 line for N = 3?
Here is an Excel version of what I am trying to produce in Matlab:
This is because your observations P are in an arbitrary order: Matlab is going from point to point in that order. You don't actually need to plot the fitted curve at each value P, you just need to plot the fitted curve over the range of P:
Pfitted = linspace(min(P),max(P),1000) % Generate 1000 equally spaced points
Cfitted = polyval(y,Pfitted) % Fit to these points
plot(Pfitted,Cfitted,'-')

How to plot for loop results in matlab?

I am calculating the absolute error of a summation compared to an integral (summation answer - integral answer):
integral of e^x from 0 to 1, compared to (1/n)*summation(e^rand()) from i = 1 to n.
I have to plot the error vs n in matlab. I can't wrap my head around how to do this. I am able to calculate the error from 1 to an arbitrary number like 50 by using a for loop from 1 to 50. But, how would I plot this? I would need to do multiple summations to different values of n correct?
So what you want to do is calculate the area with the integral and the error function at the same time and store them in an array:
maxLevel = 50;
integral = zeros(maxLevel, 1);
summation = zeros(maxLevel, 1);
for i = 1:maxLevel
integral(i) = integralFunction(i);
summation(i) = summationFunction(i);
end
Then you can plot like this:
plot(1:length(integral), integral, 'r');
hold on;
plot(1:length(summation), summation, 'g');

How to fit a curve by a series of segmented lines in Matlab?

I have a simple loglog curve as above. Is there some function in Matlab which can fit this curve by segmented lines and show the starting and end points of these line segments ? I have checked the curve fitting toolbox in matlab. They seems to do curve fitting by either one line or some functions. I do not want to curve fitting by one line only.
If there is no direct function, any alternative to achieve the same goal is fine with me. My goal is to fit the curve by segmented lines and get locations of the end points of these segments .
First of all, your problem is not called curve fitting. Curve fitting is when you have data, and you find the best function that describes it, in some sense. You, on the other hand, want to create a piecewise linear approximation of your function.
I suggest the following strategy:
Split manually into sections. The section size should depend on the derivative, large derivative -> small section
Sample the function at the nodes between the sections
Find a linear interpolation that passes through the points mentioned above.
Here is an example of a code that does that. You can see that the red line (interpolation) is very close to the original function, despite the small amount of sections. This happens due to the adaptive section size.
function fitLogLog()
x = 2:1000;
y = log(log(x));
%# Find section sizes, by using an inverse of the approximation of the derivative
numOfSections = 20;
indexes = round(linspace(1,numel(y),numOfSections));
derivativeApprox = diff(y(indexes));
inverseDerivative = 1./derivativeApprox;
weightOfSection = inverseDerivative/sum(inverseDerivative);
totalRange = max(x(:))-min(x(:));
sectionSize = weightOfSection.* totalRange;
%# The relevant nodes
xNodes = x(1) + [ 0 cumsum(sectionSize)];
yNodes = log(log(xNodes));
figure;plot(x,y);
hold on;
plot (xNodes,yNodes,'r');
scatter (xNodes,yNodes,'r');
legend('log(log(x))','adaptive linear interpolation');
end
Andrey's adaptive solution provides a more accurate overall fit. If what you want is segments of a fixed length, however, then here is something that should work, using a method that also returns a complete set of all the fitted values. Could be vectorized if speed is needed.
Nsamp = 1000; %number of data samples on x-axis
x = [1:Nsamp]; %this is your x-axis
Nlines = 5; %number of lines to fit
fx = exp(-10*x/Nsamp); %generate something like your current data, f(x)
gx = NaN(size(fx)); %this will hold your fitted lines, g(x)
joins = round(linspace(1, Nsamp, Nlines+1)); %define equally spaced breaks along the x-axis
dx = diff(x(joins)); %x-change
df = diff(fx(joins)); %f(x)-change
m = df./dx; %gradient for each section
for i = 1:Nlines
x1 = joins(i); %start point
x2 = joins(i+1); %end point
gx(x1:x2) = fx(x1) + m(i)*(0:dx(i)); %compute line segment
end
subplot(2,1,1)
h(1,:) = plot(x, fx, 'b', x, gx, 'k', joins, gx(joins), 'ro');
title('Normal Plot')
subplot(2,1,2)
h(2,:) = loglog(x, fx, 'b', x, gx, 'k', joins, gx(joins), 'ro');
title('Log Log Plot')
for ip = 1:2
subplot(2,1,ip)
set(h(ip,:), 'LineWidth', 2)
legend('Data', 'Piecewise Linear', 'Location', 'NorthEastOutside')
legend boxoff
end
This is not an exact answer to this question, but since I arrived here based on a search, I'd like to answer the related question of how to create (not fit) a piecewise linear function that is intended to represent the mean (or median, or some other other function) of interval data in a scatter plot.
First, a related but more sophisticated alternative using regression, which apparently has some MATLAB code listed on the wikipedia page, is Multivariate adaptive regression splines.
The solution here is to just calculate the mean on overlapping intervals to get points
function [x, y] = intervalAggregate(Xdata, Ydata, aggFun, intStep, intOverlap)
% intOverlap in [0, 1); 0 for no overlap of intervals, etc.
% intStep this is the size of the interval being aggregated.
minX = min(Xdata);
maxX = max(Xdata);
minY = min(Ydata);
maxY = max(Ydata);
intInc = intOverlap*intStep; %How far we advance each iteraction.
if intOverlap <= 0
intInc = intStep;
end
nInt = ceil((maxX-minX)/intInc); %Number of aggregations
parfor i = 1:nInt
xStart = minX + (i-1)*intInc;
xEnd = xStart + intStep;
intervalIndices = find((Xdata >= xStart) & (Xdata <= xEnd));
x(i) = aggFun(Xdata(intervalIndices));
y(i) = aggFun(Ydata(intervalIndices));
end
For instance, to calculate the mean over some paired X and Y data I had handy with intervals of length 0.1 having roughly 1/3 overlap with each other (see scatter image):
[x,y] = intervalAggregate(Xdat, Ydat, #mean, 0.1, 0.333)
x =
Columns 1 through 8
0.0552 0.0868 0.1170 0.1475 0.1844 0.2173 0.2498 0.2834
Columns 9 through 15
0.3182 0.3561 0.3875 0.4178 0.4494 0.4671 0.4822
y =
Columns 1 through 8
0.9992 0.9983 0.9971 0.9955 0.9927 0.9905 0.9876 0.9846
Columns 9 through 15
0.9803 0.9750 0.9707 0.9653 0.9598 0.9560 0.9537
We see that as x increases, y tends to decrease slightly. From there, it is easy enough to draw line segments and/or perform some other kind of smoothing.
(Note that I did not attempt to vectorize this solution; a much faster version could be assumed if Xdata is sorted.)