- Easier to use than ever before!
- Contour plots.
- Interactive charts: pan and zoom with the mouse.
- New API.
- Programmatically close chart windows.

To use F# for Visualization in a script, simply put the DLL in the same directory as the .fsx file and reference it in the script like this:

#r "FSharpForVisualization"

The following namespace contains lots of helpful functions that make F# for Visualization extremely easy to use:

open FlyingFrog.FSharpForVisualization

For example, you can plot a sine wave like this:

plot sin

Note that the chart can be dragged and zoomed using the mouse.

Heuristics are used to guess ranges when none are supplied:

plot sqrt

Ranges over x are easily supplied like this:

plot(atan, (0, 10))

Ranges over y can be supplied in a similar way:

plot(atan, (-10, 10), (-1.5, 1.5))

Note that ranges need not be given as floating point numbers but can, in fact, be any numeric type.

We can also label the axes like this:

plot(atan, (-10, 10), (-1.5, 1.5), ("x", "atan(x)"))

Run-time type information is used to determine the kind of chart used to visualize a function. For example, a function of two variables is automatically visualized as a contour plot:

plot atan2

Functions of the type Complex→float are also visualized as contour plots, this time with default axis labels. For example, the function Im(√z):

open System.Numerics

plot(fun z -> Complex.Sqrt(z).Imaginary)

The plot function can also be used to plot series. For example, sequences of numbers are taken to be y coordinates:

plot [for i in 0..10 -> i*i]

Sequences of pairs of numbers are x,y coordinates:

plot [for i in 0..10 -> i*i, i]

Sequences of such sequences are assumed to be multiple series:

plot[[for i in 0..10 -> i*i, i]; [for i in 0..10 -> i*i*i, i]]

Predator-prey population evolution may then be visualized like this:

let g, k, t = 0.02, 5e2, 1500

let evolve (r, f) _ =

let dtrf = 1e-4 * r * f

r + (1.0 - r/k)*r*g - dtrf, dtrf + (1.0 - g)*f

plot(Seq.scan evolve (50.0, 10.0) [1..t], ("Rabbits", "Foxes"))

The plot function returns an object with SaveAsPng and Close members that allow the visualization to be saved programmatically and closed:

let window = plot floor

window.SaveAsPng "TheFloorFunction.png"

window.Close()

Charts support typeset mathematics for both labels and annotations. For example, plot the sinc function and label the axes accordingly:

open FlyingFrog.Controls

open FlyingFrog.Graphics.Typeset.Math

open FlyingFrog.Interactive

let sinc x = sin x / x

let g = Plot([Function sinc], (-10.0, 10.0))

g.Labels <- font="" math="">"x", Fraction(Row[Text "sin"; math "(x)"], math "x"))

Annotate a point on the graph:

#r "PresentationCore.dll"

#r "PresentationFramework.dll"

#r "WindowsBase.dll"

open System.Windows

open FlyingFrog.Graphics.Scene

open FlyingFrog.Graphics.Typeset

let pi = System.Math.PI

g.Data <- data="" o:p="" pi="" sinc="" unction="">

g.Epilog <- font="" label="" math="" ow="" scene="">"("; Fraction(Greek.pi, math "2"); math ",";

Fraction(math "2", Greek.pi); math ")"]),

0.003, Point(pi/2.0, sinc(pi/2.0)), Vector(-1.2, -1.2))

Although F# for Visualization does not depend upon F# for Numerics or the F# PowerPack it can consume types from those libraries. For example, the following computes the 5x5 Hilbert matrix using arbitrary-precision rational elements:

#r "FSharp.PowerPack.dll"

open Microsoft.FSharp.Math

let A =

Matrix.Generic.ofSeq

[ for i in 0N..4N ->

[ for j in 0N..4N ->

1N / (i + j + 1N) ] ]

Just as our plot function attempts to chart any value of any type so the view function attempts to visualize any value of any type, such as our Hilbert matrix:

view A

or even a typeset mathematical matrix equation:

view(Row[math A; Symbols.Times; math A; math "="; math(A*A)])

The ability to visualize values of F# types as typeset mathematics so easily is invaluable for interactive technical computing.

F# for Visualization also provides an easy-to-use API for general 2D vector graphics. Vector graphics are styled by a sequence of strokes or fills colored with WPF brushes:

open System.Windows.Media

open FlyingFrog.Graphics.Style

let styles =

[ Stroke(Brushes.Red, {Width = 0.001}) ]

The geometry of a shape is a sequence of contours that may be closed or open (only closed contours will be filled):

open FlyingFrog.Graphics.Contour

let geometry =

let n = 50

[ for i in 0 .. n do

for j in 0 .. 1 do

let x, y = float i / float n, float j

yield

Contour.Open(Point(x, y), [lineTo(y, 1.0 - x)]) ]

A vector graphics scene may contain shapes, groups of scenes, transformed scenes and clipped scenes:

open FlyingFrog.Graphics.Scene

let scene = Shape(styles, geometry)

The view function visualizes the vector graphics scene:

view scene

The scene may also be visualized on a pair of axes by making it the epilog of an empty plot:

Plot([], (0., 1.), (0., 1.), Epilog=scene)

open FlyingFrog.Graphics3D

open FlyingFrog.Graphics3D.Scene3D

A Mesh describes a geometry and a Shape3D combines a mesh with a WPF Brush in order to represent a colored 3D object as a piece of scene graph. For example, the following creates a white icosahedron:

let scene3d = Shape3D(Polyhedra.icosahedron, Brushes.White)

The same "view" function can be used to visualize 3D objects:

view scene3d