Skip to content

Commit 0ccd95c

Browse files
committed
Complete scoped plotly.js 2.28 documentation and validation
Document shared encoded arrays, tested C# examples, numeric and shape limits, nested precedence, selected wrapper coverage, and Virtual-WebGL script loading. Correct package release notes and installation-example formatting. Add shared Sankey init/style collision tests and C# encoded SPLOM/documentation cases. Record browser validation and completion scope in the plans. Validation: full clean FAKE runTestsAll passed (960 core, 126 C#, 6 ImageExport passed with 2 existing skips). FAKE BuildDocs completed and strict reevaluation of both edited pages passed. Browser checks passed for encoded Scatter, 2x3 Heatmap, nested Sankey, SPLOM, and four Virtual-WebGL charts.
1 parent 81c30c6 commit 0ccd95c

10 files changed

Lines changed: 411 additions & 49 deletions

File tree

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Guidance for AI coding agents working in the Plotly.NET repo. This is a first dr
66

77
Plotly.NET is an interactive charting library for .NET, built on top of plotly.js. The core is written in F# and wraps the plotly.js JSON schema with multiple API layers (high-level type-safe `Chart` API down to low-level object manipulation). See [README.md](README.md) for user-facing docs and the [F1000Research paper](https://doi.org/10.12688/f1000research.123971.1) for design rationale.
88

9-
Currently targeted plotly.js version: **2.27.1** (bundled at [src/Plotly.NET/plotly-2.27.1.min.js](src/Plotly.NET/plotly-2.27.1.min.js)).
9+
Currently targeted plotly.js version: **2.28.0** (bundled at [src/Plotly.NET/plotly-2.28.0.min.js](src/Plotly.NET/plotly-2.28.0.min.js)).
1010

1111
## Packages (monorepo layout)
1212

docs/general/encoded-arrays.fsx

Lines changed: 157 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Plotly.NET.Defaults.DefaultDisplayOptions <-
3030
[![Binder]({{root}}img/badge-binder.svg)](https://mybinder.org/v2/gh/plotly/plotly.net/gh-pages?urlpath=/tree/home/jovyan/{{fsdocs-source-basename}}.ipynb)&emsp;
3131
[![Notebook]({{root}}img/badge-notebook.svg)]({{root}}{{fsdocs-source-basename}}.ipynb)
3232
33-
*Summary:* This page explains how to use `EncodedTypedArray` for efficient data transfer with plotly.js 2.28+.
33+
*Summary:* This page explains numeric encoded arrays in Plotly.NET and the selected C# chart overloads, using plotly.js 2.28.0.
3434
3535
### Table of contents
3636
@@ -42,21 +42,24 @@ Plotly.NET.Defaults.DefaultDisplayOptions <-
4242
- [Using encoded arrays with 3D charts](#Using-encoded-arrays-with-3D-charts)
4343
- [Using encoded arrays with statistical charts](#Using-encoded-arrays-with-statistical-charts)
4444
- [Using encoded arrays for error bars and trace-level styling](#Using-encoded-arrays-for-error-bars-and-trace-level-styling)
45+
- [Using encoded arrays from C#](#Using-encoded-arrays-from-C)
46+
- [Nested data and precedence](#Nested-data-and-precedence)
47+
- [Supported scope and limitations](#Supported-scope-and-limitations)
48+
- [Loading Virtual-WebGL](#Loading-Virtual-WebGL)
4549
4650
## What are encoded typed arrays?
4751
4852
plotly.js 2.28.0 introduced support for passing data arrays as **base64-encoded typed arrays** instead of plain JSON arrays.
49-
This format (`bdata`/`dtype`/`shape`) is significantly more compact and faster to parse for large numeric datasets,
50-
since it avoids the overhead of JSON number serialization.
53+
The representation contains a base64 byte payload (`bdata`), a numeric type tag (`dtype`), and an optional
54+
matrix shape (`shape`). Its size and parsing cost depend on the data and dtype; this release does not
55+
provide a benchmark or guarantee that it is smaller or faster than JSON arrays.
5156
52-
For example, a float64 array `[1.0, 2.0, 3.0]` transmitted as plain JSON looks like `[1.0,2.0,3.0]`,
53-
while the encoded form is `{"bdata":"AAAAAAAA8D8AAAAAAAAAQA==...","dtype":"f8"}` — smaller and faster to deserialize in the browser.
54-
55-
Plotly.NET exposes this via the `EncodedTypedArray` type.
57+
The core Plotly.NET assembly owns `EncodedTypedArray`, its factories, and serialization. Both F# and C#
58+
use this same representation.
5659
5760
## Creating EncodedTypedArray values
5861
59-
`EncodedTypedArray` can be constructed from any standard .NET typed array:
62+
`EncodedTypedArray` can be constructed from the supported numeric arrays listed below:
6063
*)
6164

6265
open Plotly.NET
@@ -74,7 +77,7 @@ let valuesEncoded = EncodedTypedArray.ofFloat32Array [| 1.0f; 2.5f; 0.8f |]
7477
(**
7578
Supported constructors:
7679
77-
| Constructor | .NET type | plotly.js dtype |
80+
| Constructor | F# array type | plotly.js dtype |
7881
|---|---|---|
7982
| `EncodedTypedArray.ofFloat64Array` | `float[]` | `f8` (64-bit float) |
8083
| `EncodedTypedArray.ofFloat32Array` | `float32[]` | `f4` (32-bit float) |
@@ -84,6 +87,10 @@ Supported constructors:
8487
| `EncodedTypedArray.ofUInt32Array` | `uint32[]` | `u4` (unsigned 32-bit) |
8588
| `EncodedTypedArray.ofUInt16Array` | `uint16[]` | `u2` (unsigned 16-bit) |
8689
| `EncodedTypedArray.ofUInt8Array` | `byte[]` | `u1` (unsigned 8-bit) |
90+
| `EncodedTypedArray.ofUInt8ClampedArray` | `byte[]` | `u1c` (clamped unsigned 8-bit) |
91+
92+
There are no factories for strings, arbitrary objects, decimal, or signed/unsigned 64-bit integers.
93+
Choose a supported dtype explicitly when converting data, accounting for its range and precision.
8794
8895
## Using encoded arrays with Scatter
8996
@@ -122,7 +129,8 @@ let barEncoded =
122129
Chart.Bar(
123130
valuesEncoded = EncodedTypedArray.ofFloat64Array [| 5.0; 3.0; 7.0; 2.0 |],
124131
KeysEncoded = EncodedTypedArray.ofInt32Array [| 0; 1; 2; 3 |],
125-
Name = "encoded bar"
132+
Name = "encoded bar",
133+
UseDefaults = false
126134
)
127135

128136
(*** condition: ipynb ***)
@@ -145,7 +153,7 @@ When `zEncoded` is given as a flat encoded array, `shape` must also be set so pl
145153

146154
let heatmapEncoded =
147155
Chart.Heatmap(
148-
zEncoded = EncodedTypedArray.ofFloat64Array([| 1.0; 2.0; 3.0; 4.0; 5.0; 6.0; 7.0; 8.0; 9.0 |], shape = [ 3; 3 ]),
156+
zEncoded = EncodedTypedArray.ofFloat64Array([| 1.0; 2.0; 3.0; 4.0; 5.0; 6.0 |], shape = [ 2; 3 ]),
149157
Name = "encoded heatmap",
150158
UseDefaults = false
151159
)
@@ -163,13 +171,18 @@ Note that for heatmaps the z data is passed as a flat 1D encoded array. plotly.j
163171
(rows × columns) to interpret the layout, so `shape` must be specified:
164172
165173
```
166-
// Explicit 3x3 shape
167-
let z3x3 =
168-
EncodedTypedArray.ofFloat64Array([| 1.0 .. 9.0 |], shape = [ 3; 3 ])
174+
// Row-major 2x3 matrix: [[1; 2; 3]; [4; 5; 6]]
175+
let z2x3 =
176+
EncodedTypedArray.ofFloat64Array([| 1.0 .. 6.0 |], shape = [ 2; 3 ])
169177
```
170178
171-
The same `shape` requirement applies to other matrix-style traces such as `Chart.Surface`, `Chart.Contour`,
172-
`Chart.Histogram2D`, and `Chart.Histogram2DContour`.
179+
Supply a matching row count and column count for matrix-valued inputs such as the z grid of
180+
`Chart.Surface` or `Chart.Contour`. The factories preserve the supplied shape; they do not validate
181+
that its dimensions match the payload length.
182+
183+
`Chart.Histogram2D` and `Chart.Histogram2DContour` instead consume one-dimensional x/y samples and
184+
optional z aggregation values, one per sample. Do not reshape those sample arrays into a matrix;
185+
plotly.js computes the bins.
173186
174187
## Using encoded arrays with 3D charts
175188
@@ -196,8 +209,9 @@ scatter3DEncoded |> GenericChart.toChartHTML
196209
(***include-it-raw***)
197210

198211
(**
199-
For matrix-based 3D traces such as `Chart.Surface` and `Chart.Volume`, encoded arrays are also supported,
200-
and `shape` must be set wherever plotly.js needs to reconstruct multi-dimensional data from a flat payload.
212+
`Chart.Surface` uses a two-dimensional z grid. `Chart.Volume` and `Chart.IsoSurface` use parallel
213+
one-dimensional x/y/z/value arrays describing samples in space; their coordinates and values do not
214+
require a matrix shape simply because the chart is three-dimensional.
201215
202216
## Using encoded arrays with statistical charts
203217
@@ -257,8 +271,8 @@ let scatterWithEncodedErrorBars =
257271
)
258272
)
259273
)
260-
|> GenericChart.ofTraceObject true
261-
|> Chart.withDisplayOptionsStyle(PlotlyJSReference = PlotlyJSReference.NoReference)
274+
|> GenericChart.ofTraceObject false
275+
|> Chart.withDisplayOptions(DisplayOptions.init(PlotlyJSReference = PlotlyJSReference.NoReference))
262276

263277
(*** condition: ipynb ***)
264278
#if IPYNB
@@ -275,5 +289,127 @@ for many metadata fields such as ids, custom data, selected points, text, dimens
275289
276290
For more advanced usage including encoded arrays on 3D, domain, and map traces, see the trace-level
277291
style modules (`Trace2DStyle`, `Trace3DStyle`, `TraceDomainStyle`, etc.) which accept `*Encoded` optional parameters
278-
for most data-array fields.
292+
for selected data-array fields. An encoded option only changes the transport representation; the
293+
underlying plotly.js field must still accept the resulting values.
294+
*)
295+
296+
(**
297+
## Using encoded arrays from C#
298+
299+
Reference both `Plotly.NET` and `Plotly.NET.CSharp`. The factories are F# methods in the shared core:
300+
C# supplies `shape: default` for a one-dimensional array, or an explicit
301+
`FSharpOption<IEnumerable<int>>` for a matrix. The remaining generic type argument on Scatter/Heatmap
302+
describes optional text; specify it even when no text is supplied.
303+
304+
This 1D example is compiled and checked in `EncodedArrayExamplesTests`:
305+
306+
```csharp
307+
[lang=csharp]
308+
using Plotly.NET;
309+
using Chart = Plotly.NET.CSharp.Chart;
310+
311+
var x = EncodedTypedArray.ofInt32Array(new[] { 0, 1, 2 }, shape: default);
312+
var y = EncodedTypedArray.ofFloat32Array(new[] { 1.5f, 4.5f, 2.5f }, shape: default);
313+
var scatter = Chart.Scatter<string>(
314+
xEncoded: x, yEncoded: y, mode: StyleParam.Mode.Markers,
315+
Name: "encoded scatter", UseDefaults: false);
316+
```
317+
318+
For a 2-by-3 heatmap, flatten the rows in order and supply three x coordinates and two y coordinates.
319+
This example is also compiled and checked in the C# tests:
320+
321+
```csharp
322+
[lang=csharp]
323+
using System.Collections.Generic;
324+
using Microsoft.FSharp.Core;
325+
using Plotly.NET;
326+
using Chart = Plotly.NET.CSharp.Chart;
327+
328+
var z = EncodedTypedArray.ofFloat32Array(
329+
new[] { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f },
330+
shape: new FSharpOption<IEnumerable<int>>(new[] { 2, 3 }));
331+
var heatmap = Chart.Heatmap<string>(
332+
zEncoded: z,
333+
xEncoded: EncodedTypedArray.ofInt32Array(new[] { 10, 20, 30 }, shape: default),
334+
yEncoded: EncodedTypedArray.ofInt32Array(new[] { 100, 200 }, shape: default),
335+
ReverseYAxis: true, ShowScale: false, UseDefaults: false);
336+
```
337+
338+
## Nested data and precedence
339+
340+
Use `Dimension.initSplom` / `Dimension.initParallel` with `ValuesEncoded` for nested dimension data.
341+
Existing F# and C# SPLOM/parallel chart wrappers accept these objects. ParallelCoord and
342+
ParallelCategories also offer label/encoded-value pair conveniences.
343+
344+
For Sankey, use `SankeyNodes.init` with `XEncoded` / `YEncoded` and `SankeyLinks.init` with
345+
`SourceEncoded` / `TargetEncoded` / `ValueEncoded`, then pass the objects to `Chart.Sankey(nodes, links, ...)`.
346+
Labels remain plain strings. These shared object APIs also expose numeric `CustomDataEncoded` and
347+
`ColorEncoded`; numeric encoding does not turn color names or other strings into supported typed arrays,
348+
and each field retains its plotly.js value requirements.
349+
350+
At the trace/object layer, if one init/style call supplies both the plain and encoded parameter for
351+
the same property, the encoded value wins. For example, `Value = [ 99.0 ]` together with
352+
`ValueEncoded = EncodedTypedArray.ofFloat64Array [| 8.0 |]` serializes a single encoded `value` property.
353+
A later style call can replace that property again. The explicit chart overloads instead take
354+
encoded primary inputs directly.
355+
356+
## Supported scope and limitations
357+
358+
The examples earlier on this page use the F# API. Direct encoded C# chart overloads currently cover:
359+
360+
- `Scatter`, `Bar`, `StackedBar`, `Column`, `StackedColumn`, `Heatmap`, `Histogram2D`, and `Scatter3D`.
361+
- `ParallelCoord` / `ParallelCategories` label/encoded-value pairs.
362+
- Nested objects through existing wrappers, including SPLOM and Sankey.
363+
364+
Other direct C# wrappers, including Histogram, Surface, and map/polar/carpet families, are a later
365+
milestone. C# can also use the shared low-level core types. Existing plain overloads remain available.
366+
367+
Encoded primary arrays do not make every accompanying input encoded. For example, the encoded F#
368+
Bubble convenience still takes plain sizes, and labels/styles stay plain where the signature says so.
369+
Bar keys and Heatmap axes in these encoded overloads are numeric encoded arrays; there is no matching
370+
plain string-key argument on those overloads. Use existing plain chart overloads when needed, or
371+
compose the supported fields through the shared trace API.
372+
373+
Image pixel arrays and helpers that compute from the input values, such as Pareto, Residual, and
374+
AnnotatedHeatmap, are outside the direct encoded-overload scope. Neither a metadata option nor the
375+
existence of a numeric factory establishes support for every field or chart type.
376+
377+
## Loading Virtual-WebGL
378+
379+
Virtual-WebGL is a separate plotly.js 2.28 feature for sharing WebGL contexts. It is optional and
380+
does not enable encoded arrays. To use the WebGL 1 script (`src/virtual-webgl.js` from Virtual-WebGL
381+
1.0.6, the version used for this integration check), serve the files below with your page
382+
and load Virtual-WebGL before plotly.js, as described by the
383+
[Virtual-WebGL project](https://github.com/greggman/virtual-webgl#how-to-use).
384+
385+
Existing display options can set that order without a new wrapper API:
386+
387+
```fsharp
388+
open Giraffe.ViewEngine
389+
390+
let displayOptions =
391+
DisplayOptions.init(
392+
PlotlyJSReference = PlotlyJSReference.NoReference,
393+
AdditionalHeadTags = [
394+
script [ _src "/lib/virtual-webgl.js" ] []
395+
script [ _src "/lib/plotly-2.28.0.min.js" ] []
396+
]
397+
)
398+
399+
let standaloneHtml =
400+
Chart.Scatter(
401+
xEncoded = EncodedTypedArray.ofInt32Array [| 0; 1; 2 |],
402+
yEncoded = EncodedTypedArray.ofFloat32Array [| 1.5f; 4.5f; 2.5f |],
403+
mode = StyleParam.Mode.Markers,
404+
UseWebGL = true,
405+
UseDefaults = false
406+
)
407+
|> Chart.withDisplayOptions displayOptions
408+
|> GenericChart.toEmbeddedHTML
409+
```
410+
411+
`NoReference` prevents an earlier automatic plotly.js script tag. Replace the paths with your
412+
hosted files and use a WebGL chart, such as Scatter with `UseWebGL = true`, when exercising the
413+
virtualized contexts. `toEmbeddedHTML` emits the head tags; `toChartHTML` emits only a fragment
414+
and requires the host page to supply the scripts.
279415
*)

docs/index.fsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ Plotly.NET packages are available on NuGet to plug into your favorite package ma
8686
8787
You can include the package via an inline package reference:
8888
89-
```
89+
```text
90+
[lang=text]
9091
#r "nuget: Plotly.NET, {{fsdocs-package-version}}"
9192
```
9293
@@ -95,7 +96,8 @@ You can include the package via an inline package reference:
9596
You can use the same inline package reference as in scripts, but as an additional goodie
9697
the interactive extensions for dotnet interactive have you covered for seamless chart rendering:
9798
98-
```
99+
```text
100+
[lang=text]
99101
#r "nuget: Plotly.NET.Interactive, {{fsdocs-package-version}}"
100102
```
101103

0 commit comments

Comments
 (0)