Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getdata2d relies on matplotlib #49

Closed
henry2004y opened this issue May 19, 2024 · 5 comments
Closed

getdata2d relies on matplotlib #49

henry2004y opened this issue May 19, 2024 · 5 comments

Comments

@henry2004y
Copy link
Owner

function getdata2d(bd::BATLData, var::AbstractString,

Currently getdata2d depends on matplotlib to do interpolations. In the future we really need to figure out how to do it native Julia. Related to #14.

@henry2004y
Copy link
Owner Author

This is also related to a newly wanted feature of extracting variables at a fixed spatial location from slices, presumably in an unstructured mesh.

henry2004y added a commit that referenced this issue Jun 17, 2024
@henry2004y
Copy link
Owner Author

I found one solution using NaturalNeighbours.jl. It is about 10 times slower than Matplotlibs's triangular interpolation on a small dataset, but at least we have something in native Julia now.

@DanielVandH
Copy link

I found one solution using NaturalNeighbours.jl. It is about 10 times slower than Matplotlibs's triangular interpolation on a small dataset, but at least we have something in native Julia now.

You'll probably get a faster speed if you replace

Wi = [itp(x, y; method=Triangle()) for y in yi, x in xi]::Matrix{eltype(W)}
to instead be itp(x, y), where x and y are the vectors you're evaluating at, similar to what is done in the README https://github.com/DanielVandH/NaturalNeighbours.jl. You'll be able to hook into the multithreading that way.

@henry2004y
Copy link
Owner Author

I found one solution using NaturalNeighbours.jl. It is about 10 times slower than Matplotlibs's triangular interpolation on a small dataset, but at least we have something in native Julia now.

You'll probably get a faster speed if you replace

Wi = [itp(x, y; method=Triangle()) for y in yi, x in xi]::Matrix{eltype(W)}

to instead be itp(x, y), where x and y are the vectors you're evaluating at, similar to what is done in the README https://github.com/DanielVandH/NaturalNeighbours.jl. You'll be able to hook into the multithreading that way.

Thank you for your tips! I tried and it is indeed a bit faster, with 4 thread giving a speedup of ~ 2. However, the current way I did it requires extra array allocations:

function interpolate2d_generalized_coords2(X::T, Y::T, W::T,
   plotrange::Vector{<:AbstractFloat}, plotinterval::Real) where
   {T<:AbstractVector}
   xi = range(plotrange[1], stop=plotrange[2], step=plotinterval)
   yi = range(plotrange[3], stop=plotrange[4], step=plotinterval)
   itp = interpolate(X, Y, W)
   #Wi = [itp(x, y; method=Triangle()) for y in yi, x in xi]::Matrix{eltype(W)}
   Xi, Yi = Batsrus.meshgrid(xi, yi)
   x_ = vec(Xi)
   y_ = vec(Yi)
   Wi = itp(x_, y_; method=Triangle())

   xi, yi, Wi
end

which is something I may wish to avoid (say using LazyGrids.jl, but I haven't tried yet). However, even with multithreading it is still a bit slower than the Matplotlib triangulation interpolation implementation. Do you know the reason @DanielVandH ?

Here is a minimal working example for you to test:

using NaturalNeighbours
using StableRNGs
using PyPlot

function meshgrid(x, y)
   X = [x for _ in y, x in x]
   Y = [y for y in y, _ in x]

   X, Y
end

## The data 
rng = StableRNG(123)
f = (x, y) -> sin(x * y) - cos(x - y) * exp(-(x - y)^2)
x = vec([(i - 1) / 9 for i in (1, 3, 4, 5, 8, 9, 10), j in (1, 2, 3, 5, 6, 7, 9, 10)])
y = vec([(j - 1) / 9 for i in (1, 3, 4, 5, 8, 9, 10), j in (1, 2, 3, 5, 6, 7, 9, 10)])
z = f.(x, y)

## The interpolant and grid 
itp = interpolate(x, y, z; derivatives=true)
xg = LinRange(0, 1, 100)
yg = LinRange(0, 1, 100)
_x = vec([x for x in xg, _ in yg])
_y = vec([y for _ in xg, y in yg])

## Evaluate some interpolants 
triangle_vals = itp(_x, _y; method=Triangle())
println("NaturalNeighbours.jl:")
@time itp(_x, _y; method=Triangle());


triang = matplotlib.tri.Triangulation(x, y)
# Perform linear interpolation on the triangle mesh
interpolator = matplotlib.tri.LinearTriInterpolator(triang, z)
Xi, Yi = meshgrid(xg, yg)
Wi = interpolator(Xi, Yi)
println("Matplotlib:")
@time Wi = interpolator(Xi, Yi);
println("")

What I get is

NaturalNeighbours.jl:
  0.010370 seconds (37.41 k allocations: 1.056 MiB)
Matplotlib:
  0.000652 seconds (40 allocations: 80.031 KiB)

I will post an issue in your repo~

@DanielVandH
Copy link

which is something I may wish to avoid (say using LazyGrids.jl, but I haven't tried yet)

Yeah the need for vec is annoying. I could probably fix this at some point so that matrices can also be provided if I found the time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants