Lecture 9 : Anonymous Functions, Loops, and Graphics in Mathematica

Unfortunately, last time we only got through half the planned material, so today the first half of the lecture will be fast-paced, so we can catch up to the new material. We'll cover anonymous functions and loops first, then the new material will cover the graphics subsystem of Mathematica.

Anonymous Functions and Operators to use them with

You use anonymous functions in Mathematica quite often. Unlike Matlab, where you might find yourself assigning them to variables to use them, you usually define and use them directly.
There are two ways to define an anonymous function: using the # & syntax, or the Function syntax.
The Function syntax is: Function[arg, body] or Function[arglist, body]. 
The # & syntax is: (body which uses #1, ... #n as arguments) &
Function[body] is another syntax which is equivalent to the (body) & syntax
Note that # is equivalent to #1 inside of the body
Examples will clarify:

f = Function[#^2] ;
f[1]
f[{1,x}]
??f

g = Function[Norm[#1, #2]];
g[a,b]
??g

You can use anonymous functions directly as the head of expressions

(# &) @@ {1,2} (* remember Apply replaces the head of expressions; in this case, it replaces the List with an anonymous function *)
(#1 &) @@ {1,2}
(#2 &) @@ {1,2}
Function[Log[#]][3,4]
Function[Log[#2]][3,4]

But by far, you most often use anonymous functions in a transient manner, when you need to use a function only temporarily, so it doesn't make sense to store their definitions. In this connection, it is useful to know that the Map function, which has the syntax Map[f, list] or f /@ list, returns a list constructed by applying f to every entry in list. For example, let's revisit the Monte Carlo calculation for pi:

(* incrementally *)
insideCircleQ = Function[pt, If[pt[[1]]^2 + pt[[2]]^2 ≤ 1, 1, 0]];
randomPoints = Table[{RandomReal[], RandomReal[]}, {10^5}];
4 Mean[insideCircleQ /@ randomPoints] //N

(* quick and dirty *)
4Mean[Map[ If[#[[1]]^2 + #[[2]]^2 ≤ 1, 1, 0] &, Table[{RandomReal[], RandomReal[]}, {10^5}]]] //N

As another example of the application of Map and anonymous functions, let' s calculate the (∞, 1) norm of a matrix A. This is a combinatorial quantity, so the list manipulation functions in Mathematica make calculating it a breeze :

∞1norm[A_] := Max[Norm[A.#, 1]& /@ Tuples[{-1,1}, Length@Transpose@A]];

A = (({{1, 3, 4}, {0, 5, 6}, {0, 7, 8}}));
∞1norm[A]

Other functions that may be useful include Sort and Ordering. You saw Ordering used above (read the Help for details). Sort takes a list and returns it sorted into a canonical order

Sort[{4,3,1,5}] (* for numbers, that is increasing *)
Sort[{z,y,h,a}] (* for symbols, it is lexographically increasing *)

For our purposes, it' s useful to note that you can provide an additional argument to Sort if you want to control how the list is ordered. For example, if I wanted a list of numbers to be sorted in decreasing order, I could call Sort as Sort[list, Greater]. Sort[list, pred] orders the list by evaluating pred[x, y] for every pair of x and y in the list-- this implies that pred must accept two arguments. If pred is true, then x comes before y in the list.

Sort[RandomInteger[{-4,5}, 6], Greater]

As an example, here' s a fanciful definition of InftyOneNorm[A]

InftyOneNorm[A_] :=Norm[ A .(First@Sort[Tuples[{-1,1}, Length@Transpose@A], Norm[A . #1, 1] > Norm[A.#2, 1] &]), 1];
InftyOneNorm[A]

When you use DSolve, RSolve, etc. you can get it to return an anonymous function by asking it to solve for r instead of r[x] (see example below for clarification)

Quiet[s = First[r /. DSolve[ {r''[x] + r'[x]r[x]==6, r[0]==1, r'[0]==1}, r, x]]] (* returns an anonymous function*)

 Plot[s[x], {x,0,1}] (* simpler than not using anonymous functions *)

Looping Structures in Mathematica

The most commonly used control structures in Mathematica are the For, Do, and While loops. Their most useful syntaxes are
For[startexpr, testexpr, increxpr, body]
Do[expr, {num}]
Do[expr,{i, num}]
Do[expr,{i, min, max}]
Do[expr,{i, min,max,stepsize}]
While[testexpr, body]
The Break command exits the inner most loop while the Continue command exits the current iteration of the inner loop.
Each expr may contain multiple expressions, using a Block, Module, or simply by separating multiple statements by semicolons

Note that the value of a control expression is Null, so if for example you want to build up a list using a loop, you need to assign the values to a variable to store them. The usage is straightforward-- pretty much the same way you'd use For, Do, or While loops in other languages.

3 For[i=2, i<5, i++, i] (* this is not 15, as you might expect *)

(* this doesn't work-- you can't access parts of lists unless they exist *)
For[ i=1, i < 40, i++, a[[i]] = If[Mod[i,3]==0, 1, 0]]

(* instead use the idiom of storing the values in a[i] *)
For[ i=1, i <40, i++, a[i] = If[Mod[i,3] ==0, 1, 0]]
a = Table[a[i], {i,1,39}] (* if you need them in list form *)

Another example of a For loop : find the first factorial that is also a Fibonacci number

FibQ[x_] := Or[IntegerQ[Sqrt@(5x^2+4)], IntegerQ[Sqrt@(5z^2-4)]];
TimeConstrained[ For[i = 2, !FibQ[i!], i++, i], 30] (* the principle is sound, but this might run forever, so constrain it to run for at most half a minute *)

An otherwise pointless example that illustrates two important things : the use of compound expression in loops, and how Module implements local variables

For[a = 1; Block[{a}, a = 2], a < 5, a++, Module[{a}, Print[a]]; Print[a]]

If you use For loops in functions, you can return a value from inside the loop by using the Return command

f[n_] := For[i=n, i>0, i--, If[IntegerQ@Log[2, i], Return[i]]] (* find the closest power of two less than n *)
ListPlot[f /@ Range[500]]

(2D) Graphics

2D Graphics in Mathematica are represented as Graphics objects (Graphics3D for 3D). The arguments to the Graphics object are a list of graphics objects and directives, and a list of options:
Graphics[objlist, options]
Graphics directives are commands which influence the way graphics objects are displayed, for instance changing linewidths, dashings, or colors. Directives apply only to the objects that follow them in the list. The object list can be nested arbitrarily deep; directives on one level of the list only affect objects on that level. Optionally, you can use the Style directive directly on a graphics object to specify style options that apply only to that object.

To show a Graphics object, use the Show command. Show takes a sequence of graphics objects, and additional options. These options overwrite any options specified in the objects themselves. 

Some graphics objects are: Polygon, Point, Circle, Disk, Rectangle, Line, Text.
Some graphics directives are: Thickness, Hue, GrayLevel, RGBColor, EdgeForm, FaceForm, Dashed, Dashing
 For their specifications, see the help

(* examples of nested lists in graphics *)
circleapprox[n_] := Polygon[ Table[{Cos[θ], Sin[θ]}, {θ,0,2π, ((2π)/(n-1))}]];
circleobjs = Table[{Hue[((n-3)/4)], circleapprox[n]}, {n,3,7}];
circleobjs // Reverse // Graphics //Show

Plots are graphics objects, and can be treated just like any other graphics object. In particular, note that a lot of the Plot options can be specified for any graphics object, e.g. whether or not to show axes. And the simpler of the standard graphics directives can be applied to plots using the PlotStyle option.

p = Plot[Sin[x] Cos[x], {x,0,2π}, Filling->Axis];
q = Plot[Sin[x+(π/2)] Cos[x+(π/2)], {x,0,2π}, Filling->Axis, FillingStyle->Purple, PlotStyle->{Black}];
p //FullForm //Short;
Show[p,q, Axes->False, Frame->True]

Let's create our own plotting function

BubbleChart[list_] := Module[{clist},
clist = Graphics[
Style[
Disk[{#[[1]], #[[2]]}, #[[3]]], Pink, EdgeForm[{Thick, Black}]] & /@ list] ;
Show[clist, Axes->True]
];
BubbleChart::usage = "BubbleChart[{{x1,y1,z1}, ...}] list plots the points {xn,yn} using bubbles with radius zn";

Protect[BubbleChart];
?BubbleChart

testpts = MapThread[Append, {RandomReal[{-10,10}, {10,2}], RandomReal[{0,1}, 10]}];
BubbleChart[testpts]

Recall the GraphicsArray from one of the previous homework solutions; It does the same as Graphics, except you pass in a matrix of graphics objects

Lissajoux[s_] := 
ListPlot[
Apply[{Sin[5(#1 + #2)], Cos[7(#1+#2)]} &, Transpose[{Range[4000] ((2π)/4000) , RandomReal[{-s, s}, 4000]}], {1}], 
Joined->True, Axes->False, AspectRatio->1];

GraphicsGrid[Partition[Lissajoux /@ {.01,.1,.15,.2},2], ImageSize->Medium]

The Animate command allows us to animate expressions (they aren't limited to being graphical); see help for more details. 

Recall earlier we mentioned that Mathematica tries to determine what region of a plot is interesting, and sometimes you have to override its choice using the PlotRange option. The same is true for displaying any graphics object. Also, if you have an animation where the size of the graphic changes rapidly between frames, you should specify the PlotRange explicitly to prevent flickering

(* broken clock *)
myClock[h_] := {Circle[{0,0},1], 
Table[Line[{{Cos[θ], Sin[θ]}, .9 {Cos[θ], Sin[θ]}}],{θ,(π/2),(π/2)+2π-((2π)/11),2(π/11) }],
{PointSize[.025], Point[{0,0}]},
Arrow[{{0,0}, .75 {Cos[τ], Sin[τ]}/.τ->((-h)/24)2π+(π/2)}],
Arrow[{{0,0}, .95{Cos[τ], Sin[τ]}/.τ->-FractionalPart[h]2π+(π/2)}]};
Animate[Graphics@myClock[h], {h,0,24}, AnimationRate->.5,AnimationRunning->False]

There are two coordinate systems in Mathematica: the scaled, or display, coordinates, which vary from {0,0} to {1,1} from the lower left corner of the image to its upper right corner, or original coordinates, which are like those you use in plots. When displaying an object, Mathematica converts the original coordinates to display coordinates. You can specify locations directly in terms of scaled coordinates by using the Scaled[{x,y}] command

Show[Plot[ ((Sin[x])/x), {x,0,2π}, Filling->Bottom], Graphics@Text[Style[Sinc[x], 16], Scaled[{.8,.8}]], Frame->True, Axes->False]

Note that most directives which require dimensions take them in scaled coordinates, Thickness and Dashing, for instance, so e.g. {Thickness[.1], Circle[{0, 0}, 5]} specifies a circle drawn with a line that is .1 thick as the image is wide. You can specify dimensions in absolute coordinates (printer points) using the Absolute variants of these directives

GraphicsArray[{Graphics@{Thickness[.1], Circle[{0,0},5]},
Graphics@{AbsoluteThickness[1], Circle[{0,0}, 5]}
}]

An integrated example

(* given a polygon, determine the centroid *)
Centroid[poly_] := Module[{x,y,n,area,cx,cy}, 
x = #[[1]] &/@ First@poly;
y = #[[2]] & /@ First@poly;
n = Length[x];
area = (1/2)Sum[x[[i]]y[[i+1]]-x[[i+1]]y[[i]],{i,1,n-1}];
cx = (1/(6area))Sum[(x[[i]]+x[[i+1]])(x[[i]] y[[i+1]]-x[[i+1]]y[[i]]), {i,1,n-1}];
cy = (1/(6 area))Sum[(y[[i]]+y[[i+1]])(x[[i]]y[[i+1]]-x[[i+1]]y[[i]]),{i,1,n-1}];
{cx,cy}
];

(* given the coordinates defining the polygonal outline of a country, return a graphics list defining the country outline and its centroid *)
DrawCountry[coordlist_] := {Polygon[#], Red, Point@Centroid@Polygon@#} & /@ coordlist;

(* all the countries Mathematica has data on *)
countrynames = CountryData[];
(* all the properties of the countries Mathematica has stored *)
CountryData["Properties"] 

flex = CountryData[#, "FemaleElderlyPopulation"]&/@countrynames;
validc = Delete[countrynames, Position[flex, Missing[x_]]];
flex = Delete[flex, Position[flex, Missing[x_]]];
coords = CountryData[#,"Coordinates"] & /@ validc;
coords = coords /. {x_Real, y_Real} ->{y,x};
connectedcountries = Complement[Range[Length[coords]], Flatten@Position[coords, x_/;Length[x]>1,{1}]];
Length[connectedcountries]
b = BubbleChart[MapThread[Append, {Centroid /@coords[[connectedcountries]], Rescale@flex[[connectedcountries]]}]];
m = DrawCountry /@ coords[[connectedcountries]];
 Graphics[{m,First@b}] // Show