Angara.Chart


Angara.Chart

An F# data visualization library. Supports visualization of uncertain values. Powered by JavaScript library InteractiveDataDisplay.

The Angara.Chart library can be installed from NuGet:
PM> Install-Package Angara.Chart

Example

The example builds a chart consisting of the line and markers plots:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
#r "Angara.Chart.dll"

open Angara.Charting

open System

let x = [| for i in 0..99 -> float(i) / 10.0 |]
let y = x |> Array.map (fun x -> sin x)
let z = x |> Array.map (fun x -> cos x)

let chart = [ Plot.line(x, y); Plot.markers(x, z) ] |> Chart.ofList

Plot Gallery

This section is a gallery of plots supported by the Angara.Chart. Here we use Angara.Table to load sample data which then is displayed with Angara.Chart.

Preparing data

The code loads several tables that will be used in the following charts.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
#r "Angara.Table.dll"
#r "System.Collections.Immutable.dll"
open Angara.Data
open System.Linq

let wheat = Table.Load("../files/data/wheat.csv")
let uwheat = Table.Load("../files/data/uwheat.csv")
let site = Table.Load("../files/data/site.csv")
let npz = Table.Load("../files/data/npz.csv")
let grid = Table.Load("../files/data/grid.csv")
let ugrid = Table.Load("../files/data/ugrid.csv")

// This function returns a float array of the given table column 
let col (colName:string) (t:Table) : float[] = t.[colName].Rows.AsReal.ToArray()
// This function returns an array of records representing quantiles,
// so instead of a value it gives an information about its uncertainty.
let quantiles prefix table = 
    { median = table |> col (prefix + "_median")
      lower68 = table |> col (prefix + "_lb68")
      upper68 = table |> col (prefix + "_ub68")
      lower95 = table |> col (prefix + "_lb95")
      upper95 = table |> col (prefix + "_ub95") }

Line and uncertainty bands

The functions Plot.lineallow to define a plot displayed straight line segments connecting a series of data points.

It is enough to provide just y data series to define a line plot:

1: 
2: 
3: 
let y = Array.init 100 (fun i -> let x = float(i-50)/10.0 in x*x)

let line_y = [ Plot.line(y) ] |> Chart.ofList

The following plot takes both x and y series, defines stroke color, line thickness and axis titles. See the API Reference for other optional parameteres of the line plot.

1: 
2: 
3: 
4: 
5: 
6: 
let t = site |> col "t"
let p = site |> col "p"

let line_tp = 
  [ Plot.line(t, p, stroke = "#00007F", thickness = 2.0, titles = Titles.line("time", "p")) ] 
  |> Chart.ofList

If a variable that determines the position on the vertical axis is uncertain, bands corresponding to the given quantiles of the uncertain values are displayed in addition to the line segments, which represent median values.

1: 
2: 
3: 
4: 
5: 
let y_uncertain = npz |> quantiles "p"

let line_uncertain = 
  [ Plot.line(LineX.Values t, LineY.UncertainValues y_uncertain, titles = Titles.line("time", "p")) ] 
  |> Chart.ofList

Area

1: 
2: 
3: 
4: 
5: 
6: 
let y1 = npz |> col "p_lb68"
let y2 = npz |> col "p_ub68"

let area = 
  [ Plot.area(t, y1, y2, titles = Titles.area("time", "p - lower bound", "p - upper bound")) ] 
  |> Chart.ofList

Markers

It is a plot which displays data as a collection of points, each having the value of one data series determining the position on the horizontal axis and the value of the other data series determining the position on the vertical axis. Also data series can be bound to marker size and color, and other appearance settings.

Markers plot has default collection of supported shapes such as box, circle, cross, triangle etc, but still it allows creating new shapes.

1: 
2: 
3: 
4: 
5: 
let lon = wheat |> col "Lon"
let lat = wheat |> col "Lat"
let wheat = wheat |> col "wheat"

let markers = [ Plot.markers(lon, lat, displayName = "wheat") ] |> Chart.ofList
1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
let markers_colors =
  [ Plot.markers(lon, lat, 
      color = MarkersColor.Values wheat, 
      colorPalette = "0=Red=Green=Yellow=Blue=10", 
      shape = MarkersShape.Circle, 
      displayName = "wheat",
      titles = Titles.markers("lon", "lat", color = "wheat production")) ] 
  |> Chart.ofList
        
1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
let markers_colors_sizes = 
  [ Plot.markers(lon, lat, 
      color = MarkersColor.Values wheat, colorPalette = "Red,Green,Yellow,Blue", 
      size = MarkersSize.Values wheat, sizePalette = MarkersSizePalette.Normalized(5.0, 15.0), 
      shape = MarkersShape.Diamond, 
      displayName = "wheat",
      titles = Titles.markers(color = "wheat production", size = "wheat production")) ] 
  |> Chart.ofList

The shapes petals, bull-eye, boxwhisker allow drawing data
if one of the properties is uncertain. Uncertain variable is represented as a set of quantiles. Particular qualities for each shape are described below.

Petals is a kind of markers when shape indicates level of uncertainty. Data series size is a set of quantiles which must contain lower95 and upper95.

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
let wheat_uncertain = uwheat |> quantiles "w"

let markers_petals =
  [ Plot.markers(lon, lat, 
      color = MarkersColor.Values wheat_uncertain.median,
      size = MarkersSize.UncertainValues wheat_uncertain, sizePalette = MarkersSizePalette.Normalized(5.0, 15.0),
      displayName = "wheat")] 
  |> Chart.ofList

Bull-eyes is a kind of markers when outer and inner colors indicate level of uncertainty. Data series size is a size in pixels, same for all markers; color is an array of quantiles which must contains median, lower95 and upper95.

1: 
2: 
3: 
4: 
5: 
6: 
let markers_bulleyes =
  [ Plot.markers(lon, lat, 
      color = MarkersColor.UncertainValues wheat_uncertain,
      size = MarkersSize.Value 15.0,
      displayName = "wheat")] 
  |> Chart.ofList

Box-and-whisker plot is displayed if y is uncertain and given as an array of quantiles, which may contain all or some of properties median, lower95, upper95, lower68 and upper68. )

1: 
2: 
3: 
4: 
5: 
let markers_box =
  [ Plot.markers(MarkersX.Values t, MarkersY.UncertainValues y_uncertain, 
    displayName = "p",
    titles = Titles.markers("time", "p"))] 
  |> Chart.ofList

Heatmap displays a graphical representation of data where the individual values contained in a matrix are represented as colors. If the values are uncertain, it allows to see quantiles of each point and highlight regions with similar values.

1: 
2: 
3: 
4: 
5: 
let grid_lon = grid |> col "lon"
let grid_lat = grid |> col "lat"
let grid_value = grid |> col "value"

let heatmap_gradient = [ Plot.heatmap(grid_lon, grid_lat, grid_value) ] |> Chart.ofList
1: 
2: 
3: 
let heatmap_matrix = 
  [ Plot.heatmap(grid_lon, grid_lat, grid_value, treatAs = HeatmapTreatAs.Discrete) ] 
  |> Chart.ofList

Heatmap values also can be uncertain, if they are defined as quantiles containing median, lower68, upper68. The plot displays median values, but if a probe is pulled on the heatmap, the probe card contains "Highlight similar" checkbox which highlights areas of the heatmap with values similar to the value under the probe.

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
let ugrid_lon = ugrid |> col "lon"
let ugrid_lat = ugrid |> col "lat"
let ugrid_value = ugrid |> quantiles "value"

let heatmap_uncertain = 
  [ Plot.heatmap(ugrid_lon, ugrid_lat, 
      HeatmapValues.TabularUncertainValues ugrid_value, 
      colorPalette = "blue,white,yellow,orange") ] 
  |> Chart.ofList

See more details about plots here.

Contributing and copyright

The project is hosted on GitHub where you can report issues, fork the project and submit pull requests. If you're adding a new public API, please also consider adding samples that can be turned into a documentation. You might also want to read the library design notes to understand how it works.

The library is available under Public Domain license, which allows modification and redistribution for both commercial and non-commercial purposes. For more information see the License file in the GitHub repository.

namespace Angara
namespace Angara.Charting
namespace System
val x : float []

Full name: Index.x
val i : int
Multiple items
val float : value:'T -> float (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.float

--------------------
type float = Double

Full name: Microsoft.FSharp.Core.float

--------------------
type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>
val y : float []

Full name: Index.y
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.map
val x : float
val sin : value:'T -> 'T (requires member Sin)

Full name: Microsoft.FSharp.Core.Operators.sin
val z : float []

Full name: Index.z
val cos : value:'T -> 'T (requires member Cos)

Full name: Microsoft.FSharp.Core.Operators.cos
val chart : Chart

Full name: Index.chart
type Plot =
  private new : unit -> Plot
  static member area : seriesX:float [] * seriesY1:float [] * seriesY2:float [] * ?fill:string * ?displayName:string * ?titles:AreaTitles -> PlotInfo
  static member heatmap : x:float [] * y:float [] * values:float [] * ?colorPalette:string * ?treatAs:HeatmapTreatAs * ?displayName:string * ?titles:HeatmapTitles -> PlotInfo
  static member heatmap : x:float [] * y:float [] * values:HeatmapValues * ?colorPalette:string * ?treatAs:HeatmapTreatAs * ?displayName:string * ?titles:HeatmapTitles -> PlotInfo
  static member line : seriesY:float [] * ?stroke:string * ?thickness:float * ?treatAs:LineTreatAs * ?fill68:string * ?fill95:string * ?displayName:string * ?titles:LineTitles -> PlotInfo
  static member line : seriesX:float [] * seriesY:float [] * ?stroke:string * ?thickness:float * ?treatAs:LineTreatAs * ?fill68:string * ?fill95:string * ?displayName:string * ?titles:LineTitles -> PlotInfo
  static member line : x:LineX * y:LineY * ?stroke:string * ?thickness:float * ?treatAs:LineTreatAs * ?fill68:string * ?fill95:string * ?displayName:string * ?titles:LineTitles -> PlotInfo
  static member markers : seriesX:float [] * seriesY:float [] * ?color:MarkersColor * ?colorPalette:string * ?size:MarkersSize * ?sizePalette:MarkersSizePalette * ?shape:MarkersShape * ?borderColor:string * ?displayName:string * ?titles:MarkersTitles -> PlotInfo
  static member markers : x:MarkersX * y:MarkersY * ?color:MarkersColor * ?colorPalette:string * ?size:MarkersSize * ?sizePalette:MarkersSizePalette * ?shape:MarkersShape * ?borderColor:string * ?displayName:string * ?titles:MarkersTitles -> PlotInfo

Full name: Angara.Charting.Plot
static member Plot.line : seriesY:float [] * ?stroke:string * ?thickness:float * ?treatAs:LineTreatAs * ?fill68:string * ?fill95:string * ?displayName:string * ?titles:LineTitles -> PlotInfo
static member Plot.line : seriesX:float [] * seriesY:float [] * ?stroke:string * ?thickness:float * ?treatAs:LineTreatAs * ?fill68:string * ?fill95:string * ?displayName:string * ?titles:LineTitles -> PlotInfo
static member Plot.line : x:LineX * y:LineY * ?stroke:string * ?thickness:float * ?treatAs:LineTreatAs * ?fill68:string * ?fill95:string * ?displayName:string * ?titles:LineTitles -> PlotInfo
static member Plot.markers : seriesX:float [] * seriesY:float [] * ?color:MarkersColor * ?colorPalette:string * ?size:MarkersSize * ?sizePalette:MarkersSizePalette * ?shape:MarkersShape * ?borderColor:string * ?displayName:string * ?titles:MarkersTitles -> PlotInfo
static member Plot.markers : x:MarkersX * y:MarkersY * ?color:MarkersColor * ?colorPalette:string * ?size:MarkersSize * ?sizePalette:MarkersSizePalette * ?shape:MarkersShape * ?borderColor:string * ?displayName:string * ?titles:MarkersTitles -> PlotInfo
type Chart =
  {Plots: PlotInfo list;}
  static member ofList : plots:PlotInfo list -> Chart

Full name: Angara.Charting.Chart
static member Chart.ofList : plots:PlotInfo list -> Chart
namespace Angara.Data
namespace System.Linq
val wheat : Table

Full name: Index.wheat
Multiple items
type Table =
  interface IEnumerable<Column>
  abstract member ToRows : unit -> seq<'r>
  member Count : int
  member Item : name:string -> Column with get
  member Item : index:int -> Column with get
  member RowsCount : int
  member TryItem : name:string -> Column option with get
  member TryItem : index:int -> Column option with get
  static member Add : column:Column -> table:Table -> Table
  static member Append : table1:Table -> table2:Table -> Table
  ...

Full name: Angara.Data.Table

--------------------
type Table<'r> =
  inherit Table
  member AddRow : 'r -> Table<'r>
  member AddRows : seq<'r> -> Table<'r>
  member Rows : ImmutableArray<'r>

Full name: Angara.Data.Table<_>
static member Table.Load : reader:IO.TextReader -> Table
static member Table.Load : path:string -> Table
static member Table.Load : reader:IO.TextReader * settings:DelimitedFile.ReadSettings -> Table
static member Table.Load : path:string * settings:DelimitedFile.ReadSettings -> Table
val uwheat : Table

Full name: Index.uwheat
val site : Table

Full name: Index.site
val npz : Table

Full name: Index.npz
val grid : Table

Full name: Index.grid
val ugrid : Table

Full name: Index.ugrid
val col : colName:string -> t:Table -> float []

Full name: Index.col
val colName : string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
val t : Table
val quantiles : prefix:string -> table:Table -> QuantileArray

Full name: Index.quantiles
val prefix : string
val table : Table
val init : count:int -> initializer:(int -> 'T) -> 'T []

Full name: Microsoft.FSharp.Collections.Array.init
val line_y : Chart

Full name: Index.line_y
val t : float []

Full name: Index.t
val p : float []

Full name: Index.p
val line_tp : Chart

Full name: Index.line_tp
Multiple items
type Titles =
  new : unit -> Titles
  static member area : ?x_title:string * ?y1_title:string * ?y2_title:string -> AreaTitles
  static member heatmap : ?x_title:string * ?y_title:string * ?value_title:string -> HeatmapTitles
  static member line : ?x_title:string * ?y_title:string -> LineTitles
  static member markers : ?x_title:string * ?y_title:string * ?color:string * ?size:string -> MarkersTitles

Full name: Angara.Charting.Titles

--------------------
new : unit -> Titles
static member Titles.line : ?x_title:string * ?y_title:string -> LineTitles
val y_uncertain : QuantileArray

Full name: Index.y_uncertain
val line_uncertain : Chart

Full name: Index.line_uncertain
type LineX =
  | Values of float []
  | Indices

Full name: Angara.Charting.LineX
union case LineX.Values: float [] -> LineX
type LineY =
  | Values of float []
  | UncertainValues of QuantileArray

Full name: Angara.Charting.LineY
union case LineY.UncertainValues: QuantileArray -> LineY
val y1 : float []

Full name: Index.y1
val y2 : float []

Full name: Index.y2
val area : Chart

Full name: Index.area
static member Plot.area : seriesX:float [] * seriesY1:float [] * seriesY2:float [] * ?fill:string * ?displayName:string * ?titles:AreaTitles -> PlotInfo
static member Titles.area : ?x_title:string * ?y1_title:string * ?y2_title:string -> AreaTitles
val lon : float []

Full name: Index.lon
val lat : float []

Full name: Index.lat
val wheat : float []

Full name: Index.wheat
val markers : Chart

Full name: Index.markers
val markers_colors : Chart

Full name: Index.markers_colors
type MarkersColor =
  | Value of string
  | Values of float []
  | UncertainValues of QuantileArray

Full name: Angara.Charting.MarkersColor
union case MarkersColor.Values: float [] -> MarkersColor
type MarkersShape =
  | Box
  | Circle
  | Diamond
  | Cross
  | Triangle
  | Custom of string

Full name: Angara.Charting.MarkersShape
union case MarkersShape.Circle: MarkersShape
static member Titles.markers : ?x_title:string * ?y_title:string * ?color:string * ?size:string -> MarkersTitles
val markers_colors_sizes : Chart

Full name: Index.markers_colors_sizes
type MarkersSize =
  | Value of float
  | Values of float []
  | UncertainValues of QuantileArray

Full name: Angara.Charting.MarkersSize
union case MarkersSize.Values: float [] -> MarkersSize
type MarkersSizePalette =
  | Normalized of min: float * max: float
  | Absolute of sizeMin: float * sizeMax: float * valueMin: float * valueMax: float

Full name: Angara.Charting.MarkersSizePalette
union case MarkersSizePalette.Normalized: min: float * max: float -> MarkersSizePalette
union case MarkersShape.Diamond: MarkersShape
val wheat_uncertain : QuantileArray

Full name: Index.wheat_uncertain
val markers_petals : Chart

Full name: Index.markers_petals
QuantileArray.median: float []
union case MarkersSize.UncertainValues: QuantileArray -> MarkersSize
val markers_bulleyes : Chart

Full name: Index.markers_bulleyes
union case MarkersColor.UncertainValues: QuantileArray -> MarkersColor
union case MarkersSize.Value: float -> MarkersSize
val markers_box : Chart

Full name: Index.markers_box
type MarkersX = | Values of float []

Full name: Angara.Charting.MarkersX
union case MarkersX.Values: float [] -> MarkersX
type MarkersY =
  | Values of float []
  | UncertainValues of QuantileArray

Full name: Angara.Charting.MarkersY
union case MarkersY.UncertainValues: QuantileArray -> MarkersY
val grid_lon : float []

Full name: Index.grid_lon
val grid_lat : float []

Full name: Index.grid_lat
val grid_value : float []

Full name: Index.grid_value
val heatmap_gradient : Chart

Full name: Index.heatmap_gradient
static member Plot.heatmap : x:float [] * y:float [] * values:float [] * ?colorPalette:string * ?treatAs:HeatmapTreatAs * ?displayName:string * ?titles:HeatmapTitles -> PlotInfo
static member Plot.heatmap : x:float [] * y:float [] * values:HeatmapValues * ?colorPalette:string * ?treatAs:HeatmapTreatAs * ?displayName:string * ?titles:HeatmapTitles -> PlotInfo
val heatmap_matrix : Chart

Full name: Index.heatmap_matrix
type HeatmapTreatAs =
  | Gradient
  | Discrete

Full name: Angara.Charting.HeatmapTreatAs
union case HeatmapTreatAs.Discrete: HeatmapTreatAs
val ugrid_lon : float []

Full name: Index.ugrid_lon
val ugrid_lat : float []

Full name: Index.ugrid_lat
val ugrid_value : QuantileArray

Full name: Index.ugrid_value
val heatmap_uncertain : Chart

Full name: Index.heatmap_uncertain
type HeatmapValues =
  | TabularValues of float []
  | TabularUncertainValues of QuantileArray

Full name: Angara.Charting.HeatmapValues
union case HeatmapValues.TabularUncertainValues: QuantileArray -> HeatmapValues
Fork me on GitHub