Skip to content
wpietri edited this page Sep 26, 2014 · 6 revisions

Interpolation

breeze.interpolation module currently supports interpolation facilities for data in one dimension (univariate interpolation). At this moment, there is only linear and cubic univariate interpolation available, but you are encouraged to contribute to Breeze and write other interpolators like quadratic, nearest and zero interpolators, as well as multivariate interpolation.

All examples in this document assumes that you've imported necessary modules:

scala> import breeze.interpolation._

1D interpolation

1D (univariate) interpolators gets the coordinates of nodes. One vector for each coordinate is required:

scala> val x = DenseVector(0.0, 1.0, 2.0, 3.0)
scala> val y = DenseVector(2.0, 4.0, 8.0, 5.0)
scala> val f = LinearInterpolator(x, y)

The interpolator returns an interpolating function. You can ask for the value at given point:

scala> f(2.5)
6.5

If the coordinate is not in the interpolation range, the result will be extrapolated.

The function is an universal function, so you can also pass an vector or matrix or any other iterable object:

scala> f(DenseVector(1.0, 1.25, 1.5))
DenseVector(4.0, 5.0, 6.0)

There is also CubicInterpolator implementing spline interpolation of third order. It doesn't support extrapolation and throws an OutOfTheBoundsException if you pass an argument that is not in the interpolation range.

Writing your own 1D interpolator

There are two ways to write your own univariate interpolator. The simpler but more rigid one is to extend the HandyUnivariateInterpolator and pass it vector of x and y coordinates. You need to implement only interpolate(x) method where you can assume that the argument x is in the interpolation range (so it's between the minimum and maximum of x coordinates):

class MyInterpolator (x_coords: Vector[Double],
                      y_coords: Vector[Double])
                     extends HandyUnivariateInterpolator(x_coords, y_coords) {
  override protected def interpolate(x: Double): Double = ...
}

HandyUnivariateInterpolator validates x_coords and y_coords coordinates and creates X and Y arrays sorted by X coordinate. You can access this members inside interpolate method or anywhere inside the class.

You can also override extrapolate method that is called when the argument is not in the range. By default, this method raises an OutOfTheBoundsException.

If you don't want to distinguish between interpolation and extrapolation, you can override the public apply method. The default implementation is:

def apply(x: T): T = {
  if (x < X(0) || x > X(X.size - 1))
    extrapolate(x)
  else
    interpolate(x)
}

The second way is more flexible. You only need to extend UnivariateInterpolator trait and implement apply(x) method. You are on your own to validate the x argument.

class DummyInterpolator() extends UnivariateInterpolator {
  def apply(x: Double): Double = 0
}

No matter which way you implement your interpolator, it's always an universal function and, therefore, it automatically plays well when you pass an vector or matrix instead of a plain double.