Interpolate a scalar field over a 3D mesh refining the grid - matlab

I have function f=f(x,y,z) computed numerically over a grid of points of size MxNxP.
I need to interpolate that values over a finer grid of (obviously) different dimensions. Like I do with interp1 when I have only some values of a function over an interval and I want to interpolate it to find the values at more points.
I tried executing this code:
XX=linspace(0,45,50);
YY=linspace(0,0.5,50);
ZZ=linspace(0,0.5,50);
U_1 = interp3(X,Y,Z,f,XX,YY,ZZ,'linear')
where X Y Z are the vectors of points where I have the values of f. XX,YY,ZZ are the points where I want the solution.
I tried with griddata and also with interp3 but I got the following error message:
Error using griddedInterpolant
The grid vectors do not define a grid of points that match the given values.
Error in interp3 (line 133)
F = griddedInterpolant({X, Y, Z}, V, method,extrap);
Could you help me, please?

You seem to have an irregular gridded data set. In this case you need to use the griddata() function to interpolate.
Take care that your defining point arrays X,Y,Z have equal dimensions. Also the interpolant point arrays XX,YY,ZZ have to have equal dimensions.
That means the following expression must be true (or 1):
all(size(X)==size(Y)) && all(size(X)==size(Z)))
For the creation of your interpolants you may use meshgrid. It is wise to adapt the range of your interpolation grid to your real data range:
[XX,YY,ZZ]=meshgrid(linspace(min(X(:)),max(X(:)),50), ...
linspace(min(Y(:)),max(Y(:)),50), ...
linspace(min(Z(:)),max(Z(:)),50));
This will probably give the result you expect.

Related

MATLAB: Plotting 1D Conditional Distributions with kdensity stacked in a 3D figure

I have a T x 2 Matrix, where in the second column I have some daily financial returns and in the first column I have an indicator, which can assume integer values in the interval [1, 9].
I want to extract 9 different conditional distributions of my returns, conditioned on the values assumed by the indicator. At this point, I want to plot the conditional densities through a Gaussian smoothing with the function 'ksdensity' and plot them in the same 3D plot. The final output should be similar to this one: Image
I tried to reach this result by adapting the answer I found at this thread: Function.
Now suppose that x = axis of returns, y = axis of indicator possible values, z = smoothed conditional densities.
My problem is that, while in the example the meshgrid required for all the values of y have the same values of x by construction, I have different values of x (the returns) because of the conditioning.
First split your returns data into 9 vectors, according to the indicator variable. You can use accumarray for that. Then run ksdensity on each vector separately. Then plot those outputs.

Interpolation of a 3D vector field in MATLAB

I'm trying to interpolate a 3D vector field. For every (x,y,z) position we have a vector (u,v,w). I have another set of points let's call them (xq,yq,zq) in which I don't have vector information (uq,vq,wq). I would like to interpolate my data to find the vectors at the points (xq,yq,zq).
I've tried to interpolate using several functions like griddata, by interpolating each vector component individually.
uq = griddata(x,y,z,u,xq,yq,zq);
vq = griddata(x,y,z,v,xq,yq,zq);
wq = griddata(x,y,z,w,xq,yq,zq);
I expect to obtain the vectors at the locations I specified, but the message I get is:
"Warning: The underlying triangulation is empty - the points may be
coplanar or collinear."
Is there a better way to interpolate a vector field?

Interpolating scattered 3D electric field data

I have measured electric field data in three dimensions of the following form:
pos = [x1 y1 z1
x2 y2 z2
. . .
x1000 y1000 z1000]
ef = [e_x1 e_y1 e_z1
e_x2 e_y2 e_z2
. . .
e_x1000 e_y1000 e_z1000]
The positions are located within a half sphere. I want to be able to interpolate the electric field at some point of the sphere, so that I receive all the three values of the electric field components, not just the norm of the whole field. interp3 won't work as the points are not in a grid. scatteredInterpolant needs the norm as the input, and the generated function only returns the norm. Any suggestions on what function to use or how to solve this problem?
scatteredInterpolant only interpolates one column of samples at a time, but one way to interpolate a vector field is to interpolate each component of the vector independently.
This is straightforward with scatteredInterpolant.
componentInterpolants = cellfun(#(v) {scatteredInterpolant(pos,v)}, num2cell(ef,1));
This leaves you with a cell array of three scatteredInterpolant objects, one for each cartesian component of the field. By evaluating each of them individually for the specified coordinates and concatenating the result you get an electric field vector for each given coordinates. You could define a convenience function to give you the interpolated vector field in full for a given set off coordinates:
efInterpolant = #(coords) cell2mat(cellfun(#(interpolant) {interpolant(coords)}, componentInterpolants));
Verify that this interpolates the original vector field exactly (barring floating point error):
assert(all(all(abs(ef - efInterpolant(pos)) < eps * 2)));
If interpolating each cartesian component independently doesn't maintain some relationship between the vector components you expect within this field then you might need a different numerical method – perhaps some coordinate transformation before taking the same interpolation approach – but that's probably more a question for the Mathematics Stack Exchange site.

Matlab plot of a function with 2 variables

I have a problem to plot a function with 2 variables:
if i do:
x= linspace(0,5);
y=linspace(0,5);
[x,y]=meshgrid(x,y);
z=log(x.*sqrt(y-x));
mesh(x,y,z);
I get this error:
Error using mesh (line 76) X, Y, Z, and C cannot be complex.
I think because I have some complex results in the computation.
How could I solve?
What kind of output do you expect? It's possible to plot the absolute value using mesh(x,y,abs(z));, but I'm not sure if this is what you want. quiver is another possibility to plot your data.
The reason you are getting complex results is the sqrt(y-x) part in your code. y is less than x at almost half of the points of your grid which leads to computing the square root of a negative number.
So, as Daniel suggested, you can use abs(z). Alternatively you could check if it is OK for the particular application to compute sqrt(abs(y-x)) to make sure you have a positive number under the square root

How do I "stretch" (interpolate) an array but keep its underlying data intact?

I have two splines that I've generated with (a bit of modification of) getcurve() which represent an XY and XZ of a trajectory. I would like to combine the two splines together to generate a 3d plot, via plot3(). I modified getcurve() to output the XData and YData of the line drawn on the plot.
Since the splines are graphically generated, the number of elements won't necessarily be the same between XY and XZ. Suppose length(XY)>length(XZ). I'm trying to create a new vector XZ_2 that has the same length as XY and has the same x-values as XY.
My first idea was to interpolate as follows:
XZ_2(:,2) = interp1(XZ(:,1), XZ(:,2), XY(:,1))
but I get an error:
Error using griddedInterpolant
The grid vectors are not strictly monotonic increasing.
Error in interp1 (line 191)
F = griddedInterpolant(X,V,method);
The spline XZ looks like this:
I don't understand why I can't interpolate given this spline. It doesn't look like anything special. You can rebuild this spline yourself by doing the following (you'll need the Curve Fitting Toolbox):
>> xz = [0.0288 0.0518 0.1071 0.1763 0.2707 0.3583 0.4988 0.5864 0.7339 0.8191 0.9182 0.9781
1.8070 1.3626 0.9766 0.4152 -0.0643 -0.3684 -0.9181 -1.1637 -1.4795 -1.6667 -1.8070 -1.9474];
>> fnplt(cscvn(xz));
Is there a way to "resize" XZ to use the same x-values as XY? I realize that some information about XZ will be lost when I do this, but that's okay.
it says that in interp1(x, y, xi);, the x and xi must be monotonic increasing, i.e. sorted.