Fsharp.Gdal


Land use in the Big Valley

Exploring gdal's rasters functions

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
#r "FSharp.Gdal.dll"
#r "gdal_csharp.dll"
#r "gdalconst_csharp.dll"
#r "ogr_csharp.dll"
#r "osr_csharp.dll"

open System
open System.IO
open System.Windows.Forms
open System.Drawing

open Deedle
open FSharp.Data
open FSharp.Charting

open OSGeo.GDAL
open OSGeo.OGR

open FSharp.Gdal
open FSharp.Gdal.UM
open FSharp.Gdal.Raster

For this section I will use data from the Corine Land Cover provided by the European Enivronment Agency clipped (with an external program for now) to the extension of all the municipalities that have part of their land in the Big Valley National Park. Big Valleys Municipalities

The clipped raster looks like this:

1: 
2: 
3: 
4: 
let image = new Bitmap(__SOURCE_DIRECTORY__ + "\data\clc_valgrande.tif")
let form = new Form(Visible = true, TopMost = true, Width = 700, Height = 500, 
                    BackgroundImage = image, BackgroundImageLayout = ImageLayout.Center)
form.Show()

Corinne Land Cover

We call the Configuration.Init() to configure the gdal library and then open the raster:

1: 
2: 
3: 
Configuration.Init() |> ignore

let dataset = Gdal.OpenShared(__SOURCE_DIRECTORY__ + @".\data\clc_valgrande.tif", Access.GA_ReadOnly)

Getting Dataset Information

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
let mutable (geotransform:float[]) = [|0.;0.;0.;0.;0.;0.|]
dataset.GetGeoTransform(geotransform)
let topLeftX                    = geotransform.[0]
let topLeftY                    = geotransform.[3]
let westEastPixelResolution     = geotransform.[1] * 1.<m>
let northSouthPixelResolution   = Math.Abs(geotransform.[5]) * 1.<m> // take absolute of negative number
let xSize = dataset.RasterXSize
let ySize = dataset.RasterYSize 
let bands = dataset.RasterCount

printfn "Driver = %s / %s" (dataset.GetDriver().ShortName) (dataset.GetDriver().LongName)
printfn "Size = X:%i x Y:%i x Bands:%i" xSize ySize bands
printfn "Projection = %s..." (dataset.GetProjection().ToString().Substring(0,110))
printfn "Origin = (%f,%f)" topLeftX topLeftY
printfn "Pixel Size = (%f,%f)" westEastPixelResolution northSouthPixelResolution
Driver = GTiff / GeoTIFF
Size = X:359 x Y:388 x Bands:1
Projection = PROJCS["ETRS89 / LAEA Europe",GEOGCS["ETRS89",DATUM["European_Terrestrial_Reference_System_1989",SPHEROID["GRS...
Origin = (4186544.357106,2571961.856855)
Pixel Size = (100.098957,100.104536)

In particular the pixel resolution is of about 100m x 100m so a square in the grid equals about 1ha and we can calculate the total size of the area covered by the file multiplying this value by the number of pixels.

1: 
2: 
3: 
4: 
let pixelArea = westEastPixelResolution * northSouthPixelResolution * mqToHa
let totalArea = pixelArea * (xSize * ySize |> float)

printfn "pixelArea : float<ha> = %A\ntotalArea : float<ha> = %A" pixelArea totalArea
pixelArea : float<ha> = 1.002035959
totalArea : float<ha> = 139575.5928

Corine Land Cover stores for each pixel a number that reppresents the type of land use in that area. 0 represents the white area in the picture above for which there is no information beacuase I clipped the raster to just the municipalty limits.

The European Environment Agency gives a legend of the number meanings with an excel file.

Now what I want to do is to extract the category number of land use for each pixel coordinate from the file.

1: 
2: 
3: 
4: 
5: 
6: 
7: 
let values = 
    [for x in 0..(xSize-1) ->
        [for y in 0..(ySize-1) -> 
            (x,y),(getImgValue geotransform dataset (x,y))]]
    |> List.concat

printf "%s" (values.ToString())
[((0, 0), Some(0)); ((0, 1), Some(0)); ((0, 2), Some(0)); ... ]

The values are represented here as a tuple of pixel's coordinate and their value. To get some insight let's group all the pixel and count them by their value. From the number of pixels and the pixel's area we can calculate the area in hectars occupied by each category.

With this information we populate a Deedle Frame.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
let hectarsByCategory = 
    values
    |> List.groupBy (fun (c,v) -> v)
    |> List.map (fun (v,xs) -> 
            v.Value |> string, 
            "Hectars", 
            (xs.Length |> float) * pixelArea
        )
    |> List.sortByDescending (fun (v,c,l) -> l)
    |> Frame.ofValues

Hectars

0

7,344E+04

23

2,244E+04

25

1,288E+04

26

6955

29

5567

41

5408

27

3258

24

2666

...

...

40

58,12

11

58,12

35

57,12

4

50,1

Just to check we can see that the sum is still equivalent with the total area we've calculated before:

1: 
2: 
3: 
let sumHectars = hectarsByCategory.Sum()?Hectars

printf "sumHectars = %f" sumHectars
sumHectars = 139575.592814

Now we want to decode the category number in meaningfull description.

For this puprose I will create another frame with the information stored in the corine legend indexing the frame by the GRID_CODE column which corresponds to the code number stored in the image file.

1: 
2: 
3: 
let corineLegend = 
    Frame.ReadCsv(__SOURCE_DIRECTORY__ + "./data/clc_legend.csv",separators = ";")
    |> Frame.indexRowsString "GRID_CODE"

CLC_CODE

LABEL1

LABEL2

LABEL3

RGB

1

111

Artificial surfaces

Urban fabric

Continuous urban fabric

230-000-077

2

112

Artificial surfaces

Urban fabric

Discontinuous urban fabric

255-000-000

3

121

Artificial surfaces

Industrial, commercial and transport units

Industrial or commercial units

204-077-242

4

122

Artificial surfaces

Industrial, commercial and transport units

Road and rail networks and associated land

204-000-000

5

123

Artificial surfaces

Industrial, commercial and transport units

Port areas

230-204-204

6

124

Artificial surfaces

Industrial, commercial and transport units

Airports

230-204-230

7

131

Artificial surfaces

Mine, dump and construction sites

Mineral extraction sites

166-000-204

8

132

Artificial surfaces

Mine, dump and construction sites

Dump sites

166-077-000

...

...

...

...

...

...

48

999

NODATA

NODATA

NODATA

49

990

UNCLASSIFIED

UNCLASSIFIED LAND SURFACE

UNCLASSIFIED LAND SURFACE

50

995

UNCLASSIFIED

UNCLASSIFIED WATER BODIES

UNCLASSIFIED WATER BODIES

230-242-255

255

990

UNCLASSIFIED

UNCLASSIFIED

UNCLASSIFIED

And finally join the two frames:

1: 
let landUse = hectarsByCategory.Join(corineLegend, kind=JoinKind.Left)

Hectars

CLC_CODE

LABEL1

LABEL2

LABEL3

RGB

0

7,344E+04

N/A

N/A

N/A

N/A

N/A

23

2,244E+04

311

Forest and semi natural areas

Forests

Broad-leaved forest

128-255-000

25

1,288E+04

313

Forest and semi natural areas

Forests

Mixed forest

077-255-000

26

6955

321

Forest and semi natural areas

Scrub and/or herbaceous vegetation associations

Natural grasslands

204-242-077

29

5567

324

Forest and semi natural areas

Scrub and/or herbaceous vegetation associations

Transitional woodland-shrub

166-242-000

41

5408

512

Water bodies

Inland waters

Water bodies

128-242-230

27

3258

322

Forest and semi natural areas

Scrub and/or herbaceous vegetation associations

Moors and heathland

166-255-128

24

2666

312

Forest and semi natural areas

Forests

Coniferous forest

000-166-000

...

...

...

...

...

...

...

40

58,12

511

Water bodies

Inland waters

Water courses

000-204-242

11

58,12

142

Artificial surfaces

Artificial, non-agricultural vegetated areas

Sport and leisure facilities

255-230-255

35

57,12

411

Wetlands

Inland wetlands

Inland marshes

166-166-255

4

50,1

122

Artificial surfaces

Industrial, commercial and transport units

Road and rail networks and associated land

204-000-000

Our frame now contains the total hectars for each category in the corine legend that has some value in the image file together with a meaningfull description..

We don't have any description for the category number 0 but this is ok beacuse we want just the information in the municipality limits that intersect the Big Valley National Park.

The corine land cover legend has a hierarchical structure which we can exploit together with deedle's functions to make some analysis.

Just to get a taste we can aggregate all the hectars by the main level in the legend.

1: 
2: 
3: 
4: 
5: 
let grossLandUse = 
    landUse
    |> Frame.aggregateRowsBy ["LABEL1"] ["Hectars"] Stats.sum
    |> Frame.indexRowsString "LABEL1"
    |> Frame.sortRowsWith "Hectars" (fun _ c -> -c)

Hectars

Forest and semi natural areas

5,505E+04

Water bodies

5466

Agricultural areas

3284

Artificial surfaces

2273

Wetlands

57,12

And to visualize the proportions let's plot it in a chart:

1: 
Chart.Pie(grossLandUse?Hectars |> Series.observations, Name = "Big Valley's gross land use") 

namespace System
namespace System.IO
namespace System.Windows
namespace System.Windows.Forms
namespace System.Drawing
namespace Deedle
Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
Multiple items
namespace FSharp.Data

--------------------
namespace Microsoft.FSharp.Data
namespace FSharp.Charting
namespace OSGeo
namespace OSGeo.GDAL
namespace OSGeo.OGR
namespace FSharp.Gdal
module UM

from FSharp.Gdal
module Raster

from FSharp.Gdal
val image : Bitmap

Full name: Land-cover.image
Multiple items
type Bitmap =
  inherit Image
  new : filename:string -> Bitmap + 11 overloads
  member Clone : rect:Rectangle * format:PixelFormat -> Bitmap + 1 overload
  member GetHbitmap : unit -> nativeint + 1 overload
  member GetHicon : unit -> nativeint
  member GetPixel : x:int * y:int -> Color
  member LockBits : rect:Rectangle * flags:ImageLockMode * format:PixelFormat -> BitmapData + 1 overload
  member MakeTransparent : unit -> unit + 1 overload
  member SetPixel : x:int * y:int * color:Color -> unit
  member SetResolution : xDpi:float32 * yDpi:float32 -> unit
  member UnlockBits : bitmapdata:BitmapData -> unit
  ...

Full name: System.Drawing.Bitmap

--------------------
Bitmap(filename: string) : unit
   (+0 other overloads)
Bitmap(stream: Stream) : unit
   (+0 other overloads)
Bitmap(original: Image) : unit
   (+0 other overloads)
Bitmap(filename: string, useIcm: bool) : unit
   (+0 other overloads)
Bitmap(type: Type, resource: string) : unit
   (+0 other overloads)
Bitmap(stream: Stream, useIcm: bool) : unit
   (+0 other overloads)
Bitmap(width: int, height: int) : unit
   (+0 other overloads)
Bitmap(original: Image, newSize: Size) : unit
   (+0 other overloads)
Bitmap(width: int, height: int, format: Imaging.PixelFormat) : unit
   (+0 other overloads)
Bitmap(width: int, height: int, g: Graphics) : unit
   (+0 other overloads)
val form : Form

Full name: Land-cover.form
Multiple items
type Form =
  inherit ContainerControl
  new : unit -> Form
  member AcceptButton : IButtonControl with get, set
  member Activate : unit -> unit
  member ActiveMdiChild : Form
  member AddOwnedForm : ownedForm:Form -> unit
  member AllowTransparency : bool with get, set
  member AutoScale : bool with get, set
  member AutoScaleBaseSize : Size with get, set
  member AutoScroll : bool with get, set
  member AutoSize : bool with get, set
  ...
  nested type ControlCollection

Full name: System.Windows.Forms.Form

--------------------
Form() : unit
type ImageLayout =
  | None = 0
  | Tile = 1
  | Center = 2
  | Stretch = 3
  | Zoom = 4

Full name: System.Windows.Forms.ImageLayout
field ImageLayout.Center = 2
Control.Show() : unit
Form.Show(owner: IWin32Window) : unit
Multiple items
module Configuration

from FSharp.Gdal

--------------------
namespace System.Configuration
val Init : unit -> unit

Full name: FSharp.Gdal.Configuration.Init
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
val dataset : Dataset

Full name: Land-cover.dataset
Multiple items
type Gdal =
  new : unit -> Gdal
  static member AllRegister : unit -> unit
  static member ApplyGeoTransform : padfGeoTransform:float[] * dfPixel:float * dfLine:float * pdfGeoX:float * pdfGeoY:float -> unit
  static member AutoCreateWarpedVRT : src_ds:Dataset * src_wkt:string * dst_wkt:string * eResampleAlg:ResampleAlg * maxerror:float -> Dataset
  static member CPLBinaryToHex : nBytes:int * pabyData:nativeint -> string
  static member CPLHexToBinary : pszHex:string * pnBytes:int -> nativeint
  static member ComputeMedianCutPCT : red:Band * green:Band * blue:Band * num_colors:int * colors:ColorTable * callback:GDALProgressFuncDelegate * callback_data:string -> int
  static member ComputeProximity : srcBand:Band * proximityBand:Band * options:string[] * callback:GDALProgressFuncDelegate * callback_data:string -> int
  static member ContourGenerate : srcBand:Band * contourInterval:float * contourBase:float * fixedLevelCount:int * fixedLevels:float[] * useNoData:int * noDataValue:float * dstLayer:Layer * idField:int * elevField:int * callback:GDALProgressFuncDelegate * callback_data:string -> int
  static member DataTypeIsComplex : eDataType:DataType -> int
  ...
  nested type GDALErrorHandlerDelegate
  nested type GDALProgressFuncDelegate

Full name: OSGeo.GDAL.Gdal

--------------------
Gdal() : unit
Gdal.OpenShared(utf8_path: string, eAccess: Access) : Dataset
type Access =
  | GA_ReadOnly = 0
  | GA_Update = 1

Full name: OSGeo.GDAL.Access
field Access.GA_ReadOnly = 0
val mutable geotransform : float []

Full name: Land-cover.geotransform
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<_>
Dataset.GetGeoTransform(argout: float []) : unit
val topLeftX : float

Full name: Land-cover.topLeftX
val topLeftY : float

Full name: Land-cover.topLeftY
val westEastPixelResolution : float<m>

Full name: Land-cover.westEastPixelResolution
[<Measure>]
type m

Full name: FSharp.Gdal.UM.m
val northSouthPixelResolution : float<m>

Full name: Land-cover.northSouthPixelResolution
type Math =
  static val PI : float
  static val E : float
  static member Abs : value:sbyte -> sbyte + 6 overloads
  static member Acos : d:float -> float
  static member Asin : d:float -> float
  static member Atan : d:float -> float
  static member Atan2 : y:float * x:float -> float
  static member BigMul : a:int * b:int -> int64
  static member Ceiling : d:decimal -> decimal + 1 overload
  static member Cos : d:float -> float
  ...

Full name: System.Math
Math.Abs(value: decimal) : decimal
Math.Abs(value: float) : float
Math.Abs(value: float32) : float32
Math.Abs(value: int64) : int64
Math.Abs(value: int) : int
Math.Abs(value: int16) : int16
Math.Abs(value: sbyte) : sbyte
val xSize : int

Full name: Land-cover.xSize
property Dataset.RasterXSize: int
val ySize : int

Full name: Land-cover.ySize
property Dataset.RasterYSize: int
val bands : int

Full name: Land-cover.bands
property Dataset.RasterCount: int
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
Dataset.GetDriver() : Driver
Dataset.GetProjection() : string
val pixelArea : float<ha>

Full name: Land-cover.pixelArea
val mqToHa : float<ha/m ^ 2>

Full name: FSharp.Gdal.UM.mqToHa
val totalArea : float<ha>

Full name: Land-cover.totalArea
val values : ((int * int) * float option) list

Full name: Land-cover.values
val x : int
val y : int
val getImgValue : geotransform:float [] -> dataset:Dataset -> xPixel:int * yLine:int -> float option

Full name: FSharp.Gdal.Raster.getImgValue
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member GetSlice : startIndex:int option * endIndex:int option -> 'T list
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val concat : lists:seq<'T list> -> 'T list

Full name: Microsoft.FSharp.Collections.List.concat
val printf : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printf
Object.ToString() : string
val hectarsByCategory : Frame<string,string>

Full name: Land-cover.hectarsByCategory
val groupBy : projection:('T -> 'Key) -> list:'T list -> ('Key * 'T list) list (requires equality)

Full name: Microsoft.FSharp.Collections.List.groupBy
val c : int * int
val v : float option
val map : mapping:('T -> 'U) -> list:'T list -> 'U list

Full name: Microsoft.FSharp.Collections.List.map
val xs : ((int * int) * float option) list
property Option.Value: float
Multiple items
val string : value:'T -> string

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

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

Full name: Microsoft.FSharp.Core.string
property List.Length: int
val sortByDescending : projection:('T -> 'Key) -> list:'T list -> 'T list (requires comparison)

Full name: Microsoft.FSharp.Collections.List.sortByDescending
val v : string
val c : string
val l : float<ha>
Multiple items
module Frame

from Deedle

--------------------
type Frame =
  static member ReadReader : reader:IDataReader -> Frame<int,string>
  static member CustomExpanders : Dictionary<Type,Func<obj,seq<string * Type * obj>>>
  static member NonExpandableInterfaces : List<Type>
  static member NonExpandableTypes : HashSet<Type>

Full name: Deedle.Frame

--------------------
type Frame<'TRowKey,'TColumnKey (requires equality and equality)> =
  interface IDynamicMetaObjectProvider
  interface INotifyCollectionChanged
  interface IFsiFormattable
  interface IFrame
  new : names:seq<'TColumnKey> * columns:seq<ISeries<'TRowKey>> -> Frame<'TRowKey,'TColumnKey>
  new : rowIndex:IIndex<'TRowKey> * columnIndex:IIndex<'TColumnKey> * data:IVector<IVector> * indexBuilder:IIndexBuilder * vectorBuilder:IVectorBuilder -> Frame<'TRowKey,'TColumnKey>
  member AddColumn : column:'TColumnKey * series:ISeries<'TRowKey> -> unit
  member AddColumn : column:'TColumnKey * series:seq<'V> -> unit
  member AddColumn : column:'TColumnKey * series:ISeries<'TRowKey> * lookup:Lookup -> unit
  member AddColumn : column:'TColumnKey * series:seq<'V> * lookup:Lookup -> unit
  ...

Full name: Deedle.Frame<_,_>

--------------------
new : names:seq<'TColumnKey> * columns:seq<ISeries<'TRowKey>> -> Frame<'TRowKey,'TColumnKey>
new : rowIndex:Indices.IIndex<'TRowKey> * columnIndex:Indices.IIndex<'TColumnKey> * data:IVector<IVector> * indexBuilder:Indices.IIndexBuilder * vectorBuilder:Vectors.IVectorBuilder -> Frame<'TRowKey,'TColumnKey>
static member Frame.ofValues : values:seq<'R * 'C * 'V> -> Frame<'R,'C> (requires equality and equality)
val sumHectars : float

Full name: Land-cover.sumHectars
static member FrameExtensions.Sum : frame:Frame<'R,'C> -> Series<'C,float> (requires equality and equality)
val corineLegend : Frame<string,string>

Full name: Land-cover.corineLegend
static member Frame.ReadCsv : path:string * ?hasHeaders:bool * ?inferTypes:bool * ?inferRows:int * ?schema:string * ?separators:string * ?culture:string * ?maxRows:int * ?missingValues:string [] -> Frame<int,string>
static member Frame.ReadCsv : stream:Stream * ?hasHeaders:bool * ?inferTypes:bool * ?inferRows:int * ?schema:string * ?separators:string * ?culture:string * ?maxRows:int * ?missingValues:string [] -> Frame<int,string>
static member Frame.ReadCsv : reader:TextReader * ?hasHeaders:bool * ?inferTypes:bool * ?inferRows:int * ?schema:string * ?separators:string * ?culture:string * ?maxRows:int * ?missingValues:string [] -> Frame<int,string>
static member Frame.ReadCsv : path:string * indexCol:string * ?hasHeaders:bool * ?inferTypes:bool * ?inferRows:int * ?schema:string * ?separators:string * ?culture:string * ?maxRows:int * ?missingValues:string [] -> Frame<'R,string> (requires equality)
val indexRowsString : column:'C -> frame:Frame<'R1,'C> -> Frame<string,'C> (requires equality and equality)

Full name: Deedle.Frame.indexRowsString
val landUse : Frame<string,string>

Full name: Land-cover.landUse
member Frame.Join : otherFrame:Frame<'TRowKey,'TColumnKey> -> Frame<'TRowKey,'TColumnKey>
member Frame.Join : colKey:'TColumnKey * series:Series<'TRowKey,'V> -> Frame<'TRowKey,'TColumnKey>
member Frame.Join : otherFrame:Frame<'TRowKey,'TColumnKey> * kind:JoinKind -> Frame<'TRowKey,'TColumnKey>
member Frame.Join : colKey:'TColumnKey * series:Series<'TRowKey,'V> * kind:JoinKind -> Frame<'TRowKey,'TColumnKey>
member Frame.Join : otherFrame:Frame<'TRowKey,'TColumnKey> * kind:JoinKind * lookup:Lookup -> Frame<'TRowKey,'TColumnKey>
member Frame.Join : colKey:'TColumnKey * series:Series<'TRowKey,'V> * kind:JoinKind * lookup:Lookup -> Frame<'TRowKey,'TColumnKey>
type JoinKind =
  | Outer = 0
  | Inner = 1
  | Left = 2
  | Right = 3

Full name: Deedle.JoinKind
JoinKind.Left: JoinKind = 2
val grossLandUse : Frame<string,string>

Full name: Land-cover.grossLandUse
val aggregateRowsBy : groupBy:seq<'C> -> aggBy:seq<'C> -> aggFunc:(Series<'R,'V1> -> 'V2) -> frame:Frame<'R,'C> -> Frame<int,'C> (requires equality and equality)

Full name: Deedle.Frame.aggregateRowsBy
type Stats =
  static member count : frame:Frame<'R,'C> -> Series<'C,int> (requires equality and equality)
  static member count : series:Series<'K,'V> -> int (requires equality)
  static member expandingCount : series:Series<'K,float> -> Series<'K,float> (requires equality)
  static member expandingKurt : series:Series<'K,float> -> Series<'K,float> (requires equality)
  static member expandingMax : series:Series<'K,float> -> Series<'K,float> (requires equality)
  static member expandingMean : series:Series<'K,float> -> Series<'K,float> (requires equality)
  static member expandingMin : series:Series<'K,float> -> Series<'K,float> (requires equality)
  static member expandingSkew : series:Series<'K,float> -> Series<'K,float> (requires equality)
  static member expandingStdDev : series:Series<'K,float> -> Series<'K,float> (requires equality)
  static member expandingSum : series:Series<'K,float> -> Series<'K,float> (requires equality)
  ...

Full name: Deedle.Stats
static member Stats.sum : frame:Frame<'R,'C> -> Series<'C,float> (requires equality and equality)
static member Stats.sum : series:Series<'K,float> -> float (requires equality)
val sortRowsWith : colKey:'C -> compareFunc:('a -> 'a -> int) -> frame:Frame<'R,'C> -> Frame<'R,'C> (requires equality and equality)

Full name: Deedle.Frame.sortRowsWith
val c : int
type Chart =
  static member Area : data:seq<#value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart
  static member Area : data:seq<#key * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart
  static member Bar : data:seq<#value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart
  static member Bar : data:seq<#key * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart
  static member BoxPlotFromData : data:seq<#key * #seq<'a2>> * ?Name:string * ?Title:string * ?Color:Color * ?XTitle:string * ?YTitle:string * ?Percentile:int * ?ShowAverage:bool * ?ShowMedian:bool * ?ShowUnusualValues:bool * ?WhiskerPercentile:int -> GenericChart (requires 'a2 :> value)
  static member BoxPlotFromStatistics : data:seq<#key * #value * #value * #value * #value * #value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string * ?Percentile:int * ?ShowAverage:bool * ?ShowMedian:bool * ?ShowUnusualValues:bool * ?WhiskerPercentile:int -> GenericChart
  static member Bubble : data:seq<#value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string * ?BubbleMaxSize:int * ?BubbleMinSize:int * ?BubbleScaleMax:float * ?BubbleScaleMin:float * ?UseSizeForLabel:bool -> GenericChart
  static member Bubble : data:seq<#key * #value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string * ?BubbleMaxSize:int * ?BubbleMinSize:int * ?BubbleScaleMax:float * ?BubbleScaleMin:float * ?UseSizeForLabel:bool -> GenericChart
  static member Candlestick : data:seq<#value * #value * #value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> CandlestickChart
  static member Candlestick : data:seq<#key * #value * #value * #value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> CandlestickChart
  ...

Full name: FSharp.Charting.Chart
static member Chart.Pie : data:Series<'K,#value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> ChartTypes.PieChart (requires equality and 'K :> key)
static member Chart.Pie : data:seq<#value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> ChartTypes.PieChart
static member Chart.Pie : data:seq<#key * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> ChartTypes.PieChart
Multiple items
module Series

from Deedle

--------------------
type Series =
  static member ofNullables : values:seq<Nullable<'a0>> -> Series<int,'a0> (requires default constructor and value type and 'a0 :> ValueType)
  static member ofObservations : observations:seq<'a0 * 'a1> -> Series<'a0,'a1> (requires equality)
  static member ofOptionalObservations : observations:seq<'K * 'a1 option> -> Series<'K,'a1> (requires equality)
  static member ofValues : values:seq<'b> -> Series<int,'b>

Full name: Deedle.F# Series extensions.Series

--------------------
type Series<'K,'V (requires equality)> =
  interface IFsiFormattable
  interface ISeries<'K>
  new : pairs:seq<KeyValuePair<'K,'V>> -> Series<'K,'V>
  new : keys:'K [] * values:'V [] -> Series<'K,'V>
  new : keys:seq<'K> * values:seq<'V> -> Series<'K,'V>
  new : index:IIndex<'K> * vector:IVector<'V> * vectorBuilder:IVectorBuilder * indexBuilder:IIndexBuilder -> Series<'K,'V>
  member After : lowerExclusive:'K -> Series<'K,'V>
  member Aggregate : aggregation:Aggregation<'K> * observationSelector:Func<DataSegment<Series<'K,'V>>,KeyValuePair<'TNewKey,OptionalValue<'R>>> -> Series<'TNewKey,'R> (requires equality)
  member Aggregate : aggregation:Aggregation<'K> * keySelector:Func<DataSegment<Series<'K,'V>>,'TNewKey> * valueSelector:Func<DataSegment<Series<'K,'V>>,OptionalValue<'R>> -> Series<'TNewKey,'R> (requires equality)
  member AsyncMaterialize : unit -> Async<Series<'K,'V>>
  ...

Full name: Deedle.Series<_,_>

--------------------
new : pairs:seq<Collections.Generic.KeyValuePair<'K,'V>> -> Series<'K,'V>
new : keys:seq<'K> * values:seq<'V> -> Series<'K,'V>
new : keys:'K [] * values:'V [] -> Series<'K,'V>
new : index:Indices.IIndex<'K> * vector:IVector<'V> * vectorBuilder:Vectors.IVectorBuilder * indexBuilder:Indices.IIndexBuilder -> Series<'K,'V>
val observations : series:Series<'K,'T> -> seq<'K * 'T> (requires equality)

Full name: Deedle.Series.observations
namespace Fsharp.Gdal
F# Project
Fork me on GitHub