16
$\begingroup$

This is a related question to What's inside InterpolatingFunction[{{1., 4.}}, <>]? and Suppress extrapolation of interpolating function in a ContourPlot.

When interpolating a set of points, one might need to change the extrapolation behaviour, especially setting the function value to zero outside the original bounds of the data without reducing the performance time considerably.

It is possible to change the ExtrapolationHandler when a polynomial interpolation is performed as described in the answer by @Michael E2.

However, the same procedure does not work with spline interpolation (see the minimal code below).

Is there a way to change the default ExtrapolationHandler in spline interpolation?

Is it possible to change the default ExtrapolationHandler for all interpolating commands, like FunctionInterpolation, ListInterpolation, and BSplineFunction?

points = Transpose[{Range[0, 10*1.0]/10,RandomReal[{0, 10}, 10+1]}];
(* 10 points on x-axis from 0 to 1 with random numbers between 0 and     
  10 for the y-axis values *)

polyintpF = Interpolation[points, InterpolationOrder -> 2,
  "ExtrapolationHandler" -> {(0.0 &), "WarningMessage" -> False}];
(* polynomial interpolation of order 2 *)

splineintpF = Interpolation[points, Method -> "Spline",
  "ExtrapolationHandler" -> {(0.0 &), "WarningMessage" -> False}];
(* spline interpolation *)

polyintpF[2.0] (* gives zero as expected *)

(* extrapolates the function by the 'Automatic ExtrapolationHandler' ! *)
splineintpF[2.0] 
$\endgroup$

2 Answers 2

8
+500
$\begingroup$

A walk-around defining an intermediary function (you may want a macro instead):

Needs["DifferentialEquations`InterpolatingFunctionAnatomy`"];
makeNoExtrapFun[fun_, var_, def_] :=
 If[IntervalMemberQ[Interval@@InterpolatingFunctionDomain@fun, var],fun[var],def,def]

f = Interpolation[{1, 2, 1, 2, 1}, Method -> "Spline"];
k[x_] := makeNoExtrapFun[f, x, 0]
Plot[k@x, {x, 0, 8}]

Mathematica graphics

$\endgroup$
4
  • 1
    $\begingroup$ k[x] evaluates to 0. Perhaps IntervalMemberQ is not the best choice. I would do something like Piecewise[{{fun[var], LessEqual @@ Riffle[First[fun["Domain"]], var]}}, def] for the body of makeNoExtrapFun. $\endgroup$
    – Michael E2
    Apr 12, 2015 at 15:32
  • $\begingroup$ @MichaelE2 I used If[ ] just because of its fourth argument $\endgroup$ Apr 12, 2015 at 16:09
  • 1
    $\begingroup$ If vs. Piecewise is debatable. The main point is that IntervalMemberQ makes the function evaluate to def on non-numeric input. For instance, I'm not sure how to get the derivative of the function k[x] with D; I believe with my definition, both D[k[x], x] and k'[x] work. $\endgroup$
    – Michael E2
    Apr 12, 2015 at 16:16
  • $\begingroup$ @MichaelE2 Thanks! $\endgroup$ Apr 12, 2015 at 16:20
2
$\begingroup$

Recently, after trying several methods, I found that the following easy trick works the best and the fastest (in case of large number of function calls): Suppose that f is a deliberate interpolated function or spline (or B-spline),

(* note that 'points' cover the range [xmin, xmax]; see the original question above *)

splineintpF = Interpolation[points, Method -> "Spline"]; (* e.g., spline interpolation *)

f[x_] := 0.; (* first, define f for all x; this will be the 'extrapolation method' *) 
f[x_?(xmin <= # <= xmax &)] := splineintpF[x]; (* then, define f for x
     in the interpolated range [xmin, xmax] *)

Now, interpolation/extrapolation yields the expected result in the whole range of the variable, $(-\infty, +\infty)$. This works particularly faster than defining a Piecewise function -- as far as I could measure.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.