Skip to content

Refactor Chart.Stack #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docsrc/tools/generate.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ let rec copyRecursive dir1 dir2 =
copyRecursive subdir1 subdir2
for file in Directory.EnumerateFiles dir1 do
File.Copy(file, file.Replace(dir1, dir2), true)

// Web site location for the generated documentation
let website = "https://muehlhaus.github.io/FSharp.Plotly/"

Expand Down
8 changes: 4 additions & 4 deletions src/FSharp.Plotly.WPF/AssemblyInfo.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ open System.Reflection
[<assembly: AssemblyTitleAttribute("FSharp.Plotly.WPF")>]
[<assembly: AssemblyProductAttribute("FSharp.Plotly")>]
[<assembly: AssemblyDescriptionAttribute("A F# interactive charting library using plotly.js")>]
[<assembly: AssemblyVersionAttribute("1.2.2")>]
[<assembly: AssemblyFileVersionAttribute("1.2.2")>]
[<assembly: AssemblyVersionAttribute("1.2.3")>]
[<assembly: AssemblyFileVersionAttribute("1.2.3")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FSharp.Plotly.WPF"
let [<Literal>] AssemblyProduct = "FSharp.Plotly"
let [<Literal>] AssemblyDescription = "A F# interactive charting library using plotly.js"
let [<Literal>] AssemblyVersion = "1.2.2"
let [<Literal>] AssemblyFileVersion = "1.2.2"
let [<Literal>] AssemblyVersion = "1.2.3"
let [<Literal>] AssemblyFileVersion = "1.2.3"
8 changes: 4 additions & 4 deletions src/FSharp.Plotly/AssemblyInfo.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ open System.Reflection
[<assembly: AssemblyTitleAttribute("FSharp.Plotly")>]
[<assembly: AssemblyProductAttribute("FSharp.Plotly")>]
[<assembly: AssemblyDescriptionAttribute("A F# interactive charting library using plotly.js")>]
[<assembly: AssemblyVersionAttribute("1.2.2")>]
[<assembly: AssemblyFileVersionAttribute("1.2.2")>]
[<assembly: AssemblyVersionAttribute("1.2.3")>]
[<assembly: AssemblyFileVersionAttribute("1.2.3")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FSharp.Plotly"
let [<Literal>] AssemblyProduct = "FSharp.Plotly"
let [<Literal>] AssemblyDescription = "A F# interactive charting library using plotly.js"
let [<Literal>] AssemblyVersion = "1.2.2"
let [<Literal>] AssemblyFileVersion = "1.2.2"
let [<Literal>] AssemblyVersion = "1.2.3"
let [<Literal>] AssemblyFileVersion = "1.2.3"
177 changes: 177 additions & 0 deletions src/FSharp.Plotly/ChartExtensions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,55 @@ module ChartExtensions =
(fun (ch:GenericChart) ->
GenericChart.addLayout layout ch)

// Set the LayoutGrid options of a Chart
[<CompiledName("WithLayoutGrid")>]
static member withLayoutGrid(layoutGrid:LayoutGrid) =
(fun (ch:GenericChart) ->
let layout =
GenericChart.getLayout ch
|> Layout.SetLayoutGrid layoutGrid
GenericChart.setLayout layout ch)

// Set the LayoutGrid options of a Chart
[<CompiledName("WithLayoutGridStyle")>]
static member withLayoutGridStyle([<Optional;DefaultParameterValue(null)>]?SubPlots : StyleParam.AxisId [] [],
[<Optional;DefaultParameterValue(null)>]?XAxes : StyleParam.AxisId [],
[<Optional;DefaultParameterValue(null)>]?YAxes : StyleParam.AxisId [],
[<Optional;DefaultParameterValue(null)>]?Rows : int,
[<Optional;DefaultParameterValue(null)>]?Columns : int,
[<Optional;DefaultParameterValue(null)>]?RowOrder : StyleParam.LayoutGridRowOrder,
[<Optional;DefaultParameterValue(null)>]?Pattern : StyleParam.LayoutGridPattern,
[<Optional;DefaultParameterValue(null)>]?XGap : float,
[<Optional;DefaultParameterValue(null)>]?YGap : float,
[<Optional;DefaultParameterValue(null)>]?Domain : Domain,
[<Optional;DefaultParameterValue(null)>]?XSide : StyleParam.LayoutGridXSide,
[<Optional;DefaultParameterValue(null)>]?YSide : StyleParam.LayoutGridYSide
) =
(fun (ch:GenericChart) ->
let layout = GenericChart.getLayout ch
let updatedGrid =
let currentGrid =
match layout.TryGetTypedValue<LayoutGrid> "grid" with
| Some grid -> grid
| None -> LayoutGrid()
currentGrid
|> LayoutGrid.style(
?SubPlots = SubPlots,
?XAxes = XAxes ,
?YAxes = YAxes ,
?Rows = Rows ,
?Columns = Columns ,
?RowOrder = RowOrder,
?Pattern = Pattern ,
?XGap = XGap ,
?YGap = YGap ,
?Domain = Domain ,
?XSide = XSide ,
?YSide = YSide
)
let updatedLayout = layout |> Layout.SetLayoutGrid updatedGrid
GenericChart.setLayout updatedLayout ch)

[<CompiledName("WithConfig")>]
static member withConfig (config:Config) =
(fun (ch:GenericChart) ->
Expand Down Expand Up @@ -441,8 +490,136 @@ module ChartExtensions =
static member Combine(gCharts:seq<GenericChart>) =
GenericChart.combine gCharts

///Creates a Grid containing the given plots as subplots with the dimensions of the input (amount of columns equal to the largest inner sequence).
///
///Parameters:
///
///sharedAxes : Wether the subplots share one xAxis per column and one yAxis per row or not. (default:TopToBottom)
///
///rowOrder : the order in which the rows of the grid will be rendered (default:false)
///
///xGap : The space between columns of the grid relative to the x dimension of the grid
///
///yGap : The space between rows of the grid relative to the y dimension of the grid
///
///Use Chart.withLayoutGridStyle to further style the grid object contained in the returned chart.
[<CompiledName("Grid")>]
static member Grid ((gCharts:seq<#seq<GenericChart>>),
[<Optional;DefaultParameterValue(false)>]?sharedAxes:bool,
[<Optional;DefaultParameterValue(null)>]?rowOrder:StyleParam.LayoutGridRowOrder,
[<Optional;DefaultParameterValue(0.05)>] ?xGap,
[<Optional;DefaultParameterValue(0.05)>] ?yGap
) =

let sharedAxes = defaultArg sharedAxes false
let rowOrder = defaultArg rowOrder StyleParam.LayoutGridRowOrder.TopToBottom
let xGap = defaultArg xGap 0.05
let yGap = defaultArg yGap 0.05

let nRows = Seq.length gCharts
let nCols = gCharts |> Seq.maxBy Seq.length |> Seq.length
let pattern = if sharedAxes then StyleParam.LayoutGridPattern.Coupled else StyleParam.LayoutGridPattern.Independent

let generateDomainRanges (count:int) (gap:float) =
[|0. .. (1. / (float count)) .. 1.|]
|> fun doms ->
doms
|> Array.windowed 2
|> Array.mapi (fun i x ->
if i = 0 then
x.[0], (x.[1] - (gap / 2.))
elif i = (doms.Length - 1) then
(x.[0] + (gap / 2.)),x.[1]
else
(x.[0] + (gap / 2.)) , (x.[1] - (gap / 2.))
)

let yDomains = generateDomainRanges nRows yGap
let xDomains = generateDomainRanges nCols xGap

gCharts
|> Seq.mapi (fun rowIndex row ->
row |> Seq.mapi (fun colIndex gChart ->
let xdomain = xDomains.[colIndex]
let ydomain = yDomains.[rowIndex]

let newXIndex, newYIndex =
(if sharedAxes then colIndex + 1 else ((nRows * rowIndex) + (colIndex + 1))),
(if sharedAxes then rowIndex + 1 else ((nRows * rowIndex) + (colIndex + 1)))


let xaxis,yaxis,layout =
let layout = GenericChart.getLayout gChart
let xAxisName, yAxisName = StyleParam.AxisId.X 1 |> StyleParam.AxisId.toString, StyleParam.AxisId.Y 1 |> StyleParam.AxisId.toString

let updateXAxis index domain axis =
axis |> Axis.LinearAxis.style(Anchor=StyleParam.AxisAnchorId.X index,Domain=StyleParam.Range.MinMax domain)

let updateYAxis index domain axis =
axis |> Axis.LinearAxis.style(Anchor=StyleParam.AxisAnchorId.Y index,Domain=StyleParam.Range.MinMax domain)
match (layout.TryGetTypedValue<Axis.LinearAxis> xAxisName),(layout.TryGetTypedValue<Axis.LinearAxis> yAxisName) with
| Some x, Some y ->
// remove axis
DynObj.remove layout xAxisName
DynObj.remove layout yAxisName

x |> updateXAxis newXIndex xdomain,
y |> updateYAxis newYIndex ydomain,
layout

| Some x, None ->
// remove x - axis
DynObj.remove layout xAxisName

x |> updateXAxis newXIndex xdomain,
Axis.LinearAxis.init(Anchor=StyleParam.AxisAnchorId.Y newYIndex ,Domain=StyleParam.Range.MinMax ydomain),
layout

| None, Some y ->
// remove y - axis
DynObj.remove layout yAxisName

Axis.LinearAxis.init(Anchor=StyleParam.AxisAnchorId.X newXIndex,Domain=StyleParam.Range.MinMax xdomain),
y |> updateYAxis newYIndex ydomain,
layout
| None, None ->
Axis.LinearAxis.init(Anchor=StyleParam.AxisAnchorId.X newXIndex,Domain=StyleParam.Range.MinMax xdomain),
Axis.LinearAxis.init(Anchor=StyleParam.AxisAnchorId.Y newYIndex,Domain=StyleParam.Range.MinMax ydomain),
layout

gChart
|> GenericChart.setLayout layout
|> Chart.withAxisAnchor(X=newXIndex,Y=newYIndex)
|> Chart.withX_Axis(xaxis,newXIndex)
|> Chart.withY_Axis(yaxis,newYIndex)
)
)
|> Seq.map Chart.Combine
|> Chart.Combine
|> Chart.withLayoutGrid(
LayoutGrid.init(
Rows=nRows,Columns=nCols,XGap= xGap,YGap= yGap,Pattern=pattern,RowOrder=rowOrder
)
)

///Creates a chart stack from the input charts by stacking them on top of each other starting from the first chart.
///
///Parameters:
///
///sharedAxis : wether the stack has a shared x axis (default:true)
[<CompiledName("SingleStack")>]
static member SingleStack (charts:#seq<GenericChart>,
[<Optional;DefaultParameterValue(true)>] ?sharedXAxis:bool) =

let sharedAxis = defaultArg sharedXAxis true
let singleCol = seq {
for i = 0 to ((Seq.length charts) - 1) do
yield seq {Seq.item i charts}
}
Chart.Grid(gCharts = singleCol, sharedAxes = sharedAxis, rowOrder = StyleParam.LayoutGridRowOrder.BottomToTop)

/// Create a combined chart with the given charts merged
[<Obsolete("Use Chart.Grid for multi column grid charts or singleStack for one-column stacked charts.")>]
[<CompiledName("Stack")>]
static member Stack ( [<Optional;DefaultParameterValue(null)>] ?Columns:int,
[<Optional;DefaultParameterValue(null)>] ?Space) =
Expand Down
2 changes: 2 additions & 0 deletions src/FSharp.Plotly/FSharp.Plotly.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
<Compile Include="Table.fs" />
<Compile Include="Trace.fs" />
<Compile Include="Trace3d.fs" />
<Compile Include="LayoutGrid.fs" />
<Compile Include="Layout.fs" />
<Compile Include="Config.fs" />
<Compile Include="GenericChart.fs" />
Expand All @@ -57,6 +58,7 @@
<Compile Include="CandelstickExtension.fs" />
<Compile Include="SankeyExtension.fs" />
<Compile Include="Templates.fs" />
<None Include="Playground.fsx" />
<None Include="TestScript.fsx" />
<None Include="paket.references" />
<None Include="paket.template" />
Expand Down
19 changes: 19 additions & 0 deletions src/FSharp.Plotly/Layout.fs
Original file line number Diff line number Diff line change
Expand Up @@ -388,4 +388,23 @@ type Layout() =
layout
)

static member SetLayoutGrid
(
grid: LayoutGrid
) =
(fun (layout:Layout) ->
grid |> DynObj.setValue layout "grid"
layout
)


static member GetLayoutGrid
(
grid: LayoutGrid
) =
(fun (layout:Layout) ->
grid |> DynObj.setValue layout "grid"
layout
)


Loading