CoryKramer CoryKramer - 1 month ago 8
Python Question

Interpolate class objects

I have a simple

Point
class as follows

class Point(object):
def __init__(self, x=0.0, y=0.0, z=0.0):
self.x = x
self.y = y
self.z = z


I would like to use
scipy.interpolate.interp1d
to interpolate these points as a function of time, e.g.

x,y,z = f(t)


However when I try the following small example

import numpy as np
from scipy.interpolate import interp1d

times = np.array([0.0, 0.1, 0.2])
points = np.array([Point(0.0, 0.0, 0.0),
Point(1.0, 1.0, 1.0),
Point(2.0, 2.0, 2.0)])

function = interp1d(times, points)

new_point = function(0.05)


I get the following error

Traceback (most recent call last):
File "D:/example.py", line 31, in <module>
function = interp1d(times, points)
File "C:\long_path\scipy\interpolate\interpolate.py", line 439, in __init__
y = y.astype(np.float_)
TypeError: float() argument must be a string or a number, not 'Point'


I've also tried overloading the arithmetic operators for the
Point
class (e.g.
__add__
,
__sub__
,
__truediv__
) though that doesn't seem to help.

Is there a way I can use
scipy.interpolate.interp1d
with my class?

Answer

Since python object are internally dicts instead of contiguous buffer, numpy/scipy will fail to use certain methods when custom typed objects are inside numpy.ndarray.

A simple solution would be putting all Point inside one single ndarray with built-in type:

from __future__ import print_function
import numpy as np
import scipy.interpolate as sp_interp
points = np.array([[0.0, 0.0, 0.0],
                   [1.0, 1.0, 1.0],
                   [2.0, 2.0, 2.0]], dtype='float64')
times = np.linspace(0.,.2, len(points))

fn_interp = sp_interp.interp1d(times, points, axis=0)
print(fn_interp(0.05))

If you are dedicated to class based approach, you might want to define custom dtype or make subclass of ndarray, as answered here

Comments