Look at Cookbook/Interpolation before reading this. SciPy probably has the interpolation functions you need.

Here are some homemade interpolating functions I use that may be usefull to others. They may still contain a lot of bugs, but...

   1 from numpy import *
   2 
   3 
   4 def interpn_nearest( z, targetcoords, bincoords=None ):
   5         '''Interpolate some data, z, located at bincoords in the target locations targetcoords
   6         using nearest neighbor interpolation.
   7                 z - is the data array
   8                 targetcoords - are the coordinates where we want to evaluate the data.
   9                         It must have a format so that z[targetcoords] would make sense
  10                         if targetcoords where integers.
  11                         mgrid and ogrid can be used to get such a format.
  12                 bincoords - is a list of arrays. Each array should containt.
  13         '''
  14         coords = interpn_check_data(z,targetcoords,bincoords)
  15         indices = [ c.round().astype('i') for c in coords ]
  16         return z[indices]
  17 
  18 
  19 def interpn_linear( z, targetcoords, bincoords=None ):
  20         '''Interpolate some data, z, located at bincoords in the target locations targetcoords
  21         using linear interpolation.
  22                 z - is the data array
  23                 targetcoords - are the coordinates where we want to evaluate the data.
  24                         It must have a format so that z[targetcoords] would make sense
  25                         if targetcoords where integers.
  26                         mgrid and ogrid can be used to get such a format.
  27                 bincoords - is a list of arrays. Each array should containt.
  28         '''
  29         coords = interpn_check_data(z,targetcoords,bincoords)
  30 
  31         indices = [ x.astype('i') for x in coords ]
  32         weights = [ x-i for x,i in zip(coords,indices) ]
  33 
  34         res = z[indices]*0
  35 
  36         for selector in ndindex( *z.ndim*(2,) ):
  37                 weight = 1
  38                 for w,s in zip(weights,selector):
  39                         if s: weight = weight*w
  40                         else: weight = weight*(1-w)
  41                 value = z[ [ i+s for i,s in zip(indices,selector) ] ]
  42                 res += weight*value
  43 
  44         return res
  45 
  46 
  47 
  48 def rebin( a, newshape ):
  49         '''Rebin an array to a new shape, without interpolation.
  50         This can be usefull if the array type is not a vector space.
  51         '''
  52         assert a.ndim == len(newshape)
  53 
  54         slices = [ slice(0,old, float(old)/new) for old,new in zip(a.shape,newshape) ]
  55         coordinates = ogrid[slices]
  56         indices = [ c.astype('i') for c in coordinates ]
  57         return a[indices]
  58 
  59 
  60 
  61 #################################
  62 ## more internal functions
  63 
  64 def array_coordinates( targetx, binx ):
  65         '''Computes the coordinates in an array reference.
  66                 targetx are the coordinates of the points that we want to get in the array reference.
  67                 binx    are the coordinates of the array bins
  68         Example:
  69                 >>> array_coordinates( [2, 10], [1, 3, 13] )
  70                 [0.5, 1.7]
  71         '''
  72         tol = 1e-12
  73         binx = asarray(binx)
  74         nx = clip( targetx, binx.min()*(1+tol), binx.max()*(1-tol) )
  75 
  76         i = searchsorted( binx, nx )      # index of the biggest smaller bin
  77 
  78         bx = empty((len(binx)+2,), 'd')   # avoid probles at the border
  79         bx[0] = binx[0] - 1
  80         bx[1:-1] = binx
  81         bx[-1] = binx[-1] + 1
  82 
  83         return i-1 + ( nx - bx[i] )/( bx[i+1] - bx[i] )
  84 
  85 
  86 def interpn_check_data( z, targetcoords, bincoords ):
  87         '''Check the validity of the input data for intepn_x functions
  88         and returns the target coordinates in the array reference
  89         '''
  90         dim = z.ndim
  91         if bincoords:
  92                 if len(bincoords) != dim:
  93                         raise ValueError, 'bincoords shape mismatch.'
  94                 for i in range(dim):
  95                         if prod(bincoords[i].shape) != z.shape[i]:
  96                                 raise ValueError, 'bincoords shape mismatch.'
  97 
  98                 coords = [ array_coordinates(targetcoords[i],bincoords[i].ravel()) for i in range(dim) ]
  99         else:
 100                 coords = targetcoords
 101         return coords
 102 
 103 
 104 def interp2_linear( z, tx, ty, binx=None, biny=None  ):
 105         '''Toy function just like interpn_linear in 2 dimensions.
 106         This function exists just to help the understanding and mantaining of interpn_linear.
 107         '''
 108         if not binx is None: tx = array_coordinates( tx,binx )
 109         if not biny is None: ty = array_coordinates( ty,biny )
 110 
 111         ix = tx.astype('i')
 112         iy = ty.astype('i')
 113         wx = tx-ix
 114         wy = ty-iy
 115 
 116         return    (1-wy)*(1-wx) * z[iy  ,ix  ] \
                + (1-wy)*   wx  * z[iy  ,ix+1] \
                +    wy *(1-wx) * z[iy+1,ix  ] \
                +    wy *   wx  * z[iy+1,ix+1]
 117 
 118 
 119 
 120 
 121 
 122 
 123 ###########################################
 124 ## some visual testing
 125 ##
 126 import pylab
 127 
 128 def test():
 129         x,y = ogrid[ -1:1:10j, -1:1:10j ]
 130         z = sin( x**2 + y**2 )
 131 
 132         binx = (x,y)
 133         tx = ogrid[ -2:2:100j, -2:2:100j ]
 134 
 135         pylab.subplot(221)
 136         pylab.title('original')
 137         pylab.imshow(z)
 138         pylab.subplot(223)
 139         pylab.title('interpn_nearest')
 140         pylab.imshow( interpn_nearest( z, tx, binx ) )
 141         pylab.subplot(222)
 142         pylab.title('interpn_linear')
 143         pylab.imshow( interpn_linear( z, tx, binx ) )
 144         pylab.subplot(224)
 145         pylab.title('interp2_linear')
 146         pylab.imshow( interp2_linear( z, tx[0],tx[1], x.ravel(),y.ravel() ) )
 147         pylab.show()

PauGargallo/Interpolation (last edited 2006-05-30 14:36:30 by PauGargallo)