MathGroup Archive 1995

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

Search the Archive

More on "Extracting data points from Plot[]"

  • To: mathgroup at christensen.cybernetics.net
  • Subject: [mg959] More on "Extracting data points from Plot[]"
  • From: cameron <cameron at dnaco.net>
  • Date: Thu, 4 May 1995 03:14:11 -0400

Mathgroupers--

Another post in regard to the subject of using Plot to sample functions.

In the development of "The Mathematica Graphics Guidebook", a great deal
of material was generated over and above what appeared in the finished
book.  The project ran enormously over schedule, and we reached a point
at which we decided it was better to call a halt and publish a book than
to continue making incremental improvements and never get done at all.
So we drew a line between core material and nonessential embellishments,
polished up the core material, and published it.

However, there is much of value in the 150 pages or so of remaining
material, even though it was never brought up to publishable form.
Coincidentally, one of the examples that got eliminated is the use of
Plot and ParametricPlot to sample functions without making a graph --
the same problem that has recently been discussed in this forum.

I have attached below an "outtake" from "The Mathematica Graphics Guidebook",
in which we define the AdaptiveSample[] function.  Share and Enjoy!

Best regards--
--Cameron Smith
  co-author (with Nancy Blachman) of "The Mathematica Graphics Guidebook"

P.S. Some of the outtake material from the Guidebook may yet see the light
     of day, in "The Mathematica Graphics Cookbook".  This work -- if we
     decide to go ahead with it -- would be a companion to the Guidebook.
     The idea is that the Guidebook is a reference work explaining the
     concepts underlying Mathematica's graphics model, and the Cookbook
     would be a compendium of useful examples illustrating the practical
     use of the model; the relationship would be similar to that between
     the original PostScript Red and Green books.

---------------------------------------------------------------------
The text below is copyright (c) 1995 by Cameron Smith.
All rights are reserved.  Permission is granted to use the Mathematica
code for the AdaptiveSample[] function for any purpose, without fee,
at the user's own risk.  No warranty, express or implied, is offered.
---------------------------------------------------------------------

The adaptive sampling routine used by Plot and ParametricPlot
has other uses besides graphing functions -- for example, in certain
numerical work it would be nice to be able to say

AdaptiveSample[ f, { x, min, max } ]

to produce a list of (x,f(x)) pairs with f sampled more densely in
intervals over which it is less linear.  Mathematica doesn't give us
this direct access to its sampling algorithm, but since we know the
structure of the graphics objects that Plot and ParametricPlot create,
it isn't too hard to write.  We simply use one of the plotting
functions to prepare a graph of the function, then extract the list of
points from the graph and throw the rest away.  Here is Mathematica
code that does this:

SetAttributes[AdaptiveSample,HoldAll];

AdaptiveSample[ f_, {var_, min_, max_}, opts___ ] :=
Block[ { plot, cmp, pts, bend, div, sampler },
   sampler = Plot;
   If[ MatchQ[ Hold[f], Hold[{_,_}] ], sampler = ParametricPlot ];
   {cmp, pts, bend, div} =
      {Compiled,PlotPoints,MaxBend,PlotDivision} /. {opts} /. Options[sampler];
   plot = sampler[ f, {var,min,max},
            Compiled -> cmp, PlotPoints -> pts, MaxBend -> bend,
            PlotDivision -> div, Axes -> None, Frame -> False,
            DisplayFunction -> Identity, Prolog -> {}, Epilog -> {} ];
   First /@ Cases[ First[plot], _Line, Infinity ]
]

What's going on here?  The SetAttributes command ensures that
AdaptiveSample, like Plot and ParametricPlot, defers evaluation of its
arguments.  In the body of the function, the first thing we have to do
is to decide whether to use Plot or ParametricPlot, and we make that
choice by examining the first argument: if we were given a pair of
functions, we use ParametricPlot, otherwise we use Plot.
Next we process the optional arguments, obtaining settings for the four
options that control the sampling mechanism (Compiled, PlotPoints,
MaxBend, and PlotDivision), and using the default value for each option
if no explicit setting was provided.  Then we construct a graphics
object, setting other options (such as Axes and DisplayFunction) to
reduce the amount of unnecessary work done (no point in constructing
axes if we aren't going to look at the plot anyway) and to ensure that
the graphic isn't displayed.  Finally, we extract the Line objects from
the list of graphics primitives in the plot, and extract the lists of
points from the Line objects.

Note that the result of AdaptiveSample is a list of lists of
points, rather than simply a list of points.  This is necessary,
because the result of Plot or ParametricPlot can be a collection
of disjoint Line objects.  The plotting functions break up their
results this way when they detect one or more discontinuities in
their arguments, and we want to preserve this information.
Here's an illustration of this phenomenon:

badfunction[x_] := Which[ x<1, 1, x>2, 2, True, Null ]

AdaptiveSample[ badfunction[x], {x,0,3}, PlotPoints -> 10 ]

Plot::plnr: CompiledFunction[{x}, <<1>>, -CompiledCode-][x]
     is not a machine-size real number at x = 1..

Plot::plnr: CompiledFunction[{x}, <<1>>, -CompiledCode-][x]
     is not a machine-size real number at x = 1.33333.

Plot::plnr: CompiledFunction[{x}, <<1>>, -CompiledCode-][x]
     is not a machine-size real number at x = 1.66667.

General::stop: 
   Further output of Plot::plnr
     will be suppressed during this calculation.

{{{0., 1.}, {0.333333, 1.}, {0.666667, 1.}, {0.833333, 1.}, 
 
   {0.916667, 1.}, {0.958333, 1.}, {0.979167, 1.}, {0.989583, 1.}}, 
 
  {{2.01042, 2.}, {2.02083, 2.}, {2.04167, 2.}, {2.08333, 2.}, 
 
   {2.16667, 2.}, {2.33333, 2.}, {2.66667, 2.}, {3., 2.}}}

Still, it is true that the result of AdaptiveSample will usually be
a list containing a single list of points -- this will always be the
case if the function being sampled is continuous over the sampling
interval, and will usually be true even if it is not, since the odds
are small that the sampler will try to sample a function exactly at
an isolated point of discontinuity.

----------------------------------------------------------------------


  • Prev by Date: Re: Kernel configuration for DEC Alpha on VMS
  • Next by Date: Re: DAE Solver in Mathematica?
  • Previous by thread: Re: Galois package for Mathematica
  • Next by thread: Re: DAE Solver in Mathematica?