views:

143

answers:

4

So, I have three numpy arrays which store latitude, longitude, and some property value on a grid -- that is, I have LAT(y,x), LON(y,x), and, say temperature T(y,x), for some limits of x and y. The grid isn't necessarily regular -- in fact, it's tripolar.

I then want to interpolate these property (temperature) values onto a bunch of different lat/lon points (stored as lat1(t), lon1(t), for about 10,000 t...) which do not fall on the actual grid points. I've tried matplotlib.mlab.griddata, but that takes far too long (it's not really designed for what I'm doing, after all). I've also tried scipy.interpolate.interp2d, but I get a MemoryError (my grids are about 400x400).

Is there any sort of slick, preferably fast way of doing this? I can't help but think the answer is something obvious... Thanks!!

A: 

I suggest you taking a look at GRASS (an open source GIS package) interpolation features (http://grass.ibiblio.org/gdp/html_grass62/v.surf.bspline.html). It's not in python but you can reimplement it or interface with C code.

Vitor Py
Hmm, that certainly looks nice, though a bit of work to reimplement! I'll be looking into it. Thanks!
A: 

Am I right in thinking your data grids look something like this (red is the old data, blue is the new interpolated data)?

alt text

This might be a slightly brute-force-ish approach, but what about rendering your existing data as a bitmap (opengl will do simple interpolation of colours for you with the right options configured and you could render the data as triangles which should be fairly fast). You could then sample pixels at the locations of the new points.

Alternatively, you could sort your first set of points spatially and then find the closest old points surrounding your new point and interpolate based on the distances to those points.

Jon Cage
Right idea with the grid, though I'm actually tracking the properties of a virtual particle as it travels through the mesh, so the blue dots should look more like a trail of breadcrumbs:![mesh](http://i276.photobucket.com/albums/kk31/account321/DataSeparation.png)Hopefully that picture works. The image rendering idea is interesting -- I do have the PIL available, so I may give it a go. Thanks!
+1  A: 

There's a bunch of options here, which one is best will depend on your data... However I don't know of an out-of-the-box solution for you

You say your input data is from tripolar data. There are three main cases for how this data could be structured.

  1. Sampled from a 3d grid in tripolar space, projected back to 2d LAT, LON data.
  2. Sampled from a 2d grid in tripolar space, projected into 2d LAT LON data.
  3. Unstructured data in tripolar space projected into 2d LAT LON data

The easiest of these is 2. Instead of interpolating in LAT LON space, "just" transform your point back into the source space and interpolate there.

Another option that works for 1 and 2 is to search for the cells that maps from tripolar space to cover your sample point. (You can use a BSP or grid type structure to speed up this search) Pick one of the cells, and interpolate inside it.

Finally there's a heap of unstructured interpolation options .. but they tend to be slow. A personal favourite of mine is to use a linear interpolation of the nearest N points, finding those N points can again be done with gridding or a BSP. Another good option is to Delauney triangulate the unstructured points and interpolate on the resulting triangular mesh.

Personally if my mesh was case 1, I'd use an unstructured strategy as I'd be worried about having to handle searching through cells with overlapping projections. Choosing the "right" cell would be difficult.

Michael Anderson
+1: ..for the mention of BSP trees and generally putting my what I was getting at more elequently than I managed :-) You could form the BSP by centering each BSP node on one of the new data points and then simply drilling down to find all the neighbouring points.
Jon Cage
Nice! The consensus seems to be that I'm going to have to work at this a bit, but that's okay. I do like your suggestion of a BSP technique... Thanks a lot!
+1  A: 

Try the combination of inverse-distance weighting and scipy.spatial.KDTree described in SO inverse-distance-weighted-idw-interpolation-with-python. Kd-trees work nicely in 2d 3d ..., inverse-distance weighting is smooth and local, and the k= number of nearest neighbours can be varied to tradeoff speed / accuracy.

Denis
You, my friend, are a genius. That KDTree class is brilliant! Exactly what I needed...
I had some troubles with using vanilla inverse weighting. Found that it had some serious artifacting when the sample point was outside a cluster of points. I over came this by fitting a linear approximation (instead of a constant approximation) to the weighted data for the N-nearest neighbours. This produced pretty good results with the same amount of searching, just the overhead of solving a NxN linear system.
Michael Anderson
@Michael, is your data 2d, how scattered, what's Nnear ? Could you give an example of distances and values that misbehave ? E.g distances 1 1 1 1 1 10, values 1 1 1 1 1 10 => interpolate (6 / 5.1) = 1.18.Also, NxN ? In 2d, fitting a plane ax + by + c to N points (with weights say 1/dist) is either numpy.linalg .lstsq Nx3 or .solve 3x3 .
Denis
My data was 3D, but the problem occurs even in 1D. Take N=3 with linear data (1,1) (2,2),(3,3), sample at 2.5 and you get a result of about 2.3 (an under estimate by 10%). Things are worse if we estimate at 3.5, producing a value near 2.5 instead of the "real" 3.5 . Some will say we're now doing extrapolation rather than interpolation, but if our data points are at 1,2,3,10 then 1,2,3 are still the three closest points to 3.5 .. and we'd end up with the same result. This is what I mean by values outside of clusters. Fitting a line gives the "right" result - at least for my data
Michael Anderson
Michael, ok, nice. (Extrapolation is often wrong -- no way to tell what's "right".)
Denis