From 0c7cdaa8d0d77ec4b7049c6f33c68dce71d31adf Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Mon, 27 Sep 2021 07:44:04 +0200 Subject: [PATCH 1/6] Add Chart.Indicator and related Trace/Layout objects --- src/Plotly.NET/ChartAPI/ChartDomain.fs | 51 ++++ .../CommonAbstractions/StyleParams.fs | 55 ++++ .../ObjectAbstractions/Common/LinearAxis.fs | 101 +++++- src/Plotly.NET/Playground.fsx | 32 ++ src/Plotly.NET/Plotly.NET.fsproj | 1 + .../Traces/ObjectAbstractions/Indicator.fs | 287 ++++++++++++++++++ src/Plotly.NET/Traces/TraceDomain.fs | 43 +++ 7 files changed, 563 insertions(+), 7 deletions(-) create mode 100644 src/Plotly.NET/Traces/ObjectAbstractions/Indicator.fs diff --git a/src/Plotly.NET/ChartAPI/ChartDomain.fs b/src/Plotly.NET/ChartAPI/ChartDomain.fs index 368a6d558..fa1e75249 100644 --- a/src/Plotly.NET/ChartAPI/ChartDomain.fs +++ b/src/Plotly.NET/ChartAPI/ChartDomain.fs @@ -509,3 +509,54 @@ module ChartDomain = ) ) |> GenericChart.ofTraceObject + + /// creates table out of header sequence and row sequences + [] + static member Indicator + ( + value : #IConvertible, + mode : StyleParam.IndicatorMode, + [] ?Range : StyleParam.Range, + [] ?Name : string, + [] ?Title : string, + [] ?ShowLegend : bool, + [] ?Domain : Domain, + [] ?Align : StyleParam.IndicatorAlignment, + [] ?DeltaReference : #IConvertible, + [] ?Delta : IndicatorDelta, + [] ?Number : IndicatorNumber, + [] ?GaugeShape : StyleParam.IndicatorGaugeShape, + [] ?Gauge : IndicatorGauge, + [] ?ShowGaugeAxis : bool, + [] ?GaugeAxis : LinearAxis + ) = + let axis = + GaugeAxis + |> Option.defaultValue(LinearAxis.init()) + |> LinearAxis.style(?Range=Range, ?Visible=ShowGaugeAxis) + + let gauge = + Gauge + |> Option.defaultValue(IndicatorGauge.init()) + |> IndicatorGauge.style(Axis=axis, ?Shape=GaugeShape) + + let delta = + Delta + |> Option.defaultValue(IndicatorDelta.init()) + |> IndicatorDelta.style(?Reference = DeltaReference) + + TraceDomain.initIndicator( + TraceDomainStyle.Indicator( + ?Name = Name , + ?Title = Title , + ?ShowLegend = ShowLegend, + Mode = mode , + Value = value , + ?Domain = Domain , + ?Align = Align , + Delta = delta , + ?Number = Number , + Gauge = gauge + ) + ) + |> GenericChart.ofTraceObject \ No newline at end of file diff --git a/src/Plotly.NET/CommonAbstractions/StyleParams.fs b/src/Plotly.NET/CommonAbstractions/StyleParams.fs index 953430e5b..931d51e9e 100644 --- a/src/Plotly.NET/CommonAbstractions/StyleParams.fs +++ b/src/Plotly.NET/CommonAbstractions/StyleParams.fs @@ -1114,6 +1114,61 @@ module StyleParam = // #I# //-------------------------- + [] + type IndicatorMode = + | Number | Delta | Gauge + | NumberDelta | NumberGauge + | DeltaGauge + | NumberDeltaGauge + static member toString = function + | Number -> "number" + | Delta -> "delta" + | Gauge -> "gauge" + | NumberDelta -> "number+delta" + | NumberGauge -> "number+gauge" + | DeltaGauge -> "delta+gauge" + | NumberDeltaGauge -> "number+delta+gauge" + + static member convert = IndicatorMode.toString >> box + override this.ToString() = this |> IndicatorMode.toString + member this.Convert() = this |> IndicatorMode.convert + + [] + type IndicatorAlignment = + | Left | Center | Right + static member toString = function + | Left -> "left" + | Center-> "center" + | Right -> "right" + + static member convert = IndicatorAlignment.toString >> box + override this.ToString() = this |> IndicatorAlignment.toString + member this.Convert() = this |> IndicatorAlignment.convert + + [] + type IndicatorGaugeShape = + | Angular | Bullet + static member toString = function + | Angular -> "angular" + | Bullet -> "bullet" + + static member convert = IndicatorGaugeShape.toString >> box + override this.ToString() = this |> IndicatorGaugeShape.toString + member this.Convert() = this |> IndicatorGaugeShape.convert + + [] + type IndicatorDeltaPosition = + | Top | Bottom | Left | Right + static member toString = function + | Top -> "top" + | Bottom -> "bottom" + | Left -> "left" + | Right -> "right" + + static member convert = IndicatorDeltaPosition.toString >> box + override this.ToString() = this |> IndicatorDeltaPosition.toString + member this.Convert() = this |> IndicatorDeltaPosition.convert + [] type InsideTextAnchor = | End | Middle | Start diff --git a/src/Plotly.NET/Layout/ObjectAbstractions/Common/LinearAxis.fs b/src/Plotly.NET/Layout/ObjectAbstractions/Common/LinearAxis.fs index b826f2f35..24900cce5 100644 --- a/src/Plotly.NET/Layout/ObjectAbstractions/Common/LinearAxis.fs +++ b/src/Plotly.NET/Layout/ObjectAbstractions/Common/LinearAxis.fs @@ -116,8 +116,8 @@ type LinearAxis () = [] ?TickLabelPosition : StyleParam.TickLabelPosition, [] ?TickLabelOverflow : StyleParam.TickLabelOverflow, [] ?Mirror : StyleParam.Mirror, - [] ?TickLen : float, - [] ?TickWidth : float, + [] ?TickLen : int, + [] ?TickWidth : int, [] ?TickColor : Color, [] ?ShowTickLabels : bool, [] ?AutoMargin : bool, @@ -352,8 +352,8 @@ type LinearAxis () = [] ?TickLabelPosition : StyleParam.TickLabelPosition, [] ?TickLabelOverflow : StyleParam.TickLabelOverflow, [] ?Mirror : StyleParam.Mirror, - [] ?TickLen : float, - [] ?TickWidth : float, + [] ?TickLen : int, + [] ?TickWidth : int, [] ?TickColor : Color, [] ?ShowTickLabels : bool, [] ?AutoMargin : bool, @@ -480,7 +480,7 @@ type LinearAxis () = ?Calendar = Calendar ) /// - /// Initialize a LinearAxis object that can be used as a positional scale for Y, X or Z coordinates. + /// Initialize a LinearAxis object that can be used as a positional scale for carpet plots. /// /// Sets default for all colors associated with this axis all at once: line, font, tick, and grid colors. Grid color is lightened by blending this with the plot background Individual pieces can override this. /// Sets the axis title. @@ -647,6 +647,93 @@ type LinearAxis () = ?StartLineColor = StartLineColor , ?StartLineWidth = StartLineWidth ) + + /// + /// Initialize a LinearAxis object that can be used as a positional scale for indicator gauges. + /// + /// Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to "log" and "date" axes. If the axis `type` is "log", then ticks are set every 10^(n"dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. "log" has several special values; "L<f>", where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = "L0.5" will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use "D1" (all digits) or "D2" (only 2 and 5). `tick0` is ignored for "D1" and "D2". If the axis `type` is "date", then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. "date" also has special values "M<n>" gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to "2000-01-15" and `dtick` to "M3". To set ticks every 4 years, set `dtick` to "M48" + /// Sets the range of this axis. If the axis `type` is "log", then you must take the log of your desired range (e.g. to set the range from 1 to 100, set the range from 0 to 2). If the axis `type` is "date", it should be date strings, like date data, though Date objects and unix milliseconds will be accepted and converted to strings. If the axis `type` is "category", it should be numbers, using the scale where each category is assigned a serial number from zero in the order it appears. + /// Sets the tick mode for this axis. If "auto", the number of ticks is set via `nticks`. If "linear", the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` ("linear" is the default value if `tick0` and `dtick` are provided). If "array", the placement of the ticks is set via `TickVals` and the tick text is `TickText`. ("array" is the default value if `TickVals` is provided). + /// Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to "auto". + /// Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is "log", then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`="L<f>" (see `dtick` for more info). If the axis `type` is "date", it should be a date string, like date data. If the axis `type` is "category", it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears. + /// Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to "array". Used with `TickText`. + /// Sets the text displayed at the ticks position via `TickVals`. Only has an effect if `tickmode` is set to "array". Used with `TickVals`. + /// Determines whether ticks are drawn or not. If "", this axis' ticks are not drawn. If "outside" ("inside"), this axis' are drawn outside (inside) the axis lines. + /// Determines whether or not the tick labels are drawn. + /// Sets the tick font. + /// Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically. + /// If "all", all tick labels are displayed with a prefix. If "first", only the first tick is displayed with a prefix. If "last", only the last tick is displayed with a suffix. If "none", tick prefixes are hidden. + /// Sets a tick label prefix. + /// Same as `showtickprefix` but for tick suffixes. + /// Sets a tick label suffix. + /// If "all", all exponents are shown besides their significands. If "first", only the exponent of the first tick is shown. If "last", only the exponent of the last tick is shown. If "none", no exponents appear. + /// Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If "none", it appears as 1,000,000,000. If "e", 1e+9. If "E", 1E+9. If "power", 1x10^9 (with 9 in a super script). If "SI", 1G. If "B", 1B. + /// Hide SI prefix for 10^n if |n| is below this number. This only has an effect when `TickFormat` is "SI" or "B". + /// If "true", even 4-digit integers are separated + /// Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-3.x-api-reference/blob/master/Formatting.md#d3_format. And for dates see: https://github.com/d3/d3-time-format#locale_format. We add two items to d3's date formatter: "%h" for half of the year as a decimal number as well as "%{n}f" for fractional seconds with n digits. For example, "2016-10-13 09:15:23.456" with TickFormat "%H~%M~%S.%2f" would display "09~15~23.46" + /// Sets the tick length (in px). + /// Sets the tick width (in px). + /// Sets the tick color. + /// Set rules for customizing TickFormat on different zoom levels + /// A single toggle to hide the axis while preserving interaction like dragging. Default is true when a cheater plot is present on the axis, otherwise false + static member initIndicatorGauge + ( + [] ?DTick : #IConvertible, + [] ?ExponentFormat : StyleParam.ExponentFormat, + [] ?MinExponent : float, + [] ?NTicks : int, + [] ?Range : StyleParam.Range, + [] ?SeparateThousands : bool, + [] ?ShowExponent : StyleParam.ShowExponent, + [] ?ShowTickLabels : bool, + [] ?ShowTickPrefix : StyleParam.ShowTickOption, + [] ?ShowTickSuffix : StyleParam.ShowTickOption, + [] ?Tick0 : #IConvertible, + [] ?TickAngle : int, + [] ?TickColor : Color, + [] ?TickFont : Font, + [] ?TickFormat : string, + [] ?TickFormatStops : seq, + [] ?TickLen : int, + [] ?TickMode : StyleParam.TickMode, + [] ?TickPrefix : string, + [] ?Ticks : StyleParam.TickOptions, + [] ?TickSuffix : string, + [] ?TickText : seq<#IConvertible>, + [] ?TickVals : seq<#IConvertible>, + [] ?TickWidth : int, + [] ?Visible : bool + + ) = + LinearAxis() + |> LinearAxis.style + ( + ?DTick = DTick , + ?ExponentFormat = ExponentFormat , + ?MinExponent = MinExponent , + ?NTicks = NTicks , + ?Range = Range , + ?SeparateThousands = SeparateThousands , + ?ShowExponent = ShowExponent , + ?ShowTickLabels = ShowTickLabels , + ?ShowTickPrefix = ShowTickPrefix , + ?ShowTickSuffix = ShowTickSuffix , + ?Tick0 = Tick0 , + ?TickAngle = TickAngle , + ?TickColor = TickColor , + ?TickFont = TickFont , + ?TickFormat = TickFormat , + ?TickFormatStops = TickFormatStops , + ?TickLen = TickLen , + ?TickMode = TickMode , + ?TickPrefix = TickPrefix , + ?Ticks = Ticks , + ?TickSuffix = TickSuffix , + ?TickText = TickText , + ?TickVals = TickVals , + ?TickWidth = TickWidth , + ?Visible = Visible + ) /// /// Create a function that applies the given style parameters to a LinearAxis object /// @@ -772,8 +859,8 @@ type LinearAxis () = [] ?TickLabelPosition : StyleParam.TickLabelPosition, [] ?TickLabelOverflow : StyleParam.TickLabelOverflow, [] ?Mirror : StyleParam.Mirror, - [] ?TickLen : float, - [] ?TickWidth : float, + [] ?TickLen : int, + [] ?TickWidth : int, [] ?TickColor : Color, [] ?ShowTickLabels : bool, [] ?AutoMargin : bool, diff --git a/src/Plotly.NET/Playground.fsx b/src/Plotly.NET/Playground.fsx index 6c4860cce..fc23dca02 100644 --- a/src/Plotly.NET/Playground.fsx +++ b/src/Plotly.NET/Playground.fsx @@ -92,6 +92,7 @@ #load "Cumulative.fs" #load "Error.fs" #load "Table.fs" +#load "Indicator.fs" #I "Traces" @@ -159,6 +160,37 @@ open FSharpAux open System open System.IO +[ + Chart.Indicator( + 200., StyleParam.IndicatorMode.NumberDeltaGauge, + Delta = IndicatorDelta.init(Reference=160), + Range = StyleParam.Range.MinMax(0., 250.), + Domain = Domain.init(Row = 0, Column = 0) + ) + Chart.Indicator( + 120., StyleParam.IndicatorMode.NumberDeltaGauge, + DeltaReference = 90., + Range = StyleParam.Range.MinMax(-200., 200.), + GaugeShape = StyleParam.IndicatorGaugeShape.Bullet, + ShowGaugeAxis = false, + Domain = Domain.init(Row = 0, Column = 1) + ) + Chart.Indicator( + 300., StyleParam.IndicatorMode.NumberDelta, + DeltaReference = 90., + Domain = Domain.init(Row = 1, Column = 0) + ) + Chart.Indicator( + 40., StyleParam.IndicatorMode.Delta, + DeltaReference = 90., + Domain = Domain.init(Row = 1, Column = 1) + ) +] +|> Chart.combine +|> Chart.withLayoutGridStyle(Rows = 2, Columns = 2) +|> Chart.show + + [ Chart.Carpet( "contour", diff --git a/src/Plotly.NET/Plotly.NET.fsproj b/src/Plotly.NET/Plotly.NET.fsproj index 2483e1372..98adb202c 100644 --- a/src/Plotly.NET/Plotly.NET.fsproj +++ b/src/Plotly.NET/Plotly.NET.fsproj @@ -100,6 +100,7 @@ + diff --git a/src/Plotly.NET/Traces/ObjectAbstractions/Indicator.fs b/src/Plotly.NET/Traces/ObjectAbstractions/Indicator.fs new file mode 100644 index 000000000..346a18570 --- /dev/null +++ b/src/Plotly.NET/Traces/ObjectAbstractions/Indicator.fs @@ -0,0 +1,287 @@ +namespace Plotly.NET.TraceObjects + +open Plotly.NET +open Plotly.NET.LayoutObjects +open DynamicObj +open System +open System.Runtime.InteropServices + + +type IndicatorSymbol () = + inherit DynamicObj () + + static member init + ( + [] ?Color : Color, + [] ?Symbol : string + ) = + IndicatorSymbol () + |> IndicatorSymbol.style + ( + ?Color = Color, + ?Symbol= Symbol + ) + + static member style + ( + [] ?Color : Color, + [] ?Symbol : string + ) = + (fun (indicatorDirection: IndicatorSymbol) -> + + Color |> DynObj.setValueOpt indicatorDirection "color" + Symbol |> DynObj.setValueOpt indicatorDirection "symbol" + + indicatorDirection + ) + +type IndicatorDelta () = + inherit DynamicObj () + + static member init + ( + [] ?Decreasing : IndicatorSymbol, + [] ?Font : Font, + [] ?Increasing : IndicatorSymbol, + [] ?Position : StyleParam.IndicatorDeltaPosition, + [] ?Reference : #IConvertible, + [] ?Relative : bool, + [] ?ValueFormat: string + + ) = + IndicatorDelta () + |> IndicatorDelta.style + ( + ?Decreasing = Decreasing , + ?Font = Font , + ?Increasing = Increasing , + ?Position = Position , + ?Reference = Reference , + ?Relative = Relative , + ?ValueFormat = ValueFormat + ) + + static member style + ( + [] ?Decreasing : IndicatorSymbol, + [] ?Font : Font, + [] ?Increasing : IndicatorSymbol, + [] ?Position : StyleParam.IndicatorDeltaPosition, + [] ?Reference : #IConvertible, + [] ?Relative : bool, + [] ?ValueFormat: string + ) = + (fun (indicatorDelta: IndicatorDelta) -> + + Decreasing |> DynObj.setValueOpt indicatorDelta "decreasing" + Font |> DynObj.setValueOpt indicatorDelta "font" + Increasing |> DynObj.setValueOpt indicatorDelta "increasing" + Position |> DynObj.setValueOptBy indicatorDelta "position" StyleParam.IndicatorDeltaPosition.convert + Reference |> DynObj.setValueOpt indicatorDelta "reference" + Relative |> DynObj.setValueOpt indicatorDelta "relative" + ValueFormat |> DynObj.setValueOpt indicatorDelta "valueformat" + + indicatorDelta + ) + +type IndicatorNumber () = + inherit DynamicObj () + + static member init + ( + [] ?Font : Font, + [] ?Prefix : string, + [] ?Suffix : string, + [] ?ValueFormat: string + + ) = + IndicatorNumber () + |> IndicatorNumber.style + ( + ?Font = Font , + ?Prefix = Prefix , + ?Suffix = Suffix , + ?ValueFormat= ValueFormat + ) + + static member style + ( + [] ?Font : Font, + [] ?Prefix : string, + [] ?Suffix : string, + [] ?ValueFormat: string + ) = + (fun (indicatorNumber: IndicatorNumber) -> + + Font |> DynObj.setValueOpt indicatorNumber "font" + Prefix |> DynObj.setValueOpt indicatorNumber "prefix" + Suffix |> DynObj.setValueOpt indicatorNumber "suffix" + ValueFormat|> DynObj.setValueOpt indicatorNumber "valueformat" + + indicatorNumber + ) + + +type IndicatorBar () = + inherit DynamicObj () + + static member init + ( + [] ?Color : Color, + [] ?Line : Line, + [] ?Thickness : float + ) = + IndicatorBar () + |> IndicatorBar.style + ( + ?Color = Color , + ?Line = Line , + ?Thickness = Thickness + ) + + static member style + ( + [] ?Color : Color, + [] ?Line : Line, + [] ?Thickness : float + ) = + (fun (indicatorBar: IndicatorBar) -> + + Color |> DynObj.setValueOpt indicatorBar "color" + Line |> DynObj.setValueOpt indicatorBar "line" + Thickness |> DynObj.setValueOpt indicatorBar "thickness" + + indicatorBar + ) + +type IndicatorSteps () = + inherit DynamicObj () + + static member init + ( + [] ?Color : Color, + [] ?Line : Line, + [] ?Name : string, + [] ?Range : StyleParam.Range, + [] ?TemplateItemName : string, + [] ?Thickness : float + + ) = + IndicatorSteps () + |> IndicatorSteps.style + ( + ?Color = Color , + ?Line = Line , + ?Name = Name , + ?Range = Range , + ?TemplateItemName = TemplateItemName , + ?Thickness = Thickness + ) + + static member style + ( + [] ?Color : Color, + [] ?Line : Line, + [] ?Name : string, + [] ?Range : StyleParam.Range, + [] ?TemplateItemName : string, + [] ?Thickness : float + ) = + (fun (indicatorSteps: IndicatorSteps) -> + + Color |> DynObj.setValueOpt indicatorSteps "color" + Line |> DynObj.setValueOpt indicatorSteps "line" + Name |> DynObj.setValueOpt indicatorSteps "name" + Range |> DynObj.setValueOptBy indicatorSteps "range" StyleParam.Range.convert + TemplateItemName |> DynObj.setValueOpt indicatorSteps "templateitemname" + Thickness |> DynObj.setValueOpt indicatorSteps "thickness" + + indicatorSteps + ) + + +type IndicatorThreshold () = + inherit DynamicObj () + + static member init + ( + [] ?Line : Line, + [] ?Thickness : float, + [] ?Value : #IConvertible + + ) = + IndicatorThreshold () + |> IndicatorThreshold.style + ( + ?Line = Line , + ?Thickness = Thickness, + ?Value = Value + ) + + static member style + ( + [] ?Line : Line, + [] ?Thickness : float, + [] ?Value : #IConvertible + ) = + (fun (indicatorThreshold: IndicatorThreshold) -> + + Line |> DynObj.setValueOpt indicatorThreshold "line" + Thickness |> DynObj.setValueOpt indicatorThreshold "thickness" + Value |> DynObj.setValueOpt indicatorThreshold "value" + + indicatorThreshold + ) + + +type IndicatorGauge () = + inherit DynamicObj () + + static member init + ( + [] ?Axis : LinearAxis, + [] ?Bar : IndicatorBar, + [] ?BGColor : Color, + [] ?BorderColor: Color, + [] ?BorderWidth: int, + [] ?Shape : StyleParam.IndicatorGaugeShape, + [] ?Steps : IndicatorSteps, + [] ?Threshold : IndicatorThreshold + ) = + IndicatorGauge () + |> IndicatorGauge.style + ( + ?Axis = Axis , + ?Bar = Bar , + ?BGColor = BGColor , + ?BorderColor= BorderColor, + ?BorderWidth= BorderWidth, + ?Shape = Shape , + ?Steps = Steps , + ?Threshold = Threshold + ) + + static member style + ( + [] ?Axis : LinearAxis, + [] ?Bar : IndicatorBar, + [] ?BGColor : Color, + [] ?BorderColor: Color, + [] ?BorderWidth: int, + [] ?Shape : StyleParam.IndicatorGaugeShape, + [] ?Steps : IndicatorSteps, + [] ?Threshold : IndicatorThreshold + ) = + (fun (indicatorGauge: IndicatorGauge) -> + + Axis |> DynObj.setValueOpt indicatorGauge "axis" + Bar |> DynObj.setValueOpt indicatorGauge "bar" + BGColor |> DynObj.setValueOpt indicatorGauge "bgcolor" + BorderColor|> DynObj.setValueOpt indicatorGauge "bordercolor" + BorderWidth|> DynObj.setValueOpt indicatorGauge "borderwidth" + Shape |> DynObj.setValueOptBy indicatorGauge "shape" StyleParam.IndicatorGaugeShape.convert + Steps |> DynObj.setValueOpt indicatorGauge "steps" + Threshold |> DynObj.setValueOpt indicatorGauge "threshold " + + indicatorGauge + ) \ No newline at end of file diff --git a/src/Plotly.NET/Traces/TraceDomain.fs b/src/Plotly.NET/Traces/TraceDomain.fs index 3ffdbc9de..7641f0c5f 100644 --- a/src/Plotly.NET/Traces/TraceDomain.fs +++ b/src/Plotly.NET/Traces/TraceDomain.fs @@ -326,3 +326,46 @@ type TraceDomainStyle() = trace ) + static member Indicator + ( + [] ?Name : string, + [] ?Title : string, + [] ?Visible : StyleParam.Visible, + [] ?ShowLegend : bool, + [] ?LegendRank : int, + [] ?LegendGroup : string, + [] ?LegendGroupTitle : Title, + [] ?Mode : StyleParam.IndicatorMode, + [] ?Ids : seq<#IConvertible>, + [] ?Value : #IConvertible, + [] ?Meta : string, + [] ?CustomData : seq<#IConvertible>, + [] ?Domain : Domain, + [] ?Align : StyleParam.IndicatorAlignment, + [] ?Delta : IndicatorDelta, + [] ?Number : IndicatorNumber, + [] ?Gauge : IndicatorGauge, + [] ?UIRevision : string + ) = + fun (trace: #Trace) -> + + Name |> DynObj.setValueOpt trace "name" + Title |> DynObj.setValueOpt trace "title" + Visible |> DynObj.setValueOptBy trace "visible" StyleParam.Visible.convert + ShowLegend |> DynObj.setValueOpt trace "showlegend" + LegendRank |> DynObj.setValueOpt trace "legendrank" + LegendGroup |> DynObj.setValueOpt trace "legendgroup" + LegendGroupTitle |> DynObj.setValueOpt trace "legendgrouptitle" + Mode |> DynObj.setValueOptBy trace "mode" StyleParam.IndicatorMode.convert + Ids |> DynObj.setValueOpt trace "ids" + Value |> DynObj.setValueOpt trace "value" + Meta |> DynObj.setValueOpt trace "meta" + CustomData |> DynObj.setValueOpt trace "customdata" + Domain |> DynObj.setValueOpt trace "domain" + Align |> DynObj.setValueOptBy trace "align" StyleParam.IndicatorAlignment.convert + Delta |> DynObj.setValueOpt trace "delta" + Number |> DynObj.setValueOpt trace "number" + Gauge |> DynObj.setValueOpt trace "gauge" + UIRevision |> DynObj.setValueOpt trace "uirevision" + + trace From ec541129a3df4439a02ee9296cc8e83f71bef1ff Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Mon, 27 Sep 2021 08:13:20 +0200 Subject: [PATCH 2/6] Add indicator tests --- .../HtmlCodegen/FinanceCharts.fs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs b/tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs index 4ded81deb..dc585563c 100644 --- a/tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs +++ b/tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs @@ -98,4 +98,50 @@ let ``Funnel area charts`` = testCase "Funnel area layout" ( fun () -> emptyLayout funnelArea ); + ] + + + +let indicators = + [ + ChartDomain.Chart.Indicator( + 200., StyleParam.IndicatorMode.NumberDeltaGauge, + Delta = IndicatorDelta.init(Reference=160), + Range = StyleParam.Range.MinMax(0., 250.), + Domain = Domain.init(Row = 0, Column = 0) + ) + Chart.Indicator( + 120., StyleParam.IndicatorMode.NumberDeltaGauge, + DeltaReference = 90., + Range = StyleParam.Range.MinMax(-200., 200.), + GaugeShape = StyleParam.IndicatorGaugeShape.Bullet, + ShowGaugeAxis = false, + Domain = Domain.init(Row = 0, Column = 1) + ) + Chart.Indicator( + 300., StyleParam.IndicatorMode.NumberDelta, + DeltaReference = 90., + Domain = Domain.init(Row = 1, Column = 0) + ) + Chart.Indicator( + 40., StyleParam.IndicatorMode.Delta, + DeltaReference = 90., + Domain = Domain.init(Row = 1, Column = 1) + ) + ] + |> Chart.combine + |> Chart.withLayoutGridStyle(Rows = 2, Columns = 2) + + +[] +let ``Indicator charts`` = + testList "FinanceCharts.Funnel area charts" [ + testCase "Indicator data" ( fun () -> + """var data = [{"type":"indicator","mode":"number+delta+gauge","value":200.0,"domain":{"row":0,"column":0},"delta":{"reference":160},"gauge":{"axis":{"range":[0.0,250.0]}}},{"type":"indicator","mode":"number+delta+gauge","value":120.0,"domain":{"row":0,"column":1},"delta":{"reference":90.0},"gauge":{"axis":{"visible":false,"range":[-200.0,200.0]},"shape":"bullet"}},{"type":"indicator","mode":"number+delta","value":300.0,"domain":{"row":1,"column":0},"delta":{"reference":90.0},"gauge":{"axis":{}}},{"type":"indicator","mode":"delta","value":40.0,"domain":{"row":1,"column":1},"delta":{"reference":90.0},"gauge":{"axis":{}}}];""" + |> chartGeneratedContains funnelArea + ); + testCase "Indicator layout" ( fun () -> + """var layout = {"grid":{"rows":2,"columns":2}};""" + |> chartGeneratedContains funnelArea + ); ] \ No newline at end of file From d60d6b046cbdc288403dab531455390af6bf4677 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Mon, 27 Sep 2021 08:16:06 +0200 Subject: [PATCH 3/6] Add indicator docs --- Plotly.NET.sln | 1 + docs/07_3_indicator.fsx | 86 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 docs/07_3_indicator.fsx diff --git a/Plotly.NET.sln b/Plotly.NET.sln index 873566a31..9052fc405 100644 --- a/Plotly.NET.sln +++ b/Plotly.NET.sln @@ -82,6 +82,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{7B09CC0A-F docs\07_0_candlestick.fsx = docs\07_0_candlestick.fsx docs\07_1_funnel.fsx = docs\07_1_funnel.fsx docs\07_2_funnel_area.fsx = docs\07_2_funnel_area.fsx + docs\07_3_indicator.fsx = docs\07_3_indicator.fsx docs\08_0_polar_line-scatter-plots.fsx = docs\08_0_polar_line-scatter-plots.fsx docs\08_1_polar_bar_charts.fsx = docs\08_1_polar_bar_charts.fsx docs\08_2_styling_polar_layouts.fsx = docs\08_2_styling_polar_layouts.fsx diff --git a/docs/07_3_indicator.fsx b/docs/07_3_indicator.fsx new file mode 100644 index 000000000..74cd0c01a --- /dev/null +++ b/docs/07_3_indicator.fsx @@ -0,0 +1,86 @@ +(** +--- +title: Indicator Charts +category: Finance Charts +categoryindex: 7 +index: 4 +--- +*) + +(*** hide ***) + +(*** condition: prepare ***) +#r "nuget: Newtonsoft.JSON, 13.0.1" +#r "nuget: DynamicObj" +#r "../bin/Plotly.NET/net5.0/Plotly.NET.dll" + +(*** condition: ipynb ***) +#if IPYNB +#r "nuget: Plotly.NET, {{fsdocs-package-version}}" +#r "nuget: Plotly.NET.Interactive, {{fsdocs-package-version}}" +#endif // IPYNB + +(** +# Indicator Charts + +[![Binder]({{root}}img/badge-binder.svg)](https://mybinder.org/v2/gh/plotly/Plotly.NET/gh-pages?filepath={{fsdocs-source-basename}}.ipynb)  +[![Script]({{root}}img/badge-script.svg)]({{root}}{{fsdocs-source-basename}}.fsx)  +[![Notebook]({{root}}img/badge-notebook.svg)]({{root}}{{fsdocs-source-basename}}.ipynb) + +*Summary:* This example shows how to create indicator charts in F#. + +Indicator Charts visualize the evolution of a value compared to a reference value, optionally inside a range. + +There are different types of indicator charts, depending on the `IndicatorMode` used in chart generation: + +- `Delta`/`Number` (and combinations) simply shows if the value is increasing or decreasing compared to the reference +- Any combination of the above with `Gauge` adds a customizable gauge that indicates where the value lies inside a given range. +*) + +open Plotly.NET +open Plotly.NET.TraceObjects + +let allIndicatorTypes = + [ + Chart.Indicator( + 200., StyleParam.IndicatorMode.NumberDeltaGauge, + Title = Title.init("Angular gauge showing number and delta") + Delta = IndicatorDelta.init(Reference=160), + Range = StyleParam.Range.MinMax(0., 250.), + Domain = Domain.init(Row = 0, Column = 0) + ) + Chart.Indicator( + 120., StyleParam.IndicatorMode.NumberDeltaGauge, + Title = Title.init("Bullet gauge showing number and delta") + DeltaReference = 90., + Range = StyleParam.Range.MinMax(-200., 200.), + GaugeShape = StyleParam.IndicatorGaugeShape.Bullet, + ShowGaugeAxis = false, + Domain = Domain.init(Row = 0, Column = 1) + ) + Chart.Indicator( + 300., StyleParam.IndicatorMode.NumberDelta, + Title = Title.init("Only showing number and delta") + DeltaReference = 90., + Domain = Domain.init(Row = 1, Column = 0) + ) + Chart.Indicator( + 40., StyleParam.IndicatorMode.Delta, + Title = Title.init("Only showing delta") + DeltaReference = 90., + Domain = Domain.init(Row = 1, Column = 1) + ) + ] + |> Chart.combine + |> Chart.withLayoutGridStyle(Rows = 2, Columns = 2) + + +(*** condition: ipynb ***) +#if IPYNB +allIndicatorTypes +#endif // IPYNB + +(***hide***) +allIndicatorTypes |> GenericChart.toChartHTML +(***include-it-raw***) + From ca03c3b239c5214d75333140a771dc0fd18abb21 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Mon, 27 Sep 2021 10:03:35 +0200 Subject: [PATCH 4/6] Fix Indicator chart type annotation and tests --- src/Plotly.NET/ChartAPI/ChartDomain.fs | 2 +- src/Plotly.NET/Playground.fsx | 8 ++++---- tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs | 12 ++++++------ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Plotly.NET/ChartAPI/ChartDomain.fs b/src/Plotly.NET/ChartAPI/ChartDomain.fs index fa1e75249..bea924810 100644 --- a/src/Plotly.NET/ChartAPI/ChartDomain.fs +++ b/src/Plotly.NET/ChartAPI/ChartDomain.fs @@ -514,7 +514,7 @@ module ChartDomain = [] static member Indicator ( - value : #IConvertible, + value : IConvertible, mode : StyleParam.IndicatorMode, [] ?Range : StyleParam.Range, [] ?Name : string, diff --git a/src/Plotly.NET/Playground.fsx b/src/Plotly.NET/Playground.fsx index fc23dca02..683c8e048 100644 --- a/src/Plotly.NET/Playground.fsx +++ b/src/Plotly.NET/Playground.fsx @@ -161,22 +161,22 @@ open System open System.IO [ - Chart.Indicator( + ChartDomain.Chart.Indicator( 200., StyleParam.IndicatorMode.NumberDeltaGauge, Delta = IndicatorDelta.init(Reference=160), Range = StyleParam.Range.MinMax(0., 250.), Domain = Domain.init(Row = 0, Column = 0) ) Chart.Indicator( - 120., StyleParam.IndicatorMode.NumberDeltaGauge, - DeltaReference = 90., + 120, StyleParam.IndicatorMode.NumberDeltaGauge, + DeltaReference = 90, Range = StyleParam.Range.MinMax(-200., 200.), GaugeShape = StyleParam.IndicatorGaugeShape.Bullet, ShowGaugeAxis = false, Domain = Domain.init(Row = 0, Column = 1) ) Chart.Indicator( - 300., StyleParam.IndicatorMode.NumberDelta, + "300", StyleParam.IndicatorMode.NumberDelta, DeltaReference = 90., Domain = Domain.init(Row = 1, Column = 0) ) diff --git a/tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs b/tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs index dc585563c..c924f3a26 100644 --- a/tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs +++ b/tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs @@ -111,15 +111,15 @@ let indicators = Domain = Domain.init(Row = 0, Column = 0) ) Chart.Indicator( - 120., StyleParam.IndicatorMode.NumberDeltaGauge, - DeltaReference = 90., + 120, StyleParam.IndicatorMode.NumberDeltaGauge, + DeltaReference = 90, Range = StyleParam.Range.MinMax(-200., 200.), GaugeShape = StyleParam.IndicatorGaugeShape.Bullet, ShowGaugeAxis = false, Domain = Domain.init(Row = 0, Column = 1) ) Chart.Indicator( - 300., StyleParam.IndicatorMode.NumberDelta, + "300", StyleParam.IndicatorMode.NumberDelta, DeltaReference = 90., Domain = Domain.init(Row = 1, Column = 0) ) @@ -135,13 +135,13 @@ let indicators = [] let ``Indicator charts`` = - testList "FinanceCharts.Funnel area charts" [ + testList "Indicator.Indicator charts" [ testCase "Indicator data" ( fun () -> """var data = [{"type":"indicator","mode":"number+delta+gauge","value":200.0,"domain":{"row":0,"column":0},"delta":{"reference":160},"gauge":{"axis":{"range":[0.0,250.0]}}},{"type":"indicator","mode":"number+delta+gauge","value":120.0,"domain":{"row":0,"column":1},"delta":{"reference":90.0},"gauge":{"axis":{"visible":false,"range":[-200.0,200.0]},"shape":"bullet"}},{"type":"indicator","mode":"number+delta","value":300.0,"domain":{"row":1,"column":0},"delta":{"reference":90.0},"gauge":{"axis":{}}},{"type":"indicator","mode":"delta","value":40.0,"domain":{"row":1,"column":1},"delta":{"reference":90.0},"gauge":{"axis":{}}}];""" - |> chartGeneratedContains funnelArea + |> chartGeneratedContains indicators ); testCase "Indicator layout" ( fun () -> """var layout = {"grid":{"rows":2,"columns":2}};""" - |> chartGeneratedContains funnelArea + |> chartGeneratedContains indicators ); ] \ No newline at end of file From 8b8975a850015104920e953fcc0ad728ac4d284d Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Mon, 27 Sep 2021 10:10:04 +0200 Subject: [PATCH 5/6] Fix indicator tests --- tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs b/tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs index c924f3a26..34adf6f45 100644 --- a/tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs +++ b/tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs @@ -135,9 +135,9 @@ let indicators = [] let ``Indicator charts`` = - testList "Indicator.Indicator charts" [ + testList "FinanceCharts.Indicator charts" [ testCase "Indicator data" ( fun () -> - """var data = [{"type":"indicator","mode":"number+delta+gauge","value":200.0,"domain":{"row":0,"column":0},"delta":{"reference":160},"gauge":{"axis":{"range":[0.0,250.0]}}},{"type":"indicator","mode":"number+delta+gauge","value":120.0,"domain":{"row":0,"column":1},"delta":{"reference":90.0},"gauge":{"axis":{"visible":false,"range":[-200.0,200.0]},"shape":"bullet"}},{"type":"indicator","mode":"number+delta","value":300.0,"domain":{"row":1,"column":0},"delta":{"reference":90.0},"gauge":{"axis":{}}},{"type":"indicator","mode":"delta","value":40.0,"domain":{"row":1,"column":1},"delta":{"reference":90.0},"gauge":{"axis":{}}}];""" + """var data = [{"type":"indicator","mode":"number+delta+gauge","value":200.0,"domain":{"row":0,"column":0},"delta":{"reference":160},"gauge":{"axis":{"range":[0.0,250.0]}}},{"type":"indicator","mode":"number+delta+gauge","value":120,"domain":{"row":0,"column":1},"delta":{"reference":90},"gauge":{"axis":{"visible":false,"range":[-200.0,200.0]},"shape":"bullet"}},{"type":"indicator","mode":"number+delta","value":"300","domain":{"row":1,"column":0},"delta":{"reference":90.0},"gauge":{"axis":{}}},{"type":"indicator","mode":"delta","value":40.0,"domain":{"row":1,"column":1},"delta":{"reference":90.0},"gauge":{"axis":{}}}];""" |> chartGeneratedContains indicators ); testCase "Indicator layout" ( fun () -> From bd5bb0ac55691204490e14f59373fe17da3857dc Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Mon, 27 Sep 2021 10:20:55 +0200 Subject: [PATCH 6/6] Fix indicator docs --- docs/07_3_indicator.fsx | 24 +++++++++++++----------- src/Plotly.NET/Playground.fsx | 25 +++++++++++++++---------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/docs/07_3_indicator.fsx b/docs/07_3_indicator.fsx index 74cd0c01a..1d7b648b0 100644 --- a/docs/07_3_indicator.fsx +++ b/docs/07_3_indicator.fsx @@ -39,40 +39,42 @@ There are different types of indicator charts, depending on the `IndicatorMode` open Plotly.NET open Plotly.NET.TraceObjects +open Plotly.NET.LayoutObjects let allIndicatorTypes = [ - Chart.Indicator( - 200., StyleParam.IndicatorMode.NumberDeltaGauge, - Title = Title.init("Angular gauge showing number and delta") - Delta = IndicatorDelta.init(Reference=160), - Range = StyleParam.Range.MinMax(0., 250.), - Domain = Domain.init(Row = 0, Column = 0) - ) Chart.Indicator( 120., StyleParam.IndicatorMode.NumberDeltaGauge, - Title = Title.init("Bullet gauge showing number and delta") + Title = "Bullet gauge", DeltaReference = 90., Range = StyleParam.Range.MinMax(-200., 200.), GaugeShape = StyleParam.IndicatorGaugeShape.Bullet, ShowGaugeAxis = false, - Domain = Domain.init(Row = 0, Column = 1) + Domain = Domain.init(Row = 0, Column = 0) + ) + Chart.Indicator( + 200., StyleParam.IndicatorMode.NumberDeltaGauge, + Title = "Angular gauge", + Delta = IndicatorDelta.init(Reference=160), + Range = StyleParam.Range.MinMax(0., 250.), + Domain = Domain.init(Row = 0, Column = 1) ) Chart.Indicator( 300., StyleParam.IndicatorMode.NumberDelta, - Title = Title.init("Only showing number and delta") + Title = "number and delta", DeltaReference = 90., Domain = Domain.init(Row = 1, Column = 0) ) Chart.Indicator( 40., StyleParam.IndicatorMode.Delta, - Title = Title.init("Only showing delta") + Title = "delta", DeltaReference = 90., Domain = Domain.init(Row = 1, Column = 1) ) ] |> Chart.combine |> Chart.withLayoutGridStyle(Rows = 2, Columns = 2) + |> Chart.withMarginSize(Left = 200) (*** condition: ipynb ***) diff --git a/src/Plotly.NET/Playground.fsx b/src/Plotly.NET/Playground.fsx index 683c8e048..80c96406d 100644 --- a/src/Plotly.NET/Playground.fsx +++ b/src/Plotly.NET/Playground.fsx @@ -161,33 +161,38 @@ open System open System.IO [ - ChartDomain.Chart.Indicator( - 200., StyleParam.IndicatorMode.NumberDeltaGauge, - Delta = IndicatorDelta.init(Reference=160), - Range = StyleParam.Range.MinMax(0., 250.), - Domain = Domain.init(Row = 0, Column = 0) - ) Chart.Indicator( - 120, StyleParam.IndicatorMode.NumberDeltaGauge, - DeltaReference = 90, + 120., StyleParam.IndicatorMode.NumberDeltaGauge, + Title = "Bullet gauge", + DeltaReference = 90., Range = StyleParam.Range.MinMax(-200., 200.), GaugeShape = StyleParam.IndicatorGaugeShape.Bullet, ShowGaugeAxis = false, - Domain = Domain.init(Row = 0, Column = 1) + Domain = Domain.init(Row = 0, Column = 0) + ) + Chart.Indicator( + 200., StyleParam.IndicatorMode.NumberDeltaGauge, + Title = "Angular gauge", + Delta = IndicatorDelta.init(Reference=160), + Range = StyleParam.Range.MinMax(0., 250.), + Domain = Domain.init(Row = 0, Column = 1) ) Chart.Indicator( - "300", StyleParam.IndicatorMode.NumberDelta, + 300., StyleParam.IndicatorMode.NumberDelta, + Title = "number and delta", DeltaReference = 90., Domain = Domain.init(Row = 1, Column = 0) ) Chart.Indicator( 40., StyleParam.IndicatorMode.Delta, + Title = "delta", DeltaReference = 90., Domain = Domain.init(Row = 1, Column = 1) ) ] |> Chart.combine |> Chart.withLayoutGridStyle(Rows = 2, Columns = 2) +|> Chart.withMarginSize(Left = 200) |> Chart.show