MathGroup Archive 1995

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Extracting data points from Plot[]

> The Plot[] function does some intelligent picking of points, such that  
> usually does a pretty good job of following twists and turns in a  
> without plotting an excessive number of points. I'm not ecstatic about
> using Mma for final output, though, so I like to export these curves to  
> graphing program.


> What I'm wondering, though, is if there isn't something a bit more
> straightforward than "InputForm[%1][[1]][[1]][[2]][[1]][[1]][[1]]" to  
> at the data points?  Is there a way to generate these data series the  
> Plot[] does, without using Plot (which necessitates stripping off the
> "Graphics" and "Line" structures which make up the bulk of the
> sub-sub-sub-arrays that I'm referencing).

Fortunately, there is no need to try to pin-point the Line structures

   One thing you can do is save the samples that Plot chooses by appending
each one to some list.  If you're plotting f[x] on the interval [a, b]
you can do:

samples = {}

Plot[ (AppendTo[samples, {x, f[x]}]; f[x]), {x, a, b},
  DisplayFunction->Identity ];

Now 'samples' will contain all the sample points that Plot generated
while working toward a Plot, and in the same order in which Plot
generated them.  Since Plot uses an adaptive sampling routine that
sometimes goes back over an interval and samples it more finely,
the list of points in 'samples' may not always progress from left
to right.  Don't forget to include "samples = {}" in each evaluation
you do, otherwise 'samples' will keep accumulating points from previous

(This method is given in the Course Notes _Numerical Computation in
Mathematica_ by Jerry Keiper and Dave Withoff, on page 1.  It is
also given, in the context of a thorough description of Plot's adaptive
sampling, in Tom Wickham-Jones' book _Mathematica Graphics:  Techniques
& Applications_, p. 583.  The same method can be used for other iterative
commands like NIntegrate and FindRoot)

If f is expensive to compute, then you may not want to evaluate it
twice like I did above.  You can use a pure function that will put
f[x] to use twice, once for the AppendTo that does the record-keeping,
and once as the return value of the whole function:

Plot[ (AppendTo[samples, {x, #}]; #)& [ f[x] ], {x, a, b},
  DisplayFunction->Identity ];

This gives up some simplicity of appearance for efficiency when the latter
is more important.

   This will give you the entire set of values that Plot _tried_
in the course of sampling, but sometimes Plot will throw out points,
say if the function doesn't evaluate to a real number at some of them.
For instance, Sqrt[x^2 - 4] isn't real on (-2, 2), so if you plot it
on [-3, 3], there will be two disconnected curves, hence two separate
Line objects.  You can use Cases to find the Line objects and pull out
their points, without having to know exactly where they are in
the Graphics expression.

In[60]:= p = Plot[Sqrt[x^2 - 4], {x, -3, 3}]

   [... error messages deleted ...]

Out[60]= -Graphics-

In[61]:= subcurves = Cases[First[p], Line[pts_List] :> pts, -1]

{{{-3., 2.23607}, {-2.75, 1.88746}, {-2.5, 1.5}, {-2.375, 1.28087}, 
   [ ...some lines deleted... ]
   {2.25, 1.03078}, {2.5, 1.5}, {2.75, 1.88746}, {3., 2.23607}}}

If the function is well-behaved throughout the interval and there is just
one Line object, then First[subcurves] will give you a list of pairs.

Really, 'Cases' is a general command to extract all pieces of an
expression that have a certain structure or possess certain properties;
this is just one small application.  See p. 221 of The Mathematica Book
for more on it.

Robby Villegas

  • Prev by Date: CHAOS & MATH
  • Next by Date: Re: Some Mathematica-related URL's
  • Previous by thread: Re: Extracting data points from Plot[]
  • Next by thread: Re: Extracting data points from Plot[]