Dividing matlab plot into grids - matlab

I have two different functions of time x(t) and y(t). I want to plot x(t) vs y(t) in Matlab . The plot needs to be divided into a 40x40 grid stretching from min and max values of signal in each direction. I then need to calculate the number of grid boxes occupied in the plot. Please suggest a convenient way to implement this in Matlab.
I've tried the following code (neglect the upper and lower limits of axis):
NrGrid = 20; % Number Of Grids
x = linspace(0, 100, NrGrid+1);
[X,Y] = meshgrid(x);
figure(1)
plot(X,Y,'k')
hold on
plot(Y,X,'k')
hold off
set(gca, 'Box','off', 'XTick',[], 'YTick',[])
axis square
In my understanding, the code only divides the plot into grids. how do I count the number of grids that are occupied?
Reference: I basically need to implement the algorithm in this paper:
http://www.fhv.at/media/pdf/forschung/prozess-und-produktengineering/working-papers/working-papers-2005/detecting-ventricular

Sounds like you want to create a 40x40 matrix and then use a Bresenham line drawing algorithm to connect each of the points (after appropriate scaling) in x(t)/y(t) correspondence in that matrix.
You can then use nnz to count the number of non-zero elements in the matrix.

I managed to get a much simpler solution than the one mentioned by Dave Durbin by quantizing the signal into 40 levels and then comparing it with its shifted region. The code is attached for reference:
function TD=TimeDelay(val,fs)
n=40;
jump=( max(val) + abs(min(val)))/40;
level=zeros(n,1);
level(1)=min(val) + jump;
for i=2:n
level(i)=level(i-1)+jump;
end
level(n)=level(n)+1;
ScaledECG=zeros(size(val));
ScaledECG(val <= level(1))=1;
for j=2:n
ScaledECG( val<=level(j) & val>level(j-1))=j;
end
tau=fs*.5;
N=zeros(n,n);
for k=tau+1:1:length(val)
N(ScaledECG(k-tau),ScaledECG(k))=N(ScaledECG(k-tau),ScaledECG(k)) + 1;
end
N(N>5)=0;
N(N<=5)=1;
TD=sum(sum(N));

Related

How to resize the axes of an graph on Matlab?

I need ideas to resize my axes to have a much more airy graph to better visualize and calculate the gain between the different curves.
I used the code : axis([0 6 1e-3 1e0]) or xlim([0 6]); ylim([1e-3 1e0])
I would like to have for example my curve with: xlim([0:0.2:6]) (just the idea, otherwise it's wrong on matlab).
Thank you!
If I understand what you want, you need more XTicks in the x limits mentioned. After you plot just:
set(gca,'XTick',0:0.2:6)
another way is to write:
h=plot(.... whatever you plot...
h.XTick=0:0.2:6
Logarithmic Plot:
To create the axes the function xticks() and yticks() can be used to set the intervals, start and endpoints. xticks() and yticks() essentially take vectors that define all the ticks on the scales/axes. Just in case you'd like to also edit the interval along the y-axis. This vector can be created by raising each element in the vector (-3,1:0) to be an exponent with a base of 10. Finally, setting gca (the current axis) to logarithmic will allow the vertical spacing between the ticks to be evenly distributed.
axis([0 6 1e-3 1e0]);
Start = 0; Interval = 0.2; End = 6;
X_Vector = (Start: Interval: End);
xticks(X_Vector);
Y_Vector = 10.^(-3: 1: 0);
yticks(Y_Vector);
set(gca, 'YScale', 'log');
title("Logarithmic Plot");
grid;
Ran using MATLAB R2019b

How to create Evenly-spaced and the unevenly-spaced grids

I am trying to create a function to test_Lagrange_interpolation().
I need to plot Lagrangian interpolant of (1) built on the grid (2) with N= 8 nodes and evaluated at x.
And
another plot Lagrangian interpolant of (1) built on the grid (3) withN= 8 nodes and evaluated at x.
So, in other words, to make evenly space grid we can use linspace(-1,1,9)
for unevely space grid what can we use?
Thankx
First, we have a Lagrange polynomials with type
even grid interpolation means we generate an even x to do interpolation.
uneven grid interpolation means the x is an uneven vector.
So, what is the benefit of an uneven interpolation? It is due to some shortage of even interpolation:Runge's phenomenon, which is a problem of oscillation at the edges of an interval that occurs when using polynomial interpolation with polynomials of a high degree over a set of equispaced interpolation points.
In other words, just look at the figure below. The left one is a LaGrange polynomial with even grid and the right one's grid is uneven(Chebyshev polynomials), and we could reckon that in this case, the performance of the right one (uneven grid) is better.
Codes:
clc; clear;
syms X
subplot(1,2,1)
ezplot('1/(1+25*x^2)',[-3 3])
Y=0;
xx=-3:0.5:3;
yy=1./(1+25*xx.^2);
for ii=1:length(xx)
tmp=1;
for jj=1:length(xx)
if (jj == ii)
continue;
end
tmp=tmp*(X-xx(jj))/(xx(ii)-xx(jj));
end
Y=Y+tmp*yy(ii);
end
hold on
ezplot(Y,[-3 3])
axis([-3 3 0 1.2])
title('even grid')
subplot(1,2,2)
ezplot('1/(1+25*x^2)',[-3 3])
Y2=0;
xx=-cos((0:12)/12*pi)*3;
yy=1./(1+25*xx.^2);
for ii=1:length(xx)
tmp=1;
for jj=1:length(xx)
if (jj == ii)
continue;
end
tmp=tmp*(X-xx(jj))/(xx(ii)-xx(jj));
end
Y2=Y2+tmp*yy(ii);
end
hold on
ezplot(Y2,[-3 3])
axis([-3 3 0 1.2])
title('uneven grid')
hope it helps!

Histogram (hist) not starting (and ending) in zero

I'm using the Matlab function "hist" to estimate the probability density function of a realization of a random process I have.
I'm actually:
1) taking the histogram of h0
2) normalizing its area in order to get 1
3) plotting the normalized curve.
The problem is that, no matter how many bins I use, the histogram never start from 0 and never go back to 0 whereas I would really like that kind of behavior.
The code I use is the following:
Nbin = 36;
[n,x0] = hist(h0,Nbin);
edge = find(n~=0,1,'last');
Step = x0(edge)/Nbin;
Scale_factor = sum(Step*n);
PDF_h0 = n/Scale_factor;
hist(h0 ,Nbin) %plot the histogram
figure;
plot(a1,p_rice); %plot the theoretical curve in blue
hold on;
plot(x0, PDF_h0,'red'); %plot the normalized curve obtained from the histogram
And the plots I get are:
If your problem is that the plotted red curve does not go to zero: you can solve that adding initial and final points with y-axis value 0. It seems from your code that the x-axis separation is Step, so it would be:
plot([x0(1)-Step x0 x0(end)+Step], [0 PDF_h0 0], 'red')

Relative Frequency Histograms and Probability Density Functions

The function called DicePlot simulates rolling 10 dice 5000 times.
The function calculates the sum of values of the 10 dice of each roll, which will be a 1 ⇥ 5000 vector, and plot relative frequency histogram with edges of bins being selected in where each bin in the histogram represents a possible value of for the sum of the dice.
The mean and standard deviation of the 1 ⇥ 5000 sums of dice values will be computed, and the probability density function of normal distribution (with the mean and standard deviation computed) on top of the relative frequency histogram will be plotted.
Below is my code so far - What am I doing wrong? The graph shows up but not the extra red line on top? I looked at answers like this, and I don't think I'll be plotting anything like the Gaussian function.
% function[]= DicePlot()
for roll=1:5000
diceValues = randi(6,[1, 10]);
SumDice(roll) = sum(diceValues);
end
distr=zeros(1,6*10);
for i = 10:60
distr(i)=histc(SumDice,i);
end
bar(distr,1)
Y = normpdf(X)
xlabel('sum of dice values')
ylabel('relative frequency')
title(['NumDice = ',num2str(NumDice),' , NumRolls = ',num2str(NumRolls)]);
end
It is supposed to look like
But it looks like
The red line is not there because you aren't plotting it. Look at the documentation for normpdf. It computes the pdf, it doesn't plot it. So you problem is how do you add this line to the plot. The answer to that problem is to google "matlab hold on".
Here's some code to get you going in the right direction:
% Normalize your distribution
normalizedDist = distr/sum(distr);
bar(normalizedDist ,1);
hold on
% Setup your density function using the mean and std of your sample data
mu = mean(SumDice);
stdv = std(SumDice);
yy = normpdf(xx,mu,stdv);
xx = linspace(0,60);
% Plot pdf
h = plot(xx,yy,'r'); set(h,'linewidth',1.5);

Representing three variables in a three dimension plot

I have a problem dealing with 3rd dimension plot for three variables.
I have three matrices: Temperature, Humidity and Power. During one year, at every hour, each one of the above were measured. So, we have for each matrix 365*24 = 8760 points. Then, one average point is taken every day. So,
Tavg = 365 X 1
Havg = 365 X 1
Pavg = 365 X 1
In electrical point of veiw, the power depends on the temperature and humidity. I want to discover this relation using a three dimensional plot.
I tried using mesh, meshz, surf, plot3, and many other commands in MATLAB but unfortunately I couldn't get what I want. For example, let us take first 10 days. Here, every day is represented by average temperature, average humidity and average power.
Tavg = [18.6275
17.7386
15.4330
15.4404
16.4487
17.4735
19.4582
20.6670
19.8246
16.4810];
Havg = [75.7105
65.0892
40.7025
45.5119
47.9225
62.8814
48.1127
62.1248
73.0119
60.4168];
Pavg = [13.0921
13.7083
13.4703
13.7500
13.7023
10.6311
13.5000
12.6250
13.7083
12.9286];
How do I represent these matrices by three dimension plot?
The challenge is that the 3-D surface plotting functions (mesh, surf, etc.) are looking for a 2-D matrix of z values. So to use them you need to construct such a matrix from the data.
Currently the data is sea of points in 3-D space, so, you have to map these points to a surface. A simple approach to this is to divide up the X-Y (temperature-humidity) plane into bins and then take the average of all of the Z (power) data. Here is some sample code for this that uses accumarray() to compute the averages for each bin:
% Specify bin sizes
Tbin = 3;
Hbin = 20;
% Create binned average array
% First create a two column array of bin indexes to use as subscripts
subs = [round(Havg/Hbin)+1, round(Tavg/Tbin)+1];
% Now create the Z (power) estimate as the average value in each bin
Pest = accumarray(subs,Pavg,[],#mean);
% And the corresponding X (temp) & Y (humidity) vectors
Tval = Tbin/2:Tbin:size(Pest,2)*Tbin;
Hval = Hbin/2:Hbin:size(Pest,1)*Hbin;
% And create the plot
figure(1)
surf(Tval, Hval, Pest)
xlabel('Temperature')
ylabel('Humidity')
zlabel('Power')
title('Simple binned average')
xlim([14 24])
ylim([40 80])
The graph is a bit coarse (can't post image yet, since I am new) because we only have a few data points. We can enhance the visualization by removing any empty bins by setting their value to NaN. Also the binning approach hides any variation in the Z (power) data so we can also overlay the orgional point cloud using plot3 without drawing connecting lines. (Again no image b/c I am new)
Additional code for the final plot:
%% Expanded Plot
% Remove zeros (useful with enough valid data)
%Pest(Pest == 0) = NaN;
% First the original points
figure(2)
plot3(Tavg, Havg, Pavg, '.')
hold on
% And now our estimate
% The use of 'FaceColor' 'Interp' uses colors that "bleed" down the face
% rather than only coloring the faces away from the origin
surfc(Tval, Hval, Pest, 'FaceColor', 'Interp')
% Make this plot semi-transparent to see the original dots anb back side
alpha(0.5)
xlabel('Temperature')
ylabel('Humidity')
zlabel('Power')
grid on
title('Nicer binned average')
xlim([14 24])
ylim([40 80])
I think you're asking for a surface fit for your data. The Curve Fitting Toolbox handles this nicely:
% Fit model to data.
ft = fittype( 'poly11' );
fitresult = fit( [Tavg, Havg], Pavg, ft);
% Plot fit with data.
plot( fitresult, [xData, yData], zData );
legend( 'fit 1', 'Pavg vs. Tavg, Havg', 'Location', 'NorthEast' );
xlabel( 'Tavg' );
ylabel( 'Havg' );
zlabel( 'Pavg' );
grid on
If you don't have the Curve Fitting Toolbox, you can use the backslash operator:
% Find the coefficients.
const = ones(size(Tavg));
coeff = [Tavg Havg const] \ Pavg;
% Plot the original data points
clf
plot3(Tavg,Havg,Pavg,'r.','MarkerSize',20);
hold on
% Plot the surface.
[xx, yy] = meshgrid( ...
linspace(min(Tavg),max(Tavg)) , ...
linspace(min(Havg),max(Havg)) );
zz = coeff(1) * xx + coeff(2) * yy + coeff(3);
surf(xx,yy,zz)
title(sprintf('z=(%f)*x+(%f)*y+(%f)',coeff))
grid on
axis tight
Both of these fit a linear polynomial surface, i.e. a plane, but you'll probably want to use something more complicated. Both of these techniques can be adapted to this situation. There's more information on this subject at mathworks.com: How can I determine the equation of the best-fit line, plane, or N-D surface using MATLAB?.
You might want to look at Delaunay triangulation:
tri = delaunay(Tavg, Havg);
trisurf(tri, Tavg, Havg, Pavg);
Using your example data, this code generates an interesting 'surface'. But I believe this is another way of doing what you want.
You might also try the GridFit tool by John D'Errico from MATLAB Central. This tool produces a surface similar to interpolating between the data points (as is done by MATLAB's griddata) but with cleaner results because it smooths the resulting surface. Conceptually multiple datapoints for nearby or overlapping X,Y coordinates are averaged to produce a smooth result rather than noisy "ripples." The tool also allows for some extrapolation beyond the data points. Here is a code example (assuming the GridFit Tool has already been installed):
%Establish points for surface
num_points = 20;
Tval = linspace(min(Tavg),max(Tavg),num_points);
Hval = linspace(min(Havg),max(Havg),num_points);
%Do the fancy fitting with smoothing
Pest = gridfit(Tavg, Havg, Pavg, Tval, Hval);
%Plot results
figure(5)
surfc(XI,YI,Pest, 'FaceColor', 'Interp')
To produce an even nicer plot, you can add labels, some transparancy and overlay the original points:
alpha(0.5)
hold on
plot3(Tavg,Havg,Pavg,'.')
xlabel('Temperature')
ylabel('Humidity')
zlabel('Power')
grid on
title('GridFit')
PS: #upperBound: Thanks for the Delaunay triangulation tip. That seems like the way to go if you want to go through each of the points. I am a newbie so can't comment yet.
Below is your solution:
Save/write the Myplot3D function
function [x,y,V]=Myplot3D(X,Y,Z)
x=linspace(X(1),X(end),100);
y=linspace(Y(1),Y(end),100);
[Xt,Yt]=meshgrid(x,y);
V=griddata(X,Y,Z,Xt,Yt);
Call the following from your command line (or script)
[Tavg_new,Pavg_new,V]=Myplot3D(Tavg,Pavg,Havg);
surf(Tavg_new,Pavg_new,V)
colormap jet;
xlabel('Temperature')
ylabel('Power/Pressure')
zlabel('Humidity')