namespace Plotly.NET
open System
open Newtonsoft.Json
/// HTML template for Plotly.js
module HTML =
let doc =
"""
[CHART]
[DESCRIPTION]
"""
// let chart =
// """
//"""
let chart =
let newScript = new System.Text.StringBuilder()
newScript.AppendLine("""""") |> ignore
newScript.AppendLine("") |> ignore
newScript.ToString()
let description ="""
[DESCRIPTIONHEADING]
[DESCRIPTIONTEXT]
"""
let staticChart =
"""
"""
module ChartDescription =
type Description =
{
Heading : string
Text : string
}
let toDescriptionHtml (d:Description) =
HTML.description
.Replace("[DESCRIPTIONHEADING]",d.Heading)
.Replace("[DESCRIPTIONTEXT]",d.Text)
/// Module to represent a GenericChart
module GenericChart =
open Trace
open ChartDescription
type Figure =
{
[]
Data: Trace list
[]
Layout: Layout
}
static member create data layout = {Data = data; Layout = layout}
//TO-DO refactor as type with static members to remove verbose top namespace from 'GenericChart.GenericChart'
type GenericChart =
| Chart of Trace * Layout * Config
| MultiChart of Trace list * Layout * Config
let toFigure (gChart:GenericChart) =
match gChart with
| Chart (trace,layout,_) -> Figure.create [trace] layout
| MultiChart (traces,layout,_) -> Figure.create traces layout
let fromFigure (fig:Figure) =
let traces = fig.Data
let layout = fig.Layout
if traces.Length <> 1 then
MultiChart (traces,layout,Config())
else
Chart (traces.[0], layout, Config())
let getTraces gChart =
match gChart with
| Chart (trace,_,_) -> [trace]
| MultiChart (traces,_,_) -> traces
let getLayout gChart =
match gChart with
| Chart (_,layout,_) -> layout
| MultiChart (_,layout,_) -> layout
let setLayout layout gChart =
match gChart with
| Chart (t,_,c) -> Chart (t,layout,c)
| MultiChart (t,_,c) -> MultiChart (t,layout,c)
// Adds a Layout function to the GenericChart
let addLayout layout gChart =
match gChart with
| Chart (trace,l',c) ->
Chart (trace, (DynObj.combine l' layout |> unbox),c )
| MultiChart (traces,l',c) ->
MultiChart (traces, (DynObj.combine l' layout |> unbox),c)
/// Returns a tuple containing the width and height of a GenericChart's layout if the property is set, otherwise returns None
let tryGetLayoutSize gChart =
let layout = getLayout gChart
let width,height =
layout.TryGetTypedValue "width",
layout.TryGetTypedValue "height"
match (width,height) with
|(Some w, Some h) -> Some (w,h)
|_ -> None
let getConfig gChart =
match gChart with
| Chart (_,_,c) -> c
| MultiChart (_,_,c) -> c
let setConfig config gChart =
match gChart with
| Chart (t,l,_) -> Chart (t,l,config)
| MultiChart (t,l,_) -> MultiChart (t,l,config)
// // Adds multiple Layout functions to the GenericChart
// let addLayouts layouts gChart =
// match gChart with
// | Chart (trace,_) ->
// let l' = getLayouts gChart
// Chart (trace,Some (layouts@l'))
// | MultiChart (traces,_) ->
// let l' = getLayouts gChart
// MultiChart (traces, Some (layouts@l'))
// Combines two GenericChart
let combine(gCharts:seq) =
let combineLayouts (first:Layout) (second:Layout) =
DynObj.combine first second |> unbox
let combineConfigs (first:Config) (second:Config) =
DynObj.combine first second |> unbox
gCharts
|> Seq.reduce (fun acc elem ->
match acc,elem with
| MultiChart (traces,l1,c1),Chart (trace,l2,c2) ->
MultiChart (List.append traces [trace], combineLayouts l1 l2, combineConfigs c1 c2)
| MultiChart (traces1,l1,c1),MultiChart (traces2,l2,c2) ->
MultiChart (List.append traces1 traces2,combineLayouts l1 l2, combineConfigs c1 c2)
| Chart (trace1,l1,c1),Chart (trace2,l2,c2) ->
MultiChart ([trace1;trace2],combineLayouts l1 l2, combineConfigs c1 c2)
| Chart (trace,l1,c1),MultiChart (traces,l2,c2) ->
MultiChart (List.append [trace] traces ,combineLayouts l1 l2, combineConfigs c1 c2)
)
// let private materialzeLayout (layout:(Layout -> Layout) list) =
// let rec reduce fl v =
// match fl with
// | h::t -> reduce t (h v)
// | [] -> v
// // Attention order ov layout functions is reverse
// let l' = layout |> List.rev
// reduce l' (Layout())
/// Converts a GenericChart to it HTML representation. The div layer has a default size of 600 if not specified otherwise.
let toChartHTML gChart =
let guid = Guid.NewGuid().ToString()
let tracesJson =
getTraces gChart
|> JsonConvert.SerializeObject
let layoutJson =
getLayout gChart
|> JsonConvert.SerializeObject
let configJson =
getConfig gChart
|> JsonConvert.SerializeObject
let dims = tryGetLayoutSize gChart
let width,height =
match dims with
|Some (w,h) -> w,h
|None -> 600., 600.
let html =
HTML.chart
//.Replace("style=\"width: [WIDTH]px; height: [HEIGHT]px;\"","style=\"width: 600px; height: 600px;\"")
.Replace("[WIDTH]", string width)
.Replace("[HEIGHT]", string height)
.Replace("[ID]", guid)
.Replace("[DATA]", tracesJson)
.Replace("[LAYOUT]", layoutJson)
.Replace("[CONFIG]", configJson)
html
/// Converts a GenericChart to it HTML representation and set the size of the div
let toChartHtmlWithSize (width:int) (height:int) (gChart:GenericChart) =
let guid = Guid.NewGuid().ToString()
let tracesJson =
getTraces gChart
|> JsonConvert.SerializeObject
let layoutJson =
getLayout gChart
|> JsonConvert.SerializeObject
let configJson =
getConfig gChart
|> JsonConvert.SerializeObject
let html =
HTML.chart
.Replace("[ID]", guid)
.Replace("[WIDTH]", string width )
.Replace("[HEIGHT]", string height)
.Replace("[DATA]", tracesJson)
.Replace("[LAYOUT]", layoutJson)
.Replace("[CONFIG]", configJson)
html
let toEmbeddedHtmlWithDescription (description:Description) gChart =
let chartMarkup =
toChartHTML gChart
let descriptionMarkup =
toDescriptionHtml description
HTML.doc
.Replace("[CHART]", chartMarkup)
.Replace("[DESCRIPTION]", descriptionMarkup)
/// Converts a GenericChart to it HTML representation and embeds it into a html page.
let toEmbeddedHTML gChart =
let chartMarkup =
toChartHTML gChart
HTML.doc
.Replace("[CHART]", chartMarkup)
.Replace("[DESCRIPTION]", "")
/// Converts a GenericChart to its Image representation
let toChartImage (format:StyleParam.ImageFormat) gChart =
let guid = Guid.NewGuid().ToString()
let tracesJson =
getTraces gChart
|> JsonConvert.SerializeObject
let layoutJson =
getLayout gChart
|> JsonConvert.SerializeObject
let html =
HTML.staticChart
//.Replace("style=\"width: [WIDTH]px; height: [HEIGHT]px;\"","style=\"width: 600px; height: 600px;\"")
.Replace("[WIDTH]", string 600 )
.Replace("[HEIGHT]", string 600)
.Replace("[ID]", guid)
.Replace("[DATA]", tracesJson)
.Replace("[LAYOUT]", layoutJson)
.Replace("[IMAGEFORMAT]",format.ToString().ToLower())
.Replace("[CONFIG]","{}")
html
/// Converts a GenericChart to an image and embeds it into a html page
let toEmbeddedImage (format:StyleParam.ImageFormat) gChart =
let html =
let chartMarkup =
toChartImage format gChart
HTML.doc
.Replace("[CHART]", chartMarkup)
.Replace("[CONFIG]","{}")
html
/// Creates a new GenericChart whose traces are the results of applying the given function to each of the trace of the GenericChart.
let mapTrace f gChart =
match gChart with
| Chart (trace,layout,config) -> Chart (f trace,layout,config)
| MultiChart (traces,layout,config) -> MultiChart (traces |> List.map f,layout,config)
/// Creates a new GenericChart whose traces are the results of applying the given function to each of the trace of the GenericChart.
/// The integer index passed to the function indicates the index (from 0) of element being transformed.
let mapiTrace f gChart =
match gChart with
| Chart (trace,layout,config) -> Chart (f 0 trace,layout,config)
| MultiChart (traces,layout,config) -> MultiChart (traces |> List.mapi f,layout,config)
/// Returns the number of traces within the GenericChart
let countTrace gChart =
match gChart with
| Chart (_) -> 1
| MultiChart (traces,_,_) -> traces |> Seq.length
/// Creates a new GenericChart whose traces are the results of applying the given function to each of the trace of the GenericChart.
let existsTrace (f:Trace->bool) gChart =
match gChart with
| Chart (trace,_,_) -> f trace
| MultiChart (traces,_,_) -> traces |> List.exists f
/// Converts from a trace object and a layout object into GenericChart
let ofTraceObject trace = //layout =
GenericChart.Chart(trace, Layout(), Config())
/// Converts from a list of trace objects and a layout object into GenericChart
let ofTraceObjects traces = // layout =
GenericChart.MultiChart(traces, Layout(), Config())
let mapLayout f gChart =
match gChart with
| Chart (trace,layout,config) -> Chart (trace,f layout,config)
| MultiChart (traces,layout,config) -> MultiChart (traces,f layout,config)