Tutorial

This tutorial demonstrates the use of the DiscreteNaturalNeighbors.jl package for the interpolation of a function from an unstructured grid in $n \geq 2$ dimensions.

2D interpolation

We first look at a 2D interpolation problem and define a function that we want to interpolate.

using DiscreteNaturalNeighbors, Plots

function f2D(x,y)
    return 0.1*(y-1)^2 / ( 2 + abs(x)^2)^2 + exp(-0.2*(y-x^2)^2) + exp(-0.4*(y-x)^2) * sin(0.25*(0.2*x^2+y)^2) + 1.2*exp(-((x+2)^2)/0.2 - (y-3.5)^4)
end

xRange, yRange = -5:0.05:5, -5:0.05:5

fun_vals = [f2D(x, y) for x in xRange, y in yRange]
heatmap(xRange, yRange, transpose(fun_vals), clim=(minimum(fun_vals), maximum(fun_vals)), xlim=(-5, 5), ylim=(-5,5), aspect_ratio=:equal, size=(400, 350))
Example block output

Next we generate a random sample of points on the 2D space with corresponding function values. For clarity, we also show a scatter plot of the data points along with the underlying function (semi-transparent).

NN     = 1000
points = 10 .* rand(NN, 2) .- 5;
values = [f2D(row...) for row in eachrow(points)];

println("size of points: ", size(points))
println("size of values: ", size(values))

heatmap(xRange, yRange, transpose(fun_vals), clim=(minimum(fun_vals), maximum(fun_vals)),
xlim=(-5, 5), ylim=(-5,5), aspect_ratio=:equal, alpha=0.2, colorbar=false, size=(400, 350))
scatter!(points[:, 1], points[:, 2]; marker_z = values, markersize=3.5, markerstrokecolor=:black, markerstrokewidth=0.5,
clim=(minimum(fun_vals), maximum(fun_vals)), legend=false, xlim=(-5, 5), ylim=(-5,5), aspect_ratio=:equal)
Example block output

Using these random samples, we then interpolate the function on a regular grid (i.e. mesh) over (xRange, yRange) by calling interpolate_dnn():

interp = interpolate_dnn(points, values, (xRange, yRange))

p1 = heatmap(xRange, yRange, transpose(interp), clim=(minimum(fun_vals), maximum(fun_vals)))
p2 = heatmap(xRange, yRange, transpose(interp - fun_vals))
plot(p1, p2, layout=(1, 2), size=(800, 300), xlim=(-5, 5), ylim=(-5,5), aspect_ratio=:equal)
Example block output

The interpolation becomes more accurate with a larger number of data points. As the 2D interpolation is highly efficient even for large data sizes, progress is not displayed by default. A progress bar is enabled by setting the keyword argument verbose=true.

NN     = 10000
points = 10 .* rand(NN, 2) .- 5;
values = [f2D(row...) for row in eachrow(points)];

xRange, yRange = -5:0.025:5, -5:0.025:5
fun_vals = [f2D(x, y) for x in xRange, y in yRange]
interp   = interpolate_dnn(points, values, (xRange, yRange); verbose=true)

p1 = heatmap(xRange, yRange, transpose(interp), clim=(minimum(fun_vals), maximum(fun_vals)))
p2 = heatmap(xRange, yRange, transpose(interp - fun_vals))
plot(p1, p2, layout=(1, 2), size=(800, 300), xlim=(-5, 5), ylim=(-5,5), aspect_ratio=:equal)
Example block output

3D interpolation

3D interpolations over a mesh (xRange, yRange, zRange) are obtained analogously to the 2D case. Again, we define a function to be interpolated, create random data points and use these to obtain the interpolation.

function f3D(x, y, z)
    return exp(-z^2 * (1 + (0.1*x^2+0.4y^2))) * (0.1*(y-1)^2 / ( 2 + abs(x)^2)^2 + exp(-0.2*(y-x^2)^2) + exp(-0.4*(y-x)^2) * sin(0.25*(0.2*x^2+y)^2) + 1.2*exp(-((x+2)^2)/0.2 - (y-3.5)^4))
end

xRange, yRange, zRange = -5:0.05:5, -5:0.05:5, -5:0.05:5
#fun_vals = [f3D(x, y, z) for x in xRange, y in yRange, z in zRange]

NN     = 1000000
points = 10 .* rand(NN, 3) .- 5;
values = [f3D(row...) for row in eachrow(points)];


interp = interpolate_dnn(points, values, (xRange, yRange, zRange));

# plot a slice of the interpolation for comparison with the original function
z_idx = 87
fun_vals = [f3D(x, y, zRange[z_idx]) for x in xRange, y in yRange]
p1 = heatmap(xRange, yRange, fun_vals, clim=(minimum(fun_vals), maximum(fun_vals)))
p2 = heatmap(xRange, yRange, interp[:, :, z_idx], clim=(minimum(fun_vals), maximum(fun_vals)))
p3 = heatmap(xRange, yRange, fun_vals - interp[:, :, z_idx])
plot(p1, p2, p3, layout=(1, 3), size=(1200, 300), xlim=(-5, 5), ylim=(-5,5), aspect_ratio=:equal)
Example block output

Progress is shown for the 3D interpolation by default, and may be disabled by setting verbose=false.

$n$D interpolation

A general $n$-dimensional interpolation from a point set of size (N, n) over a mesh (Range1, Range2, ..., Rangen) is analogously calculated by calling interpolate_dnn(points, values, (Range1, Range2, ..., Rangen)).