diff numerics/interpolation.py @ 4:097296d6132e

add interpolation
author Jeff Hammel <k0scist@gmail.com>
date Thu, 04 Sep 2014 08:21:10 -0700
parents
children 7517682843cb
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/numerics/interpolation.py	Thu Sep 04 08:21:10 2014 -0700
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+
+
+"""
+interpolation
+"""
+
+__all__ = ['neighbors', 'linear_interpolation']
+
+def neighbors(start, finish):
+    """
+    returns the neighbors in finish from start
+    assumes both are sorted
+    """
+    assert finish
+    index = 0
+    retval = []
+    for x in start:
+        # endpoints
+        if x < finish[0]:
+            retval.append((None, 0))
+            continue
+        if x > finish[-1]:
+            retval.append((len(finish)-1, None))
+            continue
+        # traverse
+        try:
+            while True:
+                if x < finish[index] or x > finish[index+1]:
+                    index += 1
+                    continue
+                else:
+                    break
+            retval.append((index, index+1))
+        except IndexError:
+            retval.append((len(finish)-2, len(finish)-1))
+
+    return retval
+
+
+def linear_interpolation(data, points):
+    """
+    linearly interpolate data to points
+
+    data -- iterable of 2-tuples (or equivalent) of `x,y`
+    points -- `x`-values to interpolate to
+    """
+
+    # ensure we are sorted
+    data = sorted(data, key=lambda x: x[0])
+    points = sorted(points)
+
+    # get the neighbors
+    x = [value[0] for value in data]
+    nearest_neighbors = neighbors(points, x)
+
+    # we don't support endpoints yet; this is interpolation, not extrapolation
+    assert not any([(neighbor[0] is None or neighbor[1] is None)
+                    for neighbor in nearest_neighbors])
+
+    retval = []
+    for index, (left, right) in enumerate(nearest_neighbors):
+        # linearly interpolate
+        ratio = (points[index] - data[left][0])/float(data[right][0] - data[left][0])
+        retval.append(ratio*data[right][1] + (1.-ratio)*data[left][1])
+    return retval
+
+