i have this formula to find fourier series in matlab
f(n)= (f(t),exp(jnt))
and the inner product is: =(1\2*pi)integral((between pi and
-pi)(f1*f2'*dt))
now i want to find fourier coefficients in matlab for this vector(f(t)=t)
where t is a vector that it's lenght is 1000.
i need to find the 2k+1 fourier coefficients by approximate amount when k=2 , which means n=(-2,-1,0,1,2) and then Compare it to the Analytical Calculation.
this is what i did so far:
clc
t = linspace(-pi,pi,1000);
f=t;
plot(t,f); hold all;
dt=2*pi/1000;
cnPlusVal=0;
cnMinusVal=0;
FourierS1=0;
FourierS2=0;
k=2;
for l = 1:k
cnPlusVal=cnPlusVal+f.*exp(-i*l*t)*(dt/2*pi) ;
cnMinusVal=cnMinusVal+f.*exp(i*l*t)*(dt/2*pi);
FourierS1=FourierS1+cnPlusVal.*(exp(i*l*t));
FourierS2=FourierS2+cnMinusVal.*(exp(i*-l*t));
end
now in order to Compare it to the Analytical Calculation i need to plot the forier series .. any help of how to do this in the same graph for f ?
You have two problems to deal with here:
your first plot is on a completely different scale when compared to the output series;
you cannot infer a good axis scope using the limits of the series, because they contain complex numbers.
Here is the workaround I propose you:
figure();
plot(t,FourierS1);
x_lim = get(gca(),'XLim');
y_lim = get(gca(),'YLim');
hold on;
plot(t,f);
set(gca(),'XLim',x_lim,'YLim',y_lim);
hold off;
Basically:
you plot the Fourier serie;
you retain the current x-axis and y-axis limits of the plot;
you plot f over the current plot using the hold function properly;
you revert the plot limits to the previous scope.
Here is the output:
Related
I'm plotting a series of lines in MATLAB and the figure is like this:
As you can see the X-axis is Frequency, I want to limit the frequency spectrum so I use Xlim function in my code to select my desired bandwidth while plotting.
Now I want to calculate the slope of those lines in the chosen frequency bandwidth (what's in the plot window), not the entire band but if I choose the basic fitting option, it's clearly giving me a linear fit for the line over the entire frequency band.
Any advice?
Thanks.
You can do this in the matlab script:
% your data
f = linspace(2e7,11e7,100);
x = linspace(-0.5,-2.5,100)+0.1*rand(1,100);
% Linear fit in a specific range:
[~,i] = find( f>3e7 & f<9e7 ); % <= set your range here
p = polyfit(f(i),x(i),1); % <= note the (i) for both variables
figure;
hold all
plot(f,x,'r.-')
plot(f(i),polyval(p,f(i)),'k-','LineWidth',2) % <= polyval takes the 'p' from polyfit + the data on the x-axis
% the fit is y = p(1)*x+p(2)
You won't be able to use the basic fitting GUI for what you want to do. You will probably need to write a custom function that will "crop" the data in question to the x-limits of your current view. Then use polyfit or similar on those data segments to create the fit.
Suppose I have the following data and commands:
clc;clear;
t = [0:0.1:1];
t_new = [0:0.01:1];
y = [1,2,1,3,2,2,4,5,6,1,0];
p = interp1(t,y,t_new,'spline');
plot(t,y,'o',t_new,p)
You can see they work quite fine, in the sense interpolating function matches the data points at the nodes fine. But my problem is, I need to compute the exact derivative of y (i.e., p function) w.r.t. time and plot it against the t vector. How can it be done? I shall not use diff commands, because I need to make sure the derivative function has the same length as t vector. Thanks a lot.
Method A: Using the derivative
This method calculates the actual derivative of the polynomial. If you have the curve fitting toolbox you can use:
% calculate the polynominal
pp = interp1(t,y,'spline','pp')
% take the first order derivative of it
pp_der=fnder(pp,1);
% evaluate the derivative at points t (or any other points you wish)
slopes=ppval(pp_der,t);
If you don't have the curve fitting toolbox you can replace the fnderline with:
% piece-wise polynomial
[breaks,coefs,l,k,d] = unmkpp(pp);
% get its derivative
pp_der = mkpp(breaks,repmat(k-1:-1:1,d*l,1).*coefs(:,1:k-1),d);
Source: This mathworks question. Thanks to m7913d for linking it.
Appendix:
Note that
p = interp1(t,y,t_new,'spline');
is a shortcut for
% get the polynomial
pp = interp1(t,y,'spline','pp');
% get the height of the polynomial at query points t_new
p=ppval(pp,t_new);
To get the derivative we obviously need the polynomial and can't just work with the new interpolated points. To avoid interpolating the points twice which can take quite long for a lot of data, you should replace the shortcut with the longer version. So a fully working example that includes your code example would be:
t = [0:0.1:1];
t_new = [0:0.01:1];
y = [1,2,1,3,2,2,4,5,6,1,0];
% fit a polynomial
pp = interp1(t,y,'spline','pp');
% get the height of the polynomial at query points t_new
p=ppval(pp,t_new);
% plot the new interpolated curve
plot(t,y,'o',t_new,p)
% piece-wise polynomial
[breaks,coefs,l,k,d] = unmkpp(pp);
% get its derivative
pp_der = mkpp(breaks,repmat(k-1:-1:1,d*l,1).*coefs(:,1:k-1),d);
% evaluate the derivative at points t (or any other points you wish)
slopes=ppval(pp_der,t);
Method B: Using finite differences
A derivative of a continuous function is at its base just the difference of f(x) to f(x+infinitesimal difference) divided by said infinitesimal difference.
In matlab, eps is the smallest difference possible with a double precision. Therefore after each t_new we add a second point which is eps larger and interpolate y for the new points. Then the difference between each point and it's +eps pair divided by eps gives the derivative.
The problem is that if we work with such small differences the precision of the output derivatives is severely limited, meaning it can only have integer values. Therefore we add values slightly larger than eps to allow for higher precisions.
% how many floating points the derivatives can have
precision = 10;
% add after each t_new a second point with +eps difference
t_eps=[t_new; t_new+eps*precision];
t_eps=t_eps(:).';
% interpolate with those points and get the differences between them
differences = diff(interp1(t,y,t_eps,'spline'));
% delete all differences wich are not between t_new and t_new + eps
differences(2:2:end)=[];
% get the derivatives of each point
slopes = differences./(eps*precision);
You can of course replace t_new with t (or any other time you want to get the differential of) if you want to get the derivatives at the old points.
This method is slightly inferior to method a) in your case, as it is slower and a bit less precise. But maybe it's useful to somebody else who is in a different situation.
Using MATLAB I apply Matching Pursuit to approximate a signal. My problem is that I struggle to visualize the time-frequency representation of the selected atoms. I'm trying to produce a Wigner plot similar to the following image (source).
I have looked into the Wavelet Toolbox, Signal Processing Toolbox as well as the open source Time-Frequency Toolbox, but I'm possibly just using the wrong parameters, since my experience with signal processing is quite limited.
Example
Using this data my goal is to reproduce the plot from above.
% fit the signal using MP
itermax = 50;
signal = load('signal.txt');
dict = wmpdictionary(length(signal));
[signal_fit, r, coeff, iopt, qual, X] = wmpalg('OMP', signal, dict, ...
'itermax', itermax);
% wigner plot of the simulated signal
tfrwv(signal_fit) % wigner-ville function from time-frequency toolbox
% wigner plot of each atom
atoms = full(dict(:, iopt)) % selected atoms
for i = 1:itermax
tfrwv(atoms(:, i))
end
Unfortunately, none of the resulting plots comes close to the target visualization. Note, that in the example I use tfrwv with standard parameters which I tweak with the GUI that it opens.
I'd greatly appreciate your help.
Update
I think I have now understood that one needs to use Gabor atoms to get blobs with shapes resembling stretched gaussians. Unfortunately, there are no Gabor functions in the predefined dicts of the Signal Processing Toolbox. However, this question helped me in implementing the needed dictionaries, such that I get atoms which look quite similar to the example:
Since my plots come close but are not perfect, there are still two questions open:
Can all of the blobs that we see in the first example be modeled by Gabor atoms alone, or do I need another dictionary of functions?
How can I combine the indidividual imagesc plots into a single visualization?
To answer your second question 'How can I combine the indidividual imagesc plots into a single visualization?'
If you have multiple 2d matrices that you want to superimpose and display using imagesc, I would suggest taking the element-wise maximum.
For example, I generate two 31x31 grids with gaussians with different mean and variance.
function F = generate2dGauss(mu, Sigma)
x1 = -3:.2:3; x2 = -3:.2:3;
[X1,X2] = meshgrid(x1,x2);
F = mvnpdf([X1(:) X2(:)],mu,Sigma);
F = reshape(F,length(x2),length(x1));
end
F1 = generate2dGauss([1 1], [.25 .3; .3 1]);
F2 = generate2dGauss([-1 -1], [.1 .1; .1 1]);
I can plot them with subplots as in your example,
figure;
subplot(1,2,1);
title('Atom 1');
imagesc(F1);
subplot(1,2,2);
title('Atom 2');
imagesc(F2);
Or I can plot the per element maximum of the two grids.
figure;
title('Both Atoms');
imagesc(max(F1, F2));
You can also experiment with element-wise means, sums, etc, but based on the example you give, I think maximum will give you the cleanest looking result.
Possible pros and cons of different functions:
Maximum will work best if your atoms always have zero-valued backgrounds and no negative values. If the background is zero-valued, but the atoms also contain negative values, the negative values may be covered up by the background of other atoms. If your atom's overlap, the higher value will of course dominate.
Mean will make your peaks less high, but may be more intuitive where you have overlap between atoms.
Sum will make overlapping areas larger valued.
If you have non-zero backgrounds, you could also try using logical indexing. You would have to make some decisions about what to do in overlapping areas, but it would make it easy to filter out backgrounds.
Q. How can I combine the indidividual imagesc plots into a single visualization?
A. Use subplot to draw multiple plots, find below sample with 2 by 2 plots in a figure. Change your equations in code
x = linspace(-5,5);
y1 = sin(x);
subplot(2,2,1)
plot(x,y1)
title('First subplot')
y2 = sin(2*x);
subplot(2,2,2)
plot(x,y2)
title('Second subplot')
y3 = sin(4*x);
subplot(2,2,3)
plot(x,y3)
title('Third subplot')
y4 = sin(6*x);
subplot(2,2,4)
plot(x,y4)
title('Fourth subplot')
I have a vector with 1000 random numbers called v. I also have a vector, called x that represents the domain of which the numbers in v are generated, and another vector y that has the numbers of the cdf of the values in v. I know that I can do plot(x,y); and get a smooth function of the (non-empirical) cdf, and I also know that I can do cdfplot(v) to get a function of the empirical cdf.
My question is: How can I get these plots on the same set of axis?
Thank you for your help.
You could either generate data for an empirical cdf plot using ecdf or plot it directly with cdfplot like you mentioned. I would recommend using cdfplot since it sets up a few more things, such as a grid:
hFig = figure;
cdfplot(v);
hold all;
plot(x, y);
And as a bonus! Consider showing the X axis in logarithmic units, whichever reveals the data the best for you:
hAxes = get(hFig, 'CurrentAxes');
set(hAxes, 'XScale', 'log')
I have various plots (with hold on) as show in the following figure:
I would like to know how to find equations of these six curves in Matlab. Thanks.
I found interactive fitting tool in Matlab simple and helpful, though somewhat limited in scope:
The graph above seems to be linear interpolation. Given vectors X and Y of data, where X contains the arguments and Y the function points, you could do
f = interp1(X, Y, x)
to get the linearly interpolated value f(x). For example if the data is
X = [0 1 2 3 4 5];
Y = [0 1 4 9 16 25];
then
y = interp1(X, Y, 1.5)
should give you a very rough approximation to 1.5^2. interp1 will match the graph exactly, but you might be interested in fancier curve-fitting operations, like spline approximations etc.
Does rxns stand for reactions? In that case, your curves are most likely exponential. An exponential function has the form: y = a*exp(b * x) . In your case, y is the width of mixing zone, and x is the time in years. Now, all you need to do is run exponential regression in Matlab to find the optimal values of parameters a and b, and you'll have your equations.
The advice, though there might be better answer, from me is: try to see the rate of increase in the curve. For example, cubic is more representative than quadratic if the rate of increase seems fast and find the polynomial and compute the deviation error. For irregular curves, you might try spline fitting. I guess there is also a toolbox in matlab for spline fitting.
There is a way to extract information with the current figure handle (gcf) from you graph.
For example, you can get the series that were plotted in a graph:
% Some figure is created and data are plotted on it
figure;
hold on;
A = [ 1 2 3 4 5 7] % Dummy data
B = A.*A % Some other dummy data
plot(A,B);
plot(A.*3,B-1);
% Those three lines of code will get you series that were plotted on your graph
lh=findall(gcf,'type','line'); % Extract the plotted line from the figure handle
xp=get(lh,'xdata'); % Extract the Xs
yp=get(lh,'ydata'); % Extract the Ys
There must be other informations that you can get from the "findall(gcf,...)" methods.