Mercurial > hg > numerics
changeset 4:097296d6132e
add interpolation
author | Jeff Hammel <k0scist@gmail.com> |
---|---|
date | Thu, 04 Sep 2014 08:21:10 -0700 |
parents | 690778ffd302 |
children | d5447d401c44 |
files | numerics/interpolation.py |
diffstat | 1 files changed, 68 insertions(+), 0 deletions(-) [+] |
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 + +