I am using contourf to generate a contour plot for a 2 variable function.
My function is Z = f(x,y).
I generate x and y through meshgrid function in matlab and generate values for Z and then plot the contour using contour(x,y,z).
I want to be able to calculate the volume under this generated contour. Can anyone please help ?
Thanks in advance
couldn't you simply use a integral approximation like a riemann sum? Assuming uniform spacing for x and y something like this should work
delta_x = x(2) - x(1);
delta_y = y(2) - y(1);
vol = sum(Z(:)) * delta_x * delta_y;
This will not be the EXACT volume, but an approximation. Since you know your function you would get a more accurate answer by performing the integration of the function. But if you did not know the function you would use this method or any other numerical integration method.
From calculus we know that an actual integral is just a reimann sum where the width of each interval is infinitely small, so this should be a valid approximation
Related
This question already has answers here:
How to make a log plot in matlab
(3 answers)
Closed 1 year ago.
I have to draw a quadratic plot (something like y=a*x^2). I wonder is there anyway to find a logarithmical scale for x or y axis to convert this plot to linear form?
for example lets imagine we have a plot like this:
I want the final plot be something like this by changing the x or y axis to logarithmical scale. I wonder if this is possible theoretically and the answer is yes how can I find the base value of logarithmical scale.
Not sure what the other answers are going on about here - you're right that if you plot a graph like y = ax^2 with logarithmic scaling on both axes, you'll see a straight line. For example, I just ran
x = 0:0.1:5;
y = x.^2;
plot(x, y)
set(gca, 'xscale', 'log')
set(gca, 'yscale', 'log')
in Matlab and the result is a straight line.
Alternatively, you could take the logarithm of the values and plot them,
plot(log(x), log(y))
with a linear axis scale. In this case the gradient of the line will be the power of your equation (for a quadratic like this, 2) and the y-intercept will be the constant log(a). This is because
y = ax^b
log(y) = log(ax^b)
log(y) = log(a) + log(x^b)
log(y) = log(a) + b*log(x).
The base of your logarithm doesn't matter, as long as you know what it is. For these sorts of problems it's common to use the natural logarithm, log in Matlab. log10 or log2 also work.
Note that these methods only work when x and y are both positive.
I am trying to plot the ksdensity of an Inverse gamma(0.001, 0.001) but the plot has only one point. The commands I used are
alpha1 = 0.001;
beta1 = 0.001;
n = 1e+5;
r=1./gamrnd(alpha1,1/beta1,n,1);
[f,xi] = ksdensity(r);
plot(xi,f,'--m');
The first term of f is a real number and all the others are NaN. The first term of xi is a real number and all the others are Inf.
Could you please me help me with this.
Thank you very much.
Did you look at the generated data in r? I get almost 49 % of the time the value Inf. It appears that many values of the Gamma distribution with the parameters you chose are 0, or actually, so small that they cannot be represented in the standard double precision numeric format of Matlab (the smallest possible value is 2.225 · 10^-308).
If you look at the Wikipedia page for the inverse Gamma distribution, you will see that the mean is not defined for alpha <= 1 and the variance is not defined for alpha <= 2, etc. According to Wolfram Alpha, the mode of your distribution is at 0.000999001, while the median is at 1.90687 · 10^298 (only a few orders of magnitude below the largest possible double value, 1.797 · 10^308!).
The density around the mode
x = 0.0001:0.0001:0.1;
plot(x, beta1 ^ alpha1 / gamma(alpha1) .* x .^ -(alpha1 + 1) .* exp(- beta1 ./ x))
looks like this
but this covers only a tiny fraction of the total distribution (the 1st percentile is at 41.2211).
So the problem here is not the kernel density estimation, but that the distribution you are looking at has extreme properties which make it hard to plot the density from the analytical formula, let alone estimate it from simulated random numbers.
I have a matrix z(x,y)
This is an NxN abitary pdf constructed from a unique Kernel density estimation (i.e. not a usual pdf and it doesn't have a function). It is multivariate and can't be separated and is discrete data.
I wan't to construct a NxN matrix (F(x,y)) that is the cumulative distribution function in 2 dimensions of this pdf so that I can then randomly sample the F(x,y) = P(x < X ,y < Y);
Analytically I think the CDF of a multivariate function is the surface integral of the pdf.
What I have tried is using the cumsum function in order to calculate the surface integral and tested this with a multivariate normal against the analytical solution and there seems to be some discrepancy between the two:
% multivariate parameters
delta = 100;
mu = [1 1];
Sigma = [0.25 .3; .3 1];
x1 = linspace(-2,4,delta); x2 = linspace(-2,4,delta);
[X1,X2] = meshgrid(x1,x2);
% Calculate Normal multivariate pdf
F = mvnpdf([X1(:) X2(:)],mu,Sigma);
F = reshape(F,length(x2),length(x1));
% My attempt at a numerical surface integral
FN = cumsum(cumsum(F,1),2);
% Normalise the CDF
FN = FN./max(max(FN));
X = [X1(:) X2(:)];
% Analytic solution to a multivariate normal pdf
p = mvncdf(X,mu,Sigma);
p = reshape(p,delta,delta);
% Highlight the difference
dif = p - FN;
error = max(max(sqrt(dif.^2)));
% %% Plot
figure(1)
surf(x1,x2,F);
caxis([min(F(:))-.5*range(F(:)),max(F(:))]);
xlabel('x1'); ylabel('x2'); zlabel('Probability Density');
figure(2)
surf(X1,X2,FN);
xlabel('x1'); ylabel('x2');
figure(3);
surf(X1,X2,p);
xlabel('x1'); ylabel('x2');
figure(5)
surf(X1,X2,dif)
xlabel('x1'); ylabel('x2');
Particularly the error seems to be in the transition region which is the most important.
Does anyone have any better solution to this problem or see what I'm doing wrong??
Any help would be much appreciated!
EDIT: This is the desired outcome of the cumulative integration, The reason this function is of value to me is that when you randomly generate samples from this function on the closed interval [0,1] the higher weighted (i.e. the more likely) values appear more often in this way the samples converge on the expected value(s) (in the case of multiple peaks) this is desired outcome for algorithms such as particle filters, neural networks etc.
Think of the 1-dimensional case first. You have a function represented by a vector F and want to numerically integrate. cumsum(F) will do that, but it uses a poor form of numerical integration. Namely, it treats F as a step function. You could instead do a more accurate numerical integration using the Trapezoidal rule or Simpson's rule.
The 2-dimensional case is no different. Your use of cumsum(cumsum(F,1),2) is again treating F as a step function, and the numerical errors resulting from that assumption only get worse as the number of dimensions of integration increases. There exist 2-dimensional analogues of the Trapezoidal rule and Simpson's rule. Since there's a bit too much math to repeat here, take a look here:
http://onestopgate.com/gate-study-material/mathematics/numerical-analysis/numerical-integration/2d-trapezoidal.asp.
You DO NOT need to compute the 2-dimensional integral of the probability density function in order to sample from the distribution. If you are computing the 2-d integral, you are going about the problem incorrectly.
Here are two ways to approach the sampling problem.
(1) You write that you have a kernel density estimate. A kernel density estimate is a special case of a mixture density. Any mixture density can be sampled by first selecting one kernel (perhaps differently or equally weighted, same procedure applies), and then sampling from that kernel. (That applies in any number of dimensions.) Typically the kernels are some relatively simple distribution such as a Gaussian distribution so that it is easy to sample from it.
(2) Any joint density P(X, Y) is equal to P(X | Y) P(Y) (and equivalently P(Y | X) P(X)). Therefore you can sample from P(Y) (or P(X)) and then from P(X | Y). In order to sample from P(X | Y), you will need to integrate P(X, Y) along a line Y = y (where y is the sampled value of Y), but (this is crucial) you only need to integrate along that line; you don't need to integrate over all values of X and Y.
If you tell us more about your problem, I can help with the details.
I want to compute the gradient of the electrostatic potential of combination of 4 charges located at (1,1,0), (1,-1,0), (-1,1,0) and (-1,-1,0). How can I use the symbolic toolbox in MATLAB to achieve this?
My electromagnetics is rusty, but your question has a simple analytical solution.
The electric potential is:
and this is what it looks like on the plane z=0
Now the gradient is
and noting that
you can easily apply the above to all the terms in the equation of the gradient to get a closed form solution that can be easily plotted.
In MATLAB:
Here's an example that shows you how to perform the above partial differentiation in MATLAB. You can then build upon this to derive the full solution. I'll leave that upto you.
syms x y z x0 y0 z0
diff(1/sqrt((x-x0)^2+(y-y0)^2+(z-z0)^2),x)
ans =
-(x - x0)/((x - x0)^2 + (y - y0)^2 + (z - z0)^2)^(3/2)
Given 3 vector-pair, X, Y and Z, how to generate the contour? I understand that we need to make use of the contour plot. But the thing is that we need to pass in a 2x2 matrix for this argument, which presumably, is a matrix of Z corresponding to each X,Y pair. But this would mean that I have to go extra miles to create such a matrix by using griddata interpolation first before talking about contour generation.
Is there any other more succinct method?
Yes. Use the Tricontour tool. It is found on the file exchange (on Matlab Central.) This does the contouring as you desire directly, without forcing you to use meshgrid and griddata.
MATLAB addresses this need of yours fairly succinctly.
What you need to do is use meshgrid to two-dimensionalize your X and Y vectors. Here is a simple example to demonstrate how to generate a contour plot of z = sin (x^2 + x*y^2):
x = -10:0.1:10;
y = -10:0.1:10;
[x,y] = meshgrid(x,y);
z = sin(x.^2+x.*y.^2);
contour(x,y,z)
Note the use of the .^ and .* notations, which forces MATLAB to conduct an element-by-element evaluation of the z matrix, making it 2D in the process.