Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I am interpolating a lot of data over geographic coordinates obtained via GPS, and frequently I need to plot these interpolated functions together. For example, I may have an interpolated elevation map that looks like this:

f0 = InterpolatingFunction[{{x0min, x0max},{y0min, y0max}}, <>]

and several other interpolated functions of other data sets that stretch over subregions of the rectangle {{x0min, x0max}, {y0min, y0max}}. So, say,

f1 = InterpolatingFunction[{{x1min, x1max},{y1min, y1max}}, <>]

where {{x1min, x1max}, {y1min, y1max}} lies entirely within {{x0min, x0max}, {y0min, y0max}} and so on.

I need to plot these interpolated functions A LOT and in attempts to change the visualisations of my data sets, I need an efficient way to extract their limits and pass them on to plotting functions. For this I have written the following function:

intLimits[intF_ /; (Head@intF === InterpolatingFunction), x_: x, y_: y] := 
     Module[{ArgList},
        ArgList = First@intF;
        Which[Length@ArgList < 2,
              ArgList~Prepend~x,
              Length@ArgList == 2,
              {First@ArgList~Prepend~x, Last@ArgList~Prepend~y}
        ]
      ]

which I use with plotting functions like so

f0plot= Plot3D[f0[x,y], Evaluate@First@intLimits[f0], Evaluate@Last@intLimits[f0]];
f1plot= Plot3D[f1[x,y], Evaluate@First@intLimits[f1], Evaluate@Last@intLimits[f1]];

This works well if used to plot a list of interpolation functions (replacing f0 with # and mapping at the list) but it seems a bit ugly and the length of adding Evaluate@First@intLimits doesn't help with the readability of my notebook although seems necessary given the HoldAll Attribute of all plotting functions.

So my question is: is there a more clever way to define the function intLimits or a better way in general to be able to pass on the range of variables of interpolated functions to plotting functions?

share|improve this question
1  
Why not writing your own plotting function, where you can implement any short-cuts you want? –  Leonid Shifrin Jan 29 '13 at 14:17
    
You can change to Sequence@@{First@ArgList~Prepend~x, Last@ArgList~Prepend~y} and then Plot3D[f0[x, y], Evaluate@intLimits[f0]], should at least save your fingers a little bit (and also confuse the syntax highlighter) –  ssch Jan 29 '13 at 14:44
    
There are several ways to probe the internals of an InterpolatingFunction as outlined in this answer. –  rcollyer Jan 29 '13 at 14:55

2 Answers 2

up vote 5 down vote accepted

Ok, here is one possibility out of many.The following is a function generator:

ClearAll[generate3DPlottingFunction]
generate3DPlottingFunction[fname_Symbol, builtin_Symbol] :=
  Block[{x, y},
     ClearAll[fname];
     fname::no2D = 
         "A function `1` does not represent a 2-dimensional interpolation";
     fname[f_InterpolatingFunction, x_Symbol: x, y_Symbol: y, opts : OptionsPattern[]] :=
       With[{limits = intLimits[f, x, y]},
          With[{fst = First@limits, sec = Last@limits},
             builtin[f[x, y], fst, sec, Evaluate@ FilterRules[{opts}, Options[builtin]]]
          ] /; Length[limits] == 2
       ];
     fname[f_InterpolatingFunction, x_Symbol: x, y_Symbol: y] :=
        (Message[fname::no2D, f]; $Failed);
     fname[___] := $Failed
 ]

Now you can generate the custom functions:

generate3DPlottingFunction[plot3DInterpolated, Plot3D]
generate3DPlottingFunction[contourPlotInterpolated, ContourPlot]

Here is some test function:

testF = 
 Interpolation[
   Flatten[
      Outer[{#1, #2, Sin[#1*#2]} &, Range[0, 2 Pi, 0.1],Range[0, 2 Pi, 0.1]], 
      1
   ]]

Now,

plot3DInterpolated[testF]

enter image description here

contourPlotInterpolated[testF]

enter image description here

share|improve this answer
    
Thanks for your comment and the answer! I thought about making my own function but I would have to make one for each of Plot3D, ContourPlot and so on and also is there a safe way to add an argument to pass options to the function, like options___?RuleQ? Cause my fear of screwing that up is what stopped me in the first place. –  gpap Jan 29 '13 at 15:00
    
Passing on options seems to be as easy as adding an options___OptionQ argument so disregard the previous comment. Thanks again –  gpap Jan 29 '13 at 15:12
    
@gpap Yes, this is all possible. See my edit for details. –  Leonid Shifrin Jan 29 '13 at 15:15
    
@rm-rf Thanks, got it –  Leonid Shifrin Jan 30 '13 at 22:04

I find that the implementation of intLimits[] in the OP is a tad too cumbersome for my taste. It is apparently not too well known that InterpolatingFunction[] objects in Mathematica are set up such that one can extract a number of useful properties from them (I see that rcollyer has alluded to them in a comment). To wit, here's a vastly simpler way to write intLimits[]:

intLimits[intF_InterpolatingFunction, x_Symbol: x, y_Symbol: y] :=
   Join[{{x}, {y}}, intF["Domain"], 2]

One can indeed pass on implementing intLimits[] as a separate function, and just implement a plotting function directly:

interpolantPlot[intFun_InterpolatingFunction, plotFun_Symbol, opts___] := 
     plotFun[intFun[\[FormalX], \[FormalY]], ##, 
             Evaluate[Sequence @@ FilterRules[{opts}, Options[plotFun]]]] & @@
     Join[{{\[FormalX]}, {\[FormalY]}}, intFun["Domain"], 2] /; 
     MatchQ[plotFun, Plot3D | ContourPlot | DensityPlot]

Test it out:

testF = ListInterpolation[Table[Sin[x + Sin[y]], {x, 0, 2 Pi, Pi/30}, {y, 0, 2 Pi, Pi/30}],
                          {{0, 2 Pi}, {0, 2 Pi}}];

interpolantPlot[testF, Plot3D, BoundaryStyle -> Gray, Mesh -> False]

three-dimensional plot

interpolantPlot[testF, ContourPlot, ColorFunction -> "ThermometerColors",
                ContourStyle -> Directive[Gray, Dashed]]

contour plot

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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