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..1d7b648b0 --- /dev/null +++ b/docs/07_3_indicator.fsx @@ -0,0 +1,88 @@ +(** +--- +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 +open Plotly.NET.LayoutObjects + +let allIndicatorTypes = + [ + Chart.Indicator( + 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 = 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 = "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) + + +(*** condition: ipynb ***) +#if IPYNB +allIndicatorTypes +#endif // IPYNB + +(***hide***) +allIndicatorTypes |> GenericChart.toChartHTML +(***include-it-raw***) + diff --git a/src/Plotly.NET/ChartAPI/ChartDomain.fs b/src/Plotly.NET/ChartAPI/ChartDomain.fs index 368a6d558..bea924810 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..80c96406d 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,42 @@ open FSharpAux open System open System.IO +[ + Chart.Indicator( + 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 = 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 = "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 + + [ 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 diff --git a/tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs b/tests/Plotly.NET.Tests/HtmlCodegen/FinanceCharts.fs index 4ded81deb..34adf6f45 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.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,"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 () -> + """var layout = {"grid":{"rows":2,"columns":2}};""" + |> chartGeneratedContains indicators + ); ] \ No newline at end of file