Copyright (C) 1997 Rich Neidinger, John Swallow, and Todd Will.  Free for
distribution to college and university instructors for personal,
non-commercial use.  If these notebooks are used in a course, the authors
request $20 per student.

Chapter IX.  Special Topics

27. Fits and Graphics

Last revision:  October 16 1996

In this last section, we explore Mathematica's graphics commands and "Fit[
]" function.

Fits

Back in the Classroom

Suppose, as we did earlier in the course, that an instructor likes to ask
students in a class for answers to homework questions.  If the instructor
asks for answers to "n" questions, and there are "m" students in the class,
how many different students are likely to be called on?  We can attempt to
decide by writing a Mathematica function which mimics this classroom
situation.

roster={"Andrews","Biber","Chase","Cowles",
"Dearing","Elzayadi","Ferrentino","Hsieh","Jones",
"Kavanagh","Minlend","Montague","Peay","Smith",
"Sparks","Stovesand","Symes","Talvacchio"};
numStudents = Length[roster];

Clear[draw,numQuestions]
draw[numQuestions_] := Length[
   Union[
     Table[
        roster[[ Random[Integer,{1,numStudents}] ]],
        {numQuestions}
     ]
   ]
]

Clear[aveDraw,numCalled,trials]
aveDraw[numCalled_,trials_] :=
   N[ Sum[draw[numCalled],{trials}]/trials ]

The numeric answer may be interesting in its own right, but we may learn
more about the function by finding a graphical representation of the
function.  We can do so by using "ListPlot[ ]".  We'll plot the number of
questions asked on the x-axis and the resulting average number of different
students called upon on the y-axis.

aveData = Table[
  {numQuestions, aveDraw[numQuestions,5]},
  {numQuestions,1,100}] ;

dataPlot = ListPlot[aveData]

Unfortunately, on some monitors, the default plot size makes the points too
small to see.  If this is true on your monitor, read the rest of the
paragraph; otherwise, you may want to skip it.  One solution is to use the
option "Prolog->PointSize[.02]" in the "ListPlot[ ]" call (making it a
final parameter), but we must keep in mind that the "PointSize" parameter
affects different monitors and printers to differing amounts, so that if
we're not careful, the points will print out much larger than they appear
on the screen.  Another solution is simply to expand the graphic:  click on
the graphic, grab a corner, and drag it to a larger size.  (Note: graphics
take up lots of space in on your disk, so you may want to delete cells with
graphics before saving.)

After looking at a plot of the data, we may believe that some function
approximates the values.  We search for such a function below.

Finding an Analytic Function to Match the Data

What we'd like to do now is "fit" a curve or function to the data in the
list "aveData".  In other words, we would like to determine an analytic
function, say polynomial, trigonometric, or otherwise, which will match the
data points we have.   We might use the function later to guess what some
values of data would be, say with a number of questions too large to give
to our "aveDraw" function.  The Mathematica function needed is the function
"Fit[ ]".

?Fit

We'll feed the Fit function our list of x-y pairs, a list of "building
functions", and the variable we want to use for the function.  Mathematica
is allowed to choose any sum of any multiples of the function when finding
the "best fit"; i.e., if the building functions are "{f[x], g[x], h[x]}",
then "Fit[ ]" finds the best curve of the form "a f[x] + b g[x] + c h[x]",
where "a", "b", and "c" are numbers.

fitter[x_] = Fit[aveData,{1,x,x^2},x]

Here, given building functions "1", "x", and "x^2", the "Fit[ ]" command
finds the best coefficients of all possible curves of the form a*(1) +
b*(x) + c*(x^2), i.e. of all possible parabolas.  When your instructor ran
this command the result was the sum of 3.82261*(1), .450069*(x), and
-.00305751*(x^2). You may find slightly different results because we used
the "Random[]" function in creating the list "aveData".   Let's look at the
plot.

fitterPlot = Plot[ fitter[x],{x,1,100}]

This doesn't look too much like our previous plot, but one problem is that
not the entire graph was shown.  To see the complete graph we need to add
the option "PlotRange->All".

Clear[fitterPlot]
fitterPlot = Plot[fitter[x],{x,1,100},
                  PlotRange->All]

This looks a little closer, but let's see how it holds up when we show the
function and the data together.

Show[fitterPlot,dataPlot]

That's not too bad, but we can do better by giving the "Fit[ ]" command
more "building functions" with which to construct the approximating
function.

Clear[fitter,fitterPlot]

fitter[x_]=Fit[aveData,{1,x,x^2,x^3},x]

fitterPlot=Plot[ fitter[x],{x,1,100},
        PlotRange->All]

Show[fitterPlot,dataPlot]

The real trick to using the "Fit[ ]" function is in finding good building
functions to use.  By doing many experiments, one finds that the "Fit[ ]"
function does very well when given {1,x,1/(x+20)} as building functions.

Clear[fitter,fitterPlot]
fitter[x_]=Fit[aveData,{1,x,1/(x+20)},x]
fitterPlot=Plot[fitter[x],{x,1,100},
        DisplayFunction->Identity]
Show[dataPlot,fitterPlot,
 DisplayFunction->$DisplayFunction]

Note:  the option "DisplayFunction->Identity" suppresses the output of the
"Plot[ ]" function,
and "DisplayFunction->$DisplayFunction" forces the output to appear.
(Sometimes this last expression is unnecessary, but remembering to use it
when "DisplayFunction->Identity" is used is wise.)

Graphics, Primitives

Showing by Doing, Doing by Showing

We will build up the pieces of this picture one at a time and then use
"Show[ ]" to display them at the same time.  First, we must tell
Mathematica that we will need the package of color definitions.  This
command should be executed only once, before any other cells using color
names are executed, so that no color names will be defined in the "Global`"
context before these definitions are executed.

Needs["Graphics`Colors`"]

If we want to see all the colors we can use, we can execute the following cell.

?Graphics`Colors`*

In order to create the red triangle, we will use our first graphics
primitive.  A graphics primitive is a symbolic graphics command, which for
2-dimensional graphics are chosen from "Point[ ]", "Line[ ]", "Rectangle[
]", "Polygon[ ]", "Circle[ ]", "Disk[ ]", "Raster[ ]", and "Text[ ]".  We
will also use a graphics directive, which for us will either be a color
command or a "dashing instruction", which we will define below.  The
difference between primitives and directives lies in the fact that graphics
primitives describe particular geometric objects,while graphics directives
specify only characteristics of succeeding primitives.  If we place
graphics primitives and directives together in a list, the graphics
directives set the characteristics for all succeeding primitives (unless
another directive which negates the action is encountered).  After we
create a list of primitives and directives, we will need two commands which
will actually create the graphics based on the commands in our list.  One
command is needed for each of the two stages of the process.  The first
command, "Graphics[ ]", converts graphics directives and primitives into
Mathematica's own internal commands for the graphics.  However, this
command does not display the graphics.  The second command, "Show[ ]",
takes the internal commands created by "Graphics[ ]" and actually displays
them in a cell.  It is important that we store the result of "Graphics[ ]",
these internal commands, in some variable, so that we can execute"Show[ ]"
with this variable as a parameter.

We build up the picture as follows.  Our red triangle is formed by first
issuing the graphics directive "Red", followed by the graphics primitive
"Polygon[ ]", which takes as its argument a list of x-y pairs, thought of
as the vertices of the polygon.

redTriangle=Graphics[{Red,Polygon[{{0,0},{1,0},{1,1}}]}]

We'll now define a disk (a filled-in circle) and a circle.  These
primitives require two arguments, an x-y pair, followed by the radius of
the circle.

purpleDisk=Graphics[{Purple,Disk[{0,1},.25]}]

yellowCircle=Graphics[{Yellow,Circle[{1,1},.25]}]

We may display any combination of our primitives now by using the "Show[ ]"
command.

Show[redTriangle, purpleDisk, yellowCircle]

Our primitives appear squashed because of the default "aspect ratio", which
forces the "y" axis to be scaled in accordance with "x".  To circumvent
this, we can tell Mathematica to figure out the correct aspect ratio to
display x-y points with even scaling in the x and y directions, using the
option "AspectRatio->Automatic".

Show[redTriangle, purpleDisk, yellowCircle,
   AspectRatio->Automatic
]

Now we will construct a box, where the lines are not solid but are
"dashed", using a separate graphics directive "Dashing[ ]".  This directive
requires as arguments a list of lengths for the dashed segments of the
line; the list will be repeated over and over to determine the length of
each dashed piece.  Giving "Dashing[ ]" a list with one element, then,
specifies that the dashing segments will all be of the same length.  Our
graphics primitive is "Line[ ]", which requires a list of x-y pairs to
connect; note that we close off the list with the same point we began with.

box=Graphics[{Goldenrod,Dashing[{.01}],
    Line[{{0,1},{1,0},{2,1},{1,2},{0,1}}]}]

Finally we introduce some text, using the graphics primitive "Text[ ]",
which takes as arguments a string to be printed and an x-y pair describing
the coordinate at which the text should be centered.

tagLine=Graphics[{Text["Soda Shop or Cosmic Coffee?",{1,1.5}]}]

Voila!

masterPiece = Show[
  redTriangle,purpleDisk,yellowCircle,box,tagLine,
  Axes->True,
  AspectRatio->Automatic
]

Adding Plots to Graphics

Suppose we want to add the graphics resulting from a plot command to a
picture we have built up using graphics primitives.  We need only capture
the internal representations of the graphics, by assigning the results of
the "Graphics[ ]" command and the "Plot[ ]" or "ListPlot[ ]" command to
separate variables, and we then use "Show[ ]" to display all of the
graphics together.

sine = Plot[1+Sin[Pi x],{x,0,2}]

This command actually shows the graph, but remember that we can suppress
the immediate display by using the "DisplayFunction->Identity" option.
Remember to use "DisplayFunction-> $DisplayFunction" with the "Show[ ]"
command.

minusSine = Plot[1-Sin[Pi*x],{x,0,2},
   DisplayFunction->Identity]

Show[masterPiece, sine, minusSine,
   DisplayFunction->$DisplayFunction]

Adding Graphics to Plots

Alternatively, we can attempt to add graphics to the result of the "Plot[
]" command.  We can do so using the options "Prolog[ ]" or "Epilog[ ]",
which provide "Plot[ ]" with some graphics primitives it must display both
before and after the original plot.  We do not need to use the "Graphics[
]" function.

Plot[1+Sin[Pi x],{x,0,2},
   Epilog->
      {Purple,
       Disk[{0,1},.25],
       Red,
       Circle[{1,1},.25]}
]

Let's change "Epilog" to "Prolog".  Is there a difference?  Why?

Plot[1+Sin[Pi x],{x,0,2},
   Prolog->
      {Purple,
       Disk[{0,1},.25],
       Red,
       Circle[{1,1},.25]}
]

Further Study

The wealth of graphics primitives and directives is too large for us to
consider exhaustively here.  However, here are some tips you may wish to
remember when using "Plot[ ]" or some other plot command.

The option "PlotStyle->{ }" provides a way for graphics directives to be
issued before a function is plotted.  If the list contains sublists, then
sublists of directives are used, one at a time, for each function.  To plot
"x^2" in red and "x^3" in green, then, we could issue the command
"Plot[{x^2,x^3},PlotStyle->{{Red},{Green}}]".

Other directives include "GrayLevel[ ]", for gray-scale "color", and
"Thickness[ ]", to alter the widths of the lines drawn.

Options for plot commands also include "Axes->boolean" to decide whether or
not to draw the axes; "GridLines->..." for drawing gridlines, and
"PlotLabel->"text"" to assign a label to the plot.  Consult "Options[Plot]"
for more information.

Finally, Mathematica easily plots three-dimensional graphs using 3-D
graphics primitives and "Graphics3D[ ]".  Consult Introduction to
Programming with Mathematica, chapter 10, or the Mathematica reference
manual, for further study.