From 3f2d5020399b633b0e24baa2b24504bad2a4b842 Mon Sep 17 00:00:00 2001 From: James Foster Date: Sat, 23 Aug 2025 00:23:00 +1000 Subject: [PATCH 1/9] [docs] Update wording in Home. --- docs/src/index.md | 50 +++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index c11eeaf7..20439685 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,52 +1,60 @@ # PlotlyJS -Welcome to the documentation for `PlotlyJS.jl`, a Julia interface to the +Welcome to the documentation for PlotlyJS.jl, a Julia interface to the [plotly.js](https://plotly.com/javascript) visualization library. -This package does not interact with the [Plotly web -API](https://api.plot.ly/v2/), but rather leverages the underlying javascript -library to construct plotly graphics using all local resources. This means you -do not need a Plotly account or an internet connection to use this package. +The goals of PlotlyJS.jl are to: -The goals of `PlotlyJS.jl` are: - -1. Make it convenient to construct and manipulate plotly visualizations -2. Provide infrastructure for viewing plots on multiple frontends and saving -plotly graphics to files +1. make it convenient to construct and manipulate plotly visualizations; +2. provide the infrastructure for viewing and interacting with plots from + different front-ends such as the Julia REPL, web browsers and IDEs; +3. save plotly graphics to files in different formats. ## Getting Help There are three primary resources for getting help with using this library: -1. The [Julia discourse page](https://discourse.julialang.org/). This is your best option if the question you have is specific to Julia. Appropriate topics include how to integrate with other Julia packages or how to use plotly features unique to `PlotlyJS.jl` -2. The [julia channel](https://community.plotly.com/c/plotly-r-matlab-julia-net/julia/23) on the plotly discussion page. This is your best option if you want visibility from other parts of the plotly community including python and R users. -3. [GitHub Issues](https://github.com/JuliaPlots/PlotlyJS.jl/issues). This is appropriate only for bug reports or feature requests. General usage questions should not be posted to GitHub, but rather should utilize one of the discussion forums above +1. The [Julia Discourse page](https://discourse.julialang.org/). + This is your best option if the question you have is specific to Julia. + Appropriate topics include how to integrate with other Julia packages + or how to use plotly features unique to PlotlyJS.jl. +2. The [julia channel](https://community.plotly.com/c/plotly-r-matlab-julia-net/julia/23) + on the plotly discussion page. This is your best option if you want visibility from other parts of the plotly community including python and R users. +3. [GitHub Issues](https://github.com/JuliaPlots/PlotlyJS.jl/issues). + This is appropriate only for bug reports or feature requests. + General usage questions should not be posted to GitHub, but rather should utilize one of the discussion forums above. ## Installation -To install `PlotlyJS.jl`, open up a Julia REPL, press `]` to enter package mode and type: +To install PlotlyJS.jl, open up a Julia REPL, press `]` to enter package mode and type: ```julia -(v1.0) pkg> add PlotlyJS +(v1.10) pkg> add PlotlyJS ``` For existing users you can run `up` from the package manager REPL mode to get the latest release. If after doing this plots do not show up in your chosen -frontend, please run `build PlotlyJS` (again from pkg REPL mode) to tell Julia -to download the latest release of the plotly.js javascript library. +front-end, please run `build PlotlyJS` (again from `pkg>` REPL mode) to tell Julia +to download the latest updates to the plotly.js JavaScript library. ### Saving figures -`PlotlyJS.jl` comes with built-in support for saving figures to files via the -integration between PlotlyBase.jl (a dependency of `PlotlyJS.jl`) and Plotly's -kaleido tool. +PlotlyJS.jl comes with built-in support for saving figures to files via the +integration between PlotlyBase.jl (a dependency of PlotlyJS.jl) and Plotly's +kaleido tool (via the PlotlyKaleido.jl package). See [exporting figures](https://juliaplots.org/PlotlyJS.jl/stable/manipulating_plots/#Saving-figures) for more information. +## Relation to Plotly.com + +This package does not interact with plotly.com or the [Plotly web API](https://api.plot.ly/v2/), +but rather leverages the underlying JavaScript library to construct plotly graphics using all local resources. +This means you do not need a Plotly account or an internet connection to use this package after installation. + ### Plots.jl If you would like to have a more exhaustive set of top-level functions for constructing plots, see the [Plots.jl](https://docs.juliaplots.org/latest/) -package. This package is the `plotlyjs` `Plots.jl` backend and is fully supported +package. This package is the `plotlyjs` backend of Plots.jl and is fully supported by Plots. From 5b056a11664e349c10efd3cb5605efeaad95d070 Mon Sep 17 00:00:00 2001 From: James Foster Date: Mon, 16 Mar 2026 22:28:33 +1100 Subject: [PATCH 2/9] More clean-up --- docs/make.jl | 4 +- docs/src/basics.md | 63 +++++++++------ docs/src/building_traces_layouts.md | 119 ++++++++++++++++------------ docs/src/examples/heatmaps.md | 2 +- docs/src/index.md | 24 +++--- docs/src/manipulating_plots.md | 14 ++-- docs/src/syncplots.md | 10 +-- 7 files changed, 134 insertions(+), 102 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index a0ef965d..0a44d8d4 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -113,10 +113,10 @@ makedocs( modules=[PlotlyJS, PlotlyBase], linkcheck=true, pages=[ - "Home" => "index.md", + "Introduction" => "index.md", "User Guide" => [ "Preliminaries" => "basics.md", - "Building Blocks" => "building_traces_layouts.md", + "Building blocks" => "building_traces_layouts.md", "Putting it together" => "syncplots.md", "Working with plots" => "manipulating_plots.md", "Contributing" => "contributing.md", diff --git a/docs/src/basics.md b/docs/src/basics.md index 94f77f9b..3716fc60 100644 --- a/docs/src/basics.md +++ b/docs/src/basics.md @@ -1,6 +1,8 @@ -## Basics +## Preliminaries -[plotly.js][_plotlyjs] figures are constructed by calling the function: +PlotlyJS is a Julia package that relies on the [plotly.js](https://plotly.com/javascript/) JavaScript library. + +In that library, figures are constructed by calling the function: ```js Plotly.newPlot(divid, data, layout, config, frames) @@ -8,28 +10,32 @@ Plotly.newPlot(divid, data, layout, config, frames) where -- `divid` is an html `div` element where the plot should appear -- `data` is an array of JSON objects describing the various `trace`s in the visualization +- `data` is an array of JSON objects describing the various _traces_ (see Note) in the visualization - `layout` is a JSON object describing the layout properties of the visualization. -- `config` is a JSON object describing the configuration properties of the visualization. See more detail [here](https://plotly.com/javascript/configuration-options/) +- `config` is a JSON object describing the configuration properties of the visualization + (see more detail [here](https://plotly.com/julia/configuration-options/)) - `frames` can contain data and layout objects, which define any changes to be animated, and a traces object that defines which traces to animate. -The `divid` argument is handled automatically by one of the supported -frontends, so users of this package will mostly be concerned about constructing -the `data`, `layout`, and (optionally) `config` and `frames` arguments. - -For a complete list of traces and their attributes see the [plotly.js chart attribute reference][_plotlyref]. +The `divid` argument is an [html `
` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/div) +to control the plot on a page and is handled automatically by one of the supported +front-ends. Users of this package will mostly be concerned about constructing +the `data` and the `layout`, and (optionally) `config` and `frames` arguments. - +!!! note + A _trace_ is a general term for how data is shown graphically on a plot, + whether it is a scatter plot, bar chart, 3D surface, choropleth map or something else. + A trace is fundamentally a collection of data and the specifications of how that data should be plotted. + For a complete list of traces and their attributes see the + [plotly.js chart attribute reference](https://plotly.com/julia/reference/). ## Julia types -There are a handful of core Julia types for representing a visualization +There are a handful of core Julia types for representing a visualization. -These are +The `data`, `layout`, `frames`, `divid` and `config` fields of the `Plot` type, shown below, +map to the arguments to the `Plotly.newplot` function. +These types are defined in the PlotlyBase.jl package (a dependency of PlotlyJS.jl). +These are shown (in a simplified form) here: ```julia abstract type AbstractTrace end @@ -41,24 +47,29 @@ end mutable struct Layout{T <: AbstractDict{Symbol,Any}} <: AbstractLayout fields::T - subplots::_Maybe{Subplots} + subplots::Subplots end mutable struct PlotlyFrame{T <: AbstractDict{Symbol,Any}} <: AbstractPlotlyAttribute fields::T end -mutable struct Plot{TT<:AbstractVector{<:AbstractTrace},TL<:AbstractLayout,TF<:AbstractVector{<:PlotlyFrame}} - data::TT - layout::TL +mutable struct PlotConfig + scrollZoom::Union{Nothing,Bool} = true + editable::Union{Nothing,Bool} = false + staticPlot::Union{Nothing,Bool} = false +... +end + +mutable struct Plot + data::Vector{<:AbstractTrace} + layout::AbstractLayout + frames::Vector{<:PlotlyFrame} divid::UUID config::PlotConfig - frames::TF end ``` -The `data`, `layout`, `divid`, `config`, and `frames` fields of the `Plot` type map 1-1 to the arguments to the `Plotly.newplot` function. - - -[_plotlyjs]: https://plotly.com/javascript/ -[_plotlyref]: https://plotly.com/julia/reference/ +The `data` field of the `Plot` type can be a single trace or a vector of multiple traces. +Each trace is itself made up of a `Dict` type holding information about the type of trace +and its data along with attributes for customising the plotting of that data. \ No newline at end of file diff --git a/docs/src/building_traces_layouts.md b/docs/src/building_traces_layouts.md index 3e1a5f07..1cbbfa29 100644 --- a/docs/src/building_traces_layouts.md +++ b/docs/src/building_traces_layouts.md @@ -1,7 +1,8 @@ -# Building Blocks +# Building blocks -```@setup traces_layous -using PlotlyJS, JSON +```@setup traces_layouts +using PlotlyJS +using JSON ``` Recall that the `Plotly.newPlot` javascript function expects to receive an @@ -22,7 +23,7 @@ end The `fields` is an AbstractDict object that maps trace attributes to their values. -We create this wrapper around a Dict to provide some convnient syntax as described below. +We create this wrapper around a Dict to provide some convenient syntax as described below. Let's consider an example. Suppose we would like to build the following JSON object: @@ -45,7 +46,7 @@ object: One way to do this in Julia is: -```@example traces_layous +```@example traces_layouts fields = Dict{Symbol,Any}(:type => "scatter", :x => [1, 2, 3, 4, 5], :y => [1, 6, 3, 6, 1], @@ -60,11 +61,11 @@ GenericTrace("scatter", fields) A more convenient syntax is: -```@setup traces_layous +```@setup traces_layouts using PlotlyJS, JSON ``` -```@example traces_layous +```@example traces_layouts t1 = scatter(;x=[1, 2, 3, 4, 5], y=[1, 6, 3, 6, 1], mode="markers+text", @@ -76,18 +77,18 @@ t1 = scatter(;x=[1, 2, 3, 4, 5], ``` Notice a few things: - - The trace `type` became the function name. There is a similar method for all -plotly.js traces types. + plotly.js traces types. - All other trace attributes were set using keyword arguments. This allows us -to avoid typing out the symbol prefix (`:`) and the arrows (`=>`) that were -necessary when constructing the `Dict` + to avoid typing out the symbol prefix (`:`) and the arrows (`=>`) that were + necessary when constructing the `Dict`. - We can set nested attributes using underscores. Notice that the JSON -`"marker": { "size": 12 }` was written `marker_size=12`. + `"marker": { "size": 12 }` was written `marker_size=12`. -We can verify that this is indeed equivalent JSON by printing the JSON: (note the order of the attributes is different, but the content is identical): +We can verify that this is indeed equivalent JSON by printing the JSON. +Note the order of the attributes is different, but the content is identical: -```@example traces_layous +```@example traces_layouts print(JSON.json(t1, 2)) ``` @@ -97,14 +98,14 @@ If we then wanted to extract a particular attribute, we can do so using `getindex(t1, :attrname)`, or the syntactic sugar `t1[:attrname]`. Note that both symbols and strings can be used in a call to `getindex`: -```@repl traces_layous +```@repl traces_layouts t1["marker"] t1[:marker] ``` To access a nested property use `parent.child` -```@repl traces_layous +```@repl traces_layouts t1["textfont.family"] ``` @@ -114,7 +115,7 @@ We can also set additional attributes. Suppose we wanted to set `marker.color` to be red. We can do this with a call to `setindex!(t1, "red", :marker_color)`, or equivalently `t1["marker_color"] = "red"`: -```@repl traces_layous +```@repl traces_layouts t1["marker_color"] = "red" println(JSON.json(t1, 2)) @@ -126,7 +127,7 @@ attribute. You can also use this syntax to add completely new nested attributes: -```@repl traces_layous +```@repl traces_layouts t1["line_width"] = 5 println(JSON.json(t1, 2)) ``` @@ -138,22 +139,23 @@ The `Layout` type is defined as ```julia mutable struct Layout{T <: AbstractDict{Symbol,Any}} <: AbstractLayout fields::T - subplots::_Maybe{Subplots} + subplots::Subplots end ``` You can construct a layout using the same convenient keyword argument syntax that we used for traces: -```@repl traces_layous +```@repl traces_layouts l = Layout(;title="Penguins", xaxis_range=[0, 42.0], xaxis_title="fish", yaxis_title="Weight", xaxis_showgrid=true, yaxis_showgrid=true, legend_y=1.15, legend_x=0.7) -println(JSON.json(l, 2)) ``` +The full JSON object can be printed with `println(JSON.json(l, 2))`. + ## `attr` There is a special function named `attr` that allows you to apply the same @@ -161,47 +163,48 @@ keyword magic we saw in the trace and layout functions, but to nested attributes. Let's revisit the previous example, but use `attr` to build up our `xaxis` and `legend`: -```@repl traces_layous +```@repl traces_layouts l2 = Layout(;title="Penguins", xaxis=attr(range=[0, 42.0], title="fish", showgrid=true), yaxis_title="Weight", yaxis_showgrid=true, legend=attr(x=0.7, y=1.15)) -println(JSON.json(l2, 2)) ``` -Notice we got the exact same output as before, but we didn't have to resort to -building the `Dict` by hand _or_ prefixing multiple arguments with `xaxis_` or +Notice we obtain exactly the same layout as before, but we didn't have to resort to +building a `Dict` by hand _or_ prefixing multiple arguments with `xaxis_` or `legend_`. ## Using `DataFrame`s !!! note - New in version 0.6.0 + DataFrame support was added in version 0.6.0. You can also construct traces using the columns of any subtype of `AbstractDataFrame` (e.g. the `DataFrame` type from DataFrames.jl). -To demonstrate this functionality let's load the famous iris data set: +To demonstrate this functionality let's load the well-known iris data set: + +```@repl traces_layouts +using DataFrames +import RDatasets -```@repl traces_layous -using DataFrames, RDatasets -iris = dataset("datasets", "iris"); +iris = RDatasets.dataset("datasets", "iris"); first(iris, 10) ``` -Suppose that we wanted to construct a scatter trace with the `SepalLength` +Suppose that we wanted to construct a scatter trace with the `SepalLength` column as the x variable and the `SepalWidth` columns as the y variable. We do this by calling -```@repl traces_layous +```@repl traces_layouts my_trace = scatter(iris, x=:SepalLength, y=:SepalWidth, marker_color=:red) [my_trace[:x][1:5] my_trace[:y][1:5]] my_trace[:marker_color] ``` How does this work? The basic rule is that if the value of any keyword argument -is a Julia Symbol (i.e. created with `:something`), then the function creating +is a Julia `Symbol` (i.e. starting with `:`, such as `:blue`), then the function creating the trace checks if that symbol is one of the column names in the DataFrame. If so, it extracts the column from the DataFrame and sets that as the value for the keyword argument. Otherwise it passes the symbol directly through. @@ -219,15 +222,18 @@ The DataFrame interface becomes more useful when constructing whole plots. See the [convenience methods](@ref constructors) section of the documentation for more information. + +## Groups + !!! note - New in version 0.9.0 + New in version 0.9.0: -As of version 0.9.0, you can construct groups of traces using the DataFrame -api. This is best understood by example, so let's see it in action: +You can construct _groups of traces_ using the DataFrame interface. +This is best understood by example, so let's see it in action: -```@repl traces_layous -iris = dataset("datasets", "iris"); -unique(iris[:Species]) +```@repl traces_layouts +iris = RDatasets.dataset("datasets", "iris"); +unique(iris[:,:Species]) traces = scatter( iris, group=:Species, x=:SepalLength, y=:SepalWidth, mode="markers", marker_size=8 ) @@ -240,16 +246,18 @@ Notice how there are three `Species` in the `iris` DataFrame, and when passing We can pass a `Vector{Symbol}` as group, to split the data on the value in more than one column: -```@repl traces_layous -tips = dataset("reshape2", "tips"); -unique(tips[:Sex]) -unique(tips[:Day]) +```@repl traces_layouts +tips = RDatasets.dataset("reshape2", "tips"); +unique(tips[:,:Sex]) +unique(tips[:,:Day]) traces = violin(tips, group=[:Sex, :Day], x=:TotalBill, orientation="h") [t[:name] for t in traces] ``` -Also new in version 0.9.0, when using the DataFrame API you are allowed to pass -a function as the value for a keyword argument. When the each trace is +## Functions + +When using the DataFrame interface you are allowed to pass +a function as the value for a keyword argument. When each trace is constructed, the value will be replaced by calling the function on whatever DataFrame is being used. When used in conjunction with the `group` argument, this allows you to _compute_ group specific trace attributes on the fly. @@ -260,20 +268,27 @@ the [Violin](@ref) example page more details. ### Facets !!! note - New in PlotlyBase version 0.6.5 (PlotlyJS version 0.16.4) + New in PlotlyBase version 0.6.5 / PlotlyJS version 0.16.4: -When plotting a `DataFrame` (let's call it `df`), the keyword arguments `facet_row` and `facet_col` allow you to create a matrix of subplots. The rows of this matrix correspond `unique(df[:facet_row])`, where `:facet_row` is a placeholder for the actual value passed as the `facet_row` argument. Similarly, the columns of the matrix of subplots come from `unique(df[:facet_col])`. +When plotting a `DataFrame` (let's call it `df`), the keyword arguments +`facet_row` and `facet_col` allow you to create a matrix of subplots. +The rows of this matrix correspond to the array `unique(df[:facet_row])`, +where `:facet_row` is a placeholder for the actual value passed as the `facet_row` argument. +Similarly, the columns of the matrix of subplots come from `unique(df[:facet_col])`. -Each subplot will have the same structure, as defined by the keyword arguments passed to `plot`, but will only show data for a single value of `facet_row` and `facet_col` at a time. +Each subplot will have the same structure, as defined by the keyword arguments passed to `plot`, +but will only show data for a single value of `facet_row` and `facet_col` at a time. -Below is an example of how this works +Below is an example of how this works: ```@repl facets -using PlotlyJS, CSV, DataFrames -df = dataset(DataFrame, "tips") +using PlotlyJS +using DataFrames + +df = PlotlyJS.dataset(DataFrame, "tips") plot( - df, x=:total_bill, y=:tip, xbingroyp="x", ybingroup="y", kind="histogram2d", + df, x=:total_bill, y=:tip, xbingroup="x", ybingroup="y", kind="histogram2d", facet_row=:sex, facet_col=:smoker ) ``` diff --git a/docs/src/examples/heatmaps.md b/docs/src/examples/heatmaps.md index de7310c9..42bc064b 100644 --- a/docs/src/examples/heatmaps.md +++ b/docs/src/examples/heatmaps.md @@ -17,7 +17,7 @@ function heatmap2() trace = heatmap( x=["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], y=["Morning", "Afternoon", "Evening"], - z=rand(1:30, 5, 3) + z=rand(1:30, 3, 5) ) plot(trace) end diff --git a/docs/src/index.md b/docs/src/index.md index 20439685..e9cd6f8e 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,7 +1,7 @@ # PlotlyJS Welcome to the documentation for PlotlyJS.jl, a Julia interface to the -[plotly.js](https://plotly.com/javascript) visualization library. +[plotly.js](https://plotly.com/javascript/) visualization library. The goals of PlotlyJS.jl are to: @@ -12,12 +12,18 @@ The goals of PlotlyJS.jl are to: ## Getting Help -There are three primary resources for getting help with using this library: +The [Plotly Julia Library](https://plotly.com/julia/) documentation has +a [quick reference guide](https://plotly.com/julia/getting-started/) +and an gallery of additional examples. + +A [single-page attribute reference](https://plotly.com/julia/reference/) is also available. + +There are three primary resources for asking for help with using this library: 1. The [Julia Discourse page](https://discourse.julialang.org/). This is your best option if the question you have is specific to Julia. Appropriate topics include how to integrate with other Julia packages - or how to use plotly features unique to PlotlyJS.jl. + or how to use plotly features unique to PlotlyJS.jl (tag as `plotlyjs`) 2. The [julia channel](https://community.plotly.com/c/plotly-r-matlab-julia-net/julia/23) on the plotly discussion page. This is your best option if you want visibility from other parts of the plotly community including python and R users. 3. [GitHub Issues](https://github.com/JuliaPlots/PlotlyJS.jl/issues). @@ -29,10 +35,10 @@ There are three primary resources for getting help with using this library: To install PlotlyJS.jl, open up a Julia REPL, press `]` to enter package mode and type: ```julia -(v1.10) pkg> add PlotlyJS +pkg> add PlotlyJS ``` -For existing users you can run `up` from the package manager REPL mode to get +For existing users you can run `up` from the package manager REPL mode to update to the latest release. If after doing this plots do not show up in your chosen front-end, please run `build PlotlyJS` (again from `pkg>` REPL mode) to tell Julia to download the latest updates to the plotly.js JavaScript library. @@ -48,13 +54,13 @@ for more information. ## Relation to Plotly.com -This package does not interact with plotly.com or the [Plotly web API](https://api.plot.ly/v2/), +This package does not interact with plotly.com or any web API, but rather leverages the underlying JavaScript library to construct plotly graphics using all local resources. This means you do not need a Plotly account or an internet connection to use this package after installation. ### Plots.jl -If you would like to have a more exhaustive set of top-level functions for +If you would like to have a more comprehensive set of top-level functions for constructing plots, see the [Plots.jl](https://docs.juliaplots.org/latest/) -package. This package is the `plotlyjs` backend of Plots.jl and is fully supported -by Plots. +package. This package is the `plotlyjs` [backend](https://docs.juliaplots.org/latest/backends/) +of Plots.jl and is fully supported by JuliaPlots. diff --git a/docs/src/manipulating_plots.md b/docs/src/manipulating_plots.md index 956c0b2e..6ea3acd1 100644 --- a/docs/src/manipulating_plots.md +++ b/docs/src/manipulating_plots.md @@ -1,7 +1,7 @@ - +# Working with plots There are various methods defined on the `Plot` type. We will cover a few of -them here, but consult the (forthcoming) API docs for more exhaustive coverage. +them here, but consult the package [API Documentation](@ref) for more exhaustive coverage. ## Julia functions @@ -13,10 +13,10 @@ create a new `divid` ## API functions -All exported functions from the plotly.js -[API](https://plotly.com/javascript/plotlyjs-function-reference/) have been -exposed to Julia and operate on both `Plot` and `SyncPlot` instances. Each of -these functions has semantics that match the semantics of plotly.js +All exported functions from the [plotly.js API](https://plotly.com/javascript/plotlyjs-function-reference/) +have been exposed to Julia and operate on both `Plot` and `SyncPlot` instances. +Each of these functions has semantics that match the semantics of plotly.js library. + In `PlotlyJS.jl` these functions are spelled: @@ -41,7 +41,7 @@ plot, it keeps the Julia object and the display in sync. For more details on which methods are available for each of the above functions -consult the docstrings or (forthcoming) API documentation. +consult the docstrings or [API Documentation](@ref). !!! note Be especially careful when trying to use `restyle!`, `extendtraces!`, and diff --git a/docs/src/syncplots.md b/docs/src/syncplots.md index 9a48d223..d3dc9a11 100644 --- a/docs/src/syncplots.md +++ b/docs/src/syncplots.md @@ -1,4 +1,4 @@ -# Putting it Together +# Putting it together ```@meta CurrentModule = PlotlyJS @@ -6,7 +6,7 @@ CurrentModule = PlotlyJS We will now look at how to combine traces and a layout to create a plot. -We'll also discuss how to integrate with various frontends. +We'll also discuss how to integrate with various front-ends. ## `Plot` @@ -70,9 +70,9 @@ p = Plot(iris, x=:SepalLength, y=:SepalWidth, mode="markers", marker_size=8, gro A `Plot` is a pure Julia object and doesn't interact with plotly.js by itself. This means that we can't view the actual plotly figure the data represents. -To do that we need to link the `Plot` to one or more display frontends. +To do that we need to link the `Plot` to one or more display front-ends. -To actually connect to the display frontends we use the +To actually connect to the display front-ends we use the [WebIO.jl](https://github.com/JuliaGizmos/WebIO.jl) package. Our interaction with WebIO is wrapped up in a type called `SyncPlot` that is defined as follows: @@ -86,7 +86,7 @@ end ``` As its name suggests, a `SyncPlot` will keep the Julia representation of the a -plot (the `Plot` instance) in sync with a plot with a frontend. +plot (the `Plot` instance) in sync with a plot with a front-end. !!! note The `Plot` function will create a new `Plot` object and the `plot` function From 2f78fcdf4925286bd85cce5e44bf65d616dec6de Mon Sep 17 00:00:00 2001 From: James Foster Date: Mon, 30 Mar 2026 17:40:03 +1100 Subject: [PATCH 3/9] Revise 'Building blocks' --- docs/src/basics.md | 31 +++--- docs/src/building_traces_layouts.md | 152 +++++++++++++++++++--------- docs/src/manipulating_plots.md | 2 - 3 files changed, 124 insertions(+), 61 deletions(-) diff --git a/docs/src/basics.md b/docs/src/basics.md index 3716fc60..fce2353e 100644 --- a/docs/src/basics.md +++ b/docs/src/basics.md @@ -1,6 +1,6 @@ ## Preliminaries -PlotlyJS is a Julia package that relies on the [plotly.js](https://plotly.com/javascript/) JavaScript library. +PlotlyJS.jl is a Julia package that relies on the [plotly.js](https://plotly.com/javascript/) JavaScript library. In that library, figures are constructed by calling the function: @@ -10,11 +10,12 @@ Plotly.newPlot(divid, data, layout, config, frames) where -- `data` is an array of JSON objects describing the various _traces_ (see Note) in the visualization -- `layout` is a JSON object describing the layout properties of the visualization. +- `data` is an array of JSON objects describing the various data _traces_ (see Note) in the visualization +- `layout` is a JSON object describing the presentation properties of the visualization - `config` is a JSON object describing the configuration properties of the visualization (see more detail [here](https://plotly.com/julia/configuration-options/)) -- `frames` can contain data and layout objects, which define any changes to be animated, and a traces object that defines which traces to animate. +- `frames` can contain data and layout objects, which define any changes to be animated, + and a traces object that defines which traces to animate. The `divid` argument is an [html `
` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/div) to control the plot on a page and is handled automatically by one of the supported @@ -23,11 +24,15 @@ the `data` and the `layout`, and (optionally) `config` and `frames` arguments. !!! note A _trace_ is a general term for how data is shown graphically on a plot, - whether it is a scatter plot, bar chart, 3D surface, choropleth map or something else. + whether it is a scatter plot, bar chart, 3D surface, choropleth map or some other plot type. A trace is fundamentally a collection of data and the specifications of how that data should be plotted. For a complete list of traces and their attributes see the [plotly.js chart attribute reference](https://plotly.com/julia/reference/). +When we want to construct a `Plot` in PlotlyJS.jl for plotting on some display, we will usually have +at least one trace `tr` along with a layout object `ly` which we combine together as `Plot(tr, ly)`. +If we don't have a layout object then a default template will supply the layout for us. + ## Julia types There are a handful of core Julia types for representing a visualization. @@ -35,23 +40,23 @@ There are a handful of core Julia types for representing a visualization. The `data`, `layout`, `frames`, `divid` and `config` fields of the `Plot` type, shown below, map to the arguments to the `Plotly.newplot` function. These types are defined in the PlotlyBase.jl package (a dependency of PlotlyJS.jl). -These are shown (in a simplified form) here: +These are shown (in a much simplified form) here: ```julia abstract type AbstractTrace end abstract type AbstractLayout end -mutable struct GenericTrace{T <: AbstractDict{Symbol,Any}} <: AbstractTrace - fields::T +mutable struct GenericTrace <: AbstractTrace + fields::Dict{Symbol,Any} end -mutable struct Layout{T <: AbstractDict{Symbol,Any}} <: AbstractLayout - fields::T +mutable struct Layout <: AbstractLayout + fields::Dict{Symbol,Any} subplots::Subplots end -mutable struct PlotlyFrame{T <: AbstractDict{Symbol,Any}} <: AbstractPlotlyAttribute - fields::T +mutable struct PlotlyFrame <: AbstractPlotlyAttribute + fields::Dict{Symbol,Any} end mutable struct PlotConfig @@ -70,6 +75,6 @@ mutable struct Plot end ``` -The `data` field of the `Plot` type can be a single trace or a vector of multiple traces. +The `data` field of the `Plot` type can be constructed from a single trace or a vector of multiple traces. Each trace is itself made up of a `Dict` type holding information about the type of trace and its data along with attributes for customising the plotting of that data. \ No newline at end of file diff --git a/docs/src/building_traces_layouts.md b/docs/src/building_traces_layouts.md index 1cbbfa29..f3f63d4a 100644 --- a/docs/src/building_traces_layouts.md +++ b/docs/src/building_traces_layouts.md @@ -2,18 +2,23 @@ ```@setup traces_layouts using PlotlyJS -using JSON +import JSON ``` -Recall that the `Plotly.newPlot` javascript function expects to receive an -array of `trace` objects and, optionally, a `layout` object. In this section we -will learn how to build these object in Julia. +In [Preliminaries](@ref) we saw that the `Plotly.newPlot` javascript function +expects to receive an array of `trace` objects and, optionally, a `layout` object. + +In this section we will learn how to build the trace and layout objects in Julia +that make up the core elements of a plot. + ## Traces -A `Plot` instance will have a vector of `trace`s. These should each be a subtype of `AbstractTrace`. +A `Plot` instance will have a single trace or a vector of traces. +These should each be a subtype of `AbstractTrace`. -PlotlyJS.jl defines one such subtype: +PlotlyBase.jl provides one such general-purpose subtype `GenericTrace` +defined as ```julia mutable struct GenericTrace{T <: AbstractDict{Symbol,Any}} <: AbstractTrace @@ -21,12 +26,20 @@ mutable struct GenericTrace{T <: AbstractDict{Symbol,Any}} <: AbstractTrace end ``` -The `fields` is an AbstractDict object that maps trace attributes to their values. +Here `fields` is an `AbstractDict` object that pairs a trace's attributes to their values. +The `GenericTrace` subtype allows us to generically include data to describe the appearance +of a trace, such as point locations, marker shape and size, text annotations and more. +The reason we create a `GenericTrace` as a wrapper around a `Dict` is to provide some convenient syntax, +as described below. -We create this wrapper around a Dict to provide some convenient syntax as described below. +Let's consider an example. + +!!! note + The next example can be used as a guide to translating examples using + the plotly.js JavaScript library to their equivalent Julia versions. -Let's consider an example. Suppose we would like to build the following JSON -object: +Suppose we would like to build a `Plot` to include a `scatter`-type trace +as described here using [JSON](https://developer.mozilla.org/en-US/docs/Glossary/JSON): ```json { @@ -44,7 +57,7 @@ object: } ``` -One way to do this in Julia is: +One way to do this in Julia is to create an equivalent dictionary: ```@example traces_layouts fields = Dict{Symbol,Any}(:type => "scatter", @@ -59,11 +72,7 @@ fields = Dict{Symbol,Any}(:type => "scatter", GenericTrace("scatter", fields) ``` -A more convenient syntax is: - -```@setup traces_layouts -using PlotlyJS, JSON -``` +A more convenient approach uses the syntax of the `scatter` function: ```@example traces_layouts t1 = scatter(;x=[1, 2, 3, 4, 5], @@ -89,13 +98,15 @@ We can verify that this is indeed equivalent JSON by printing the JSON. Note the order of the attributes is different, but the content is identical: ```@example traces_layouts +import JSON + print(JSON.json(t1, 2)) ``` ### Accessing attributes If we then wanted to extract a particular attribute, we can do so using -`getindex(t1, :attrname)`, or the syntactic sugar `t1[:attrname]`. Note that +`getindex(t1, :attrname)`, or more directly, `t1[:attrname]`. Note that both symbols and strings can be used in a call to `getindex`: ```@repl traces_layouts @@ -103,12 +114,31 @@ t1["marker"] t1[:marker] ``` -To access a nested property use `parent.child` +To access a nested property use a string of the form `parent.child` ```@repl traces_layouts t1["textfont.family"] ``` +or nested dictionaries + +```@repl traces_layouts +t1[:textfont][:family] +``` + +!!! warn + Nested dictionaries will error on missing symbol keys, however using + unrecognised or unassigned strings as keys will return empty dictionaries. + For example, + ```@repl traces_layouts + t1[:textfont][:color] + ``` + returns an error while + ```@repl traces_layouts + t1["textfont.color"] + ``` + is an empty `Dict`. + ### Setting additional attributes We can also set additional attributes. Suppose we wanted to set `marker.color` @@ -148,31 +178,44 @@ that we used for traces: ```@repl traces_layouts l = Layout(;title="Penguins", - xaxis_range=[0, 42.0], xaxis_title="fish", + xaxis_range=[0, 42.0], + xaxis_title="Fish Count", yaxis_title="Weight", - xaxis_showgrid=true, yaxis_showgrid=true, - legend_y=1.15, legend_x=0.7) + xaxis_showgrid=true, + yaxis_showgrid=true, + legend_x=0.7, legend_y=1.15,) ``` -The full JSON object can be printed with `println(JSON.json(l, 2))`. +Here we set different attributes for determining the non-data layout of the plot +such as the `range` and `title` of the horizontal (`xaxis`) and vertical (`yaxis`) axes +of the plot, whether the grid lines are drawn and the position of the legend. + +!!! note + A _layout_ is a general term for how non-data elements are displayed on a plot. + There is only one layout object used for any given plot (while we may have multiple traces). + For a complete list of layout attributes see the + [layout reference documentation](https://plotly.com/julia/reference/layout/). -## `attr` + +## The `attr` function There is a special function named `attr` that allows you to apply the same -keyword magic we saw in the trace and layout functions, but to nested -attributes. Let's revisit the previous example, but use `attr` to build up our -`xaxis` and `legend`: +keyword magic we saw in the trace and layout functions with underscores, +but to nested attributes at the same level. + +Let's revisit the previous example, but use `attr` to build up our +`xaxis` or `legend` attributes in a way that groups things together: ```@repl traces_layouts l2 = Layout(;title="Penguins", - xaxis=attr(range=[0, 42.0], title="fish", showgrid=true), + xaxis=attr(range=[0, 42.0], title="Fish Count", showgrid=true), yaxis_title="Weight", yaxis_showgrid=true, legend=attr(x=0.7, y=1.15)) ``` Notice we obtain exactly the same layout as before, but we didn't have to resort to building a `Dict` by hand _or_ prefixing multiple arguments with `xaxis_` or -`legend_`. +`legend_`. Notice also that we can mix the different approaches in the one object. ## Using `DataFrame`s @@ -181,9 +224,10 @@ building a `Dict` by hand _or_ prefixing multiple arguments with `xaxis_` or DataFrame support was added in version 0.6.0. You can also construct traces using the columns of any subtype of -`AbstractDataFrame` (e.g. the `DataFrame` type from DataFrames.jl). +`AbstractDataFrame`, such as the `DataFrame` type from the DataFrames.jl +package in particular. -To demonstrate this functionality let's load the well-known iris data set: +To demonstrate this functionality let's load the well-known "iris" data set: ```@repl traces_layouts using DataFrames @@ -194,17 +238,15 @@ first(iris, 10) ``` Suppose that we wanted to construct a scatter trace with the `SepalLength` -column as the x variable and the `SepalWidth` columns as the y variable. We -do this by calling +column as the `x` variable and the `SepalWidth` columns as the `y` variable. +We do this by calling `scatter()` with a dataframe as the first argument: ```@repl traces_layouts my_trace = scatter(iris, x=:SepalLength, y=:SepalWidth, marker_color=:red) -[my_trace[:x][1:5] my_trace[:y][1:5]] -my_trace[:marker_color] ``` How does this work? The basic rule is that if the value of any keyword argument -is a Julia `Symbol` (i.e. starting with `:`, such as `:blue`), then the function creating +is a Julia `Symbol` (i.e. starting with `:`, such as `:one`), then the function creating the trace checks if that symbol is one of the column names in the DataFrame. If so, it extracts the column from the DataFrame and sets that as the value for the keyword argument. Otherwise it passes the symbol directly through. @@ -218,17 +260,24 @@ However, when setting `marker_color=:red` we found that `:red` is not one of the column names, so the value for the `marker_color` keyword argument remained `:red`. +We can access and inspect the values of the resulting trace object: +```@repl traces_layouts +[my_trace[:x][1:5] my_trace[:y][1:5]] +my_trace[:marker_color] +``` + The DataFrame interface becomes more useful when constructing whole plots. See the [convenience methods](@ref constructors) section of the documentation for more information. -## Groups +### Groups !!! note New in version 0.9.0: -You can construct _groups of traces_ using the DataFrame interface. +You can construct _groups of traces_ using the DataFrame interface +through the `group` keyword. This is best understood by example, so let's see it in action: ```@repl traces_layouts @@ -240,27 +289,35 @@ traces = scatter( [t[:name] for t in traces] ``` -Notice how there are three `Species` in the `iris` DataFrame, and when passing +Notice how there are three `Species` in the `iris` DataFrame, and by passing `group=:Species` to `scatter` we obtained three traces. -We can pass a `Vector{Symbol}` as group, to split the data on the value in more -than one column: +We can pass a `Vector{Symbol}` with the `group` keyword, to split the data according +to the values of more than one column. + +Here we split data by day of the week and time: ```@repl traces_layouts tips = RDatasets.dataset("reshape2", "tips"); unique(tips[:,:Sex]) unique(tips[:,:Day]) -traces = violin(tips, group=[:Sex, :Day], x=:TotalBill, orientation="h") +traces = violin(tips, group=[:Day, :Time], x=:TotalBill, orientation="h") [t[:name] for t in traces] ``` -## Functions +### Functions -When using the DataFrame interface you are allowed to pass +When using the DataFrame interface you may pass a function as the value for a keyword argument. When each trace is constructed, the value will be replaced by calling the function on whatever DataFrame is being used. When used in conjunction with the `group` argument, -this allows you to _compute_ group specific trace attributes on the fly. +this allows you to _compute_ group specific trace attributes on the fly, +such as dynamically annotating a plot based on the data. +For example, you might want to show the sample length with the `text` attribute: + +``` +text=(df) -> "Sample length $(size(df, 1))" +``` See the docstring for `GenericTrace` and the `violin_side_by_side` example on the [Violin](@ref) example page more details. @@ -271,7 +328,8 @@ the [Violin](@ref) example page more details. New in PlotlyBase version 0.6.5 / PlotlyJS version 0.16.4: When plotting a `DataFrame` (let's call it `df`), the keyword arguments -`facet_row` and `facet_col` allow you to create a matrix of subplots. +`facet_row` and `facet_col` allow you to create a _matrix_ of subplots. + The rows of this matrix correspond to the array `unique(df[:facet_row])`, where `:facet_row` is a placeholder for the actual value passed as the `facet_row` argument. Similarly, the columns of the matrix of subplots come from `unique(df[:facet_col])`. @@ -279,7 +337,9 @@ Similarly, the columns of the matrix of subplots come from `unique(df[:facet_col Each subplot will have the same structure, as defined by the keyword arguments passed to `plot`, but will only show data for a single value of `facet_row` and `facet_col` at a time. -Below is an example of how this works: +Below is an example of how this works. We have a distinction of Male and Female between rows +and a distinction of Smoker or Non-Smoker between columns, creating a two-by-two matrix of +four plots: ```@repl facets using PlotlyJS diff --git a/docs/src/manipulating_plots.md b/docs/src/manipulating_plots.md index 6ea3acd1..181b8f2a 100644 --- a/docs/src/manipulating_plots.md +++ b/docs/src/manipulating_plots.md @@ -38,8 +38,6 @@ object (in the `plot` field on the `SyncPlot`) is updated and the plotly.js function is called. This is where `SyncPlot` gets its name: when modifying a plot, it keeps the Julia object and the display in sync. - - For more details on which methods are available for each of the above functions consult the docstrings or [API Documentation](@ref). From 12dcc86c864cd938b02e81522adb0b9d302797fc Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 31 Mar 2026 00:25:37 +1100 Subject: [PATCH 4/9] Update 'Putting it together' --- docs/src/basics.md | 4 +- docs/src/building_traces_layouts.md | 6 +- docs/src/syncplots.md | 96 +++++++++++++++++++++-------- 3 files changed, 78 insertions(+), 28 deletions(-) diff --git a/docs/src/basics.md b/docs/src/basics.md index fce2353e..1ccc6cb3 100644 --- a/docs/src/basics.md +++ b/docs/src/basics.md @@ -17,7 +17,7 @@ where - `frames` can contain data and layout objects, which define any changes to be animated, and a traces object that defines which traces to animate. -The `divid` argument is an [html `
` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/div) +The `divid` argument refers to an [html `
` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/div) to control the plot on a page and is handled automatically by one of the supported front-ends. Users of this package will mostly be concerned about constructing the `data` and the `layout`, and (optionally) `config` and `frames` arguments. @@ -27,7 +27,7 @@ the `data` and the `layout`, and (optionally) `config` and `frames` arguments. whether it is a scatter plot, bar chart, 3D surface, choropleth map or some other plot type. A trace is fundamentally a collection of data and the specifications of how that data should be plotted. For a complete list of traces and their attributes see the - [plotly.js chart attribute reference](https://plotly.com/julia/reference/). + [plotly figure reference](https://plotly.com/julia/reference/). When we want to construct a `Plot` in PlotlyJS.jl for plotting on some display, we will usually have at least one trace `tr` along with a layout object `ly` which we combine together as `Plot(tr, ly)`. diff --git a/docs/src/building_traces_layouts.md b/docs/src/building_traces_layouts.md index f3f63d4a..8a48168c 100644 --- a/docs/src/building_traces_layouts.md +++ b/docs/src/building_traces_layouts.md @@ -327,11 +327,13 @@ the [Violin](@ref) example page more details. !!! note New in PlotlyBase version 0.6.5 / PlotlyJS version 0.16.4: +A _facet_ is another name for a plot displaying a subset of a larger dataset. + When plotting a `DataFrame` (let's call it `df`), the keyword arguments -`facet_row` and `facet_col` allow you to create a _matrix_ of subplots. +`facet_row` and `facet_col` allow you to create a _matrix_ of [subplots](@ref Subplots). The rows of this matrix correspond to the array `unique(df[:facet_row])`, -where `:facet_row` is a placeholder for the actual value passed as the `facet_row` argument. +where `:facet_row` is a placeholder for the actual symbol passed as the `facet_row` argument. Similarly, the columns of the matrix of subplots come from `unique(df[:facet_col])`. Each subplot will have the same structure, as defined by the keyword arguments passed to `plot`, diff --git a/docs/src/syncplots.md b/docs/src/syncplots.md index d3dc9a11..56f25fd7 100644 --- a/docs/src/syncplots.md +++ b/docs/src/syncplots.md @@ -50,11 +50,36 @@ unique identification of multiple plots in a single web page. There are also a number of convenience methods to the `Plot` function that will attempt to construct the traces for you. They have the following signatures +that show a variety of arguments that can be used to create a plot: ```@docs PlotlyBase.Plot ``` +Here are some examples: + +```@example +t = range(0, 3, 41); +p0 = Plot([0, 1, 3], [10, 5, 2]) +plot(p1) +``` + +```@example +t = range(0, 3, 41); +p1 = Plot(t, [2sin.(t) 3cos.(t) cos.(t).-sin.(t)], Layout(showlegend=true)) +plot(p1) +``` + +```@example +p2 = Plot(x -> (x - 0.6)^2, -2, 2, Layout(showlegend=false)) +plot(p2) +``` + +```@example +p3 = Plot([sin, cos], 0, 2*pi) +plot(p3) +``` + Especially convenient is the `group` keyword argument when calling `Plot(::AbstractDataFrame, ... ; ...)`. Here is an example below: @@ -62,15 +87,22 @@ Especially convenient is the `group` keyword argument when calling using PlotlyJS # hide using RDatasets iris = RDatasets.dataset("datasets", "iris"); -p = Plot(iris, x=:SepalLength, y=:SepalWidth, mode="markers", marker_size=8, group=:Species) +p = Plot(iris, x=:SepalLength, y=:SepalWidth, mode="markers", marker_size=8, + group=:Species, + Layout(title="Iris Species")) +plot(p) ``` +See the section on [Groups](@ref) for more detail. + ## `SyncPlot`s A `Plot` is a pure Julia object and doesn't interact with plotly.js by itself. -This means that we can't view the actual plotly figure the data represents. +This means that we can't view the actual plotly figure that the data represents +until we have a way to display it to the screen. To do that we need to link the `Plot` to one or more display front-ends. +The (lowercase) `plot()` function is used to set up the link. To actually connect to the display front-ends we use the [WebIO.jl](https://github.com/JuliaGizmos/WebIO.jl) package. Our interaction @@ -85,44 +117,57 @@ mutable struct SyncPlot end ``` -As its name suggests, a `SyncPlot` will keep the Julia representation of the a +As its name suggests, a `SyncPlot` will keep the Julia representation of a plot (the `Plot` instance) in sync with a plot with a front-end. +The `scope` field refers to a `WebIO.Scope` object used for passing messages +between Julia and JavaScript. !!! note - The `Plot` function will create a new `Plot` object and the `plot` function + The `Plot` function will create a new `Plot` object while the `plot` function will create a new `SyncPlot`. The `plot` function passes all arguments - to construct a `Plot` and then sets up the display. All `Plot` methods are also defined for `plot` + to construct a `Plot` and then sets up the display. + All `Plot` methods are also defined for `plot`. By leveraging WebIO.jl we can render our figures anywhere WebIO can render. At time of writing this includes [Jupyter notebooks](https://jupyter.org/), [Jupyterlab](https://github.com/jupyterlab/jupyterlab), -[Mux.jl](https://github.com/JuliaWeb/Mux.jl) web apps, the -[Juno](https://junolab.org/) Julia environment inside the Atom text editor, and -Electron windows from [Blink.jl](https://github.com/JuliaGizmos/Blink.jl). Please -see the [WebIO.jl readme](https://github.com/JuliaGizmos/WebIO.jl) for -additional (and up to date!) information. +[Mux.jl](https://github.com/JuliaWeb/Mux.jl) web apps, and +Electron windows from [Blink.jl](https://github.com/JuliaGizmos/Blink.jl). +Please see the [WebIO.jl documentation](https://juliagizmos.github.io/WebIO.jl/latest/gettingstarted/#Getting-Started) +for additional information. + +When using PlotlyJS.jl at the Julia REPL a plot will automatically be displayed +in two possible ways. + +A `Plot()` call will try to launch the application that handles `.html` +files on the user's computer, typically their default browser. -When using `PlotlyJS.jl` at the Julia REPL a plot will automatically be displayed -in an Electron window. This is a dedicated browser window we have full control -over. To see a plot `p`, just type `p` by itself at the REPL and execute the -line. Alternatively you can call `display(p)`. +A `plot()` call will launch a new Electron window. This is a dedicated +browser window we have full control over. To see a plot `p`, just type `p` by +itself at the REPL and execute the line. Alternatively you can call `display(p)`. In addition to being able to see our charts in many front-end environments, -WebIO also provides a 2-way communication bridge between javascript and Julia. +WebIO also provides a two-way communication bridge between JavaScript and Julia. In fact, when a `SyncPlot` is constructed, we automatically get listeners for all [plotly.js javascript events](https://plotly.com/javascript/plotlyjs-events/). + + What's more is that we can hook up Julia functions as callbacks when those events are triggered. In the very contrived example below we have Julia print out details regarding points on a plot whenever a user hovers over them on the display: ```julia -using WebIO +using PlotlyJS +using PlotlyJS: WebIO p = plot(rand(10, 4)); display(p) # usually optional -on(p["hover"]) do data - println("\nYou hovered over", data) +WebIO.on(p["hover"]) do data + if haskey(data, "points") + pt = first(data["points"]) + println("\nYou hovered over the point x=", pt["x"], ", y=", pt["y"])) + end end ``` @@ -130,7 +175,8 @@ In this next example, whenever we click on a point we change its marker symbol to a star and marker color to gold: ```julia -using WebIO +using PlotlyJS +using PlotlyJS: WebIO colors = (fill("red", 10), fill("blue", 10)) symbols = (fill("circle", 10), fill("circle", 10)) ys = (rand(10), rand(10)) @@ -140,7 +186,7 @@ p = plot( ) display(p) # usually optional -on(p["click"]) do data +WebIO.on(p["click"]) do data colors = (fill("red", 10), fill("blue", 10)) symbols = (fill("circle", 10), fill("circle", 10)) for point in data["points"] @@ -151,19 +197,21 @@ on(p["click"]) do data end ``` -While completely nonsensical, hopefully these examples show you that it is +While mostly nonsensical, hopefully these examples show you that it is possible to build rich, interactive, web-based data visualization applications with business logic implemented entirely in Julia!. -### Display configuration +## Display configuration !!! note New in PlotlyBase version 0.6.4 (PlotlyJS version 0.16.3) -When calling `plot` or `Plot`, we can specify some configuration options using the `config` keyword argument. +When calling `plot` or `Plot`, we can specify some configuration options +using the `config` keyword argument. -The `config` argument must be set to an instance of `PlotConfig`, which should be constructed using keyword arguments. +The `config` argument must be set to an instance of `PlotConfig`, +which should be constructed using keyword arguments. As an example, if we were to execute the following code, we would see a static chart (no hover information or ability to zoom/pan) with 4 lines instead of an From 1366591ef73e041866905f9e1d0a17e4f3e59743 Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 31 Mar 2026 16:50:53 +1100 Subject: [PATCH 5/9] Final edit and check --- docs/src/basics.md | 5 +- docs/src/building_traces_layouts.md | 11 +++-- docs/src/contributing.md | 24 ++++++---- docs/src/manipulating_plots.md | 74 +++++++++++++++-------------- docs/src/syncplots.md | 36 +++++++------- 5 files changed, 81 insertions(+), 69 deletions(-) diff --git a/docs/src/basics.md b/docs/src/basics.md index 1ccc6cb3..0726a0ad 100644 --- a/docs/src/basics.md +++ b/docs/src/basics.md @@ -10,7 +10,8 @@ Plotly.newPlot(divid, data, layout, config, frames) where -- `data` is an array of JSON objects describing the various data _traces_ (see Note) in the visualization +- `data` is an array of [JSON](https://developer.mozilla.org/en-US/docs/Glossary/JSON) objects + describing the various data _traces_ in the visualization (see Note) - `layout` is a JSON object describing the presentation properties of the visualization - `config` is a JSON object describing the configuration properties of the visualization (see more detail [here](https://plotly.com/julia/configuration-options/)) @@ -31,7 +32,7 @@ the `data` and the `layout`, and (optionally) `config` and `frames` arguments. When we want to construct a `Plot` in PlotlyJS.jl for plotting on some display, we will usually have at least one trace `tr` along with a layout object `ly` which we combine together as `Plot(tr, ly)`. -If we don't have a layout object then a default template will supply the layout for us. +If we don't have a layout object then a template will supply a default layout for us. ## Julia types diff --git a/docs/src/building_traces_layouts.md b/docs/src/building_traces_layouts.md index 8a48168c..87657568 100644 --- a/docs/src/building_traces_layouts.md +++ b/docs/src/building_traces_layouts.md @@ -5,7 +5,7 @@ using PlotlyJS import JSON ``` -In [Preliminaries](@ref) we saw that the `Plotly.newPlot` javascript function +In [Preliminaries](@ref) we saw that the `Plotly.newPlot` JavaScript function expects to receive an array of `trace` objects and, optionally, a `layout` object. In this section we will learn how to build the trace and layout objects in Julia @@ -339,18 +339,19 @@ Similarly, the columns of the matrix of subplots come from `unique(df[:facet_col Each subplot will have the same structure, as defined by the keyword arguments passed to `plot`, but will only show data for a single value of `facet_row` and `facet_col` at a time. -Below is an example of how this works. We have a distinction of Male and Female between rows -and a distinction of Smoker or Non-Smoker between columns, creating a two-by-two matrix of +Below is an example of how this works. We have a distinction of male/female between rows +and a distinction of smoker/non-smoker between columns, creating a two-by-two matrix of four plots: -```@repl facets +```@example facets using PlotlyJS +import CSV using DataFrames df = PlotlyJS.dataset(DataFrame, "tips") plot( df, x=:total_bill, y=:tip, xbingroup="x", ybingroup="y", kind="histogram2d", - facet_row=:sex, facet_col=:smoker + facet_row=:sex, facet_col=:smoker, colorbar_showticklabels=false ) ``` diff --git a/docs/src/contributing.md b/docs/src/contributing.md index a6d8113a..a6f31510 100644 --- a/docs/src/contributing.md +++ b/docs/src/contributing.md @@ -6,15 +6,16 @@ out the [issue list](https://github.com/JuliaPlots/PlotlyJS.jl/issues). If submitting pull requests on GitHub is intimidating, we're happy to help you work through getting your code polished up and included in the right places. -Other projects that are helpful are: +Other tasks or small projects that are helpful are: -- Adding docstrings to function names +- Adding [docstrings](https://docs.julialang.org/en/v1/manual/documentation/#Writing-Documentation) + to function names - Adding more examples to the documentation (see below) - Submitting feature requests or bug reports ### Documentation -The documentation for `PlotlyJS.jl` is contained in the `docs` directory of this +The documentation for PlotlyJS.jl is contained in the `docs` directory of this repository. Docs are build using the `Documenter.jl` package and can be built following these steps: @@ -41,19 +42,24 @@ to open one of the files in that directory and add a new 0 argument function that constructs and returns a `SyncPlot` object (this is the output of the `plot` function). -For example, if we wanted to add an example of a scatter plot of the sin function we could add the following function definition inside the `examples/line_scatter.jl` file: +For example, if we wanted to add an example of a scatter plot of the sine function +we could add the following function definition inside the `examples/line_scatter.jl` file: ```julia -function sin_scatter() +function sine_scatter() x = range(0, stop=2*pi, length=50) - y = sin(x) - plot(scatter(x=x, y=y, marker_symbol="line-nw", mode="markers+symbols")) + y = sin.(x) + plot(scatter(x=x, y=y, marker_symbol="triangle-nw-dot", mode="markers+symbols")) end ``` The next step is to have Julia re-build the markdown (`.md`) files in `docs/examples` to use all your new functions in the Julia files from the -`examples` folder. To do this run the script `docs/build_example_docs.jl`. If I -were in the root directory of the repository, I could do this by running `julia docs/build_example_docs.jl`. +`examples` folder. To do this run the script `docs/build_example_docs.jl`. +If I were in the root directory of the repository, I could do this by running +from the command line +``` +julia docs/build_example_docs.jl +``` The final step is to build the docs again using one of the commands from above. diff --git a/docs/src/manipulating_plots.md b/docs/src/manipulating_plots.md index 181b8f2a..26992e8e 100644 --- a/docs/src/manipulating_plots.md +++ b/docs/src/manipulating_plots.md @@ -8,27 +8,29 @@ them here, but consult the package [API Documentation](@ref) for more exhaustive `Plot` and `SyncPlot` both have implementations of common Julia methods: - `size`: returns the `width` and `layout` attributes in the plot's layout -- `copy`: create a shallow copy of all traces in the plot and the layout, but -create a new `divid` +- `copy`: creates a shallow copy of all traces in the plot and the layout + (but creates a new `divid` for controlling interaction with HTML layouts). +- `show`: draws the plot, where the specific form it takes depends on the + context it is called in (such as the REPL, a notebook or for a web page). -## API functions +## Plotly API functions All exported functions from the [plotly.js API](https://plotly.com/javascript/plotlyjs-function-reference/) have been exposed to Julia and operate on both `Plot` and `SyncPlot` instances. Each of these functions has semantics that match the semantics of plotly.js library. -In `PlotlyJS.jl` these functions are spelled: +In PlotlyJS.jl these functions are spelled: -- [`restyle!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlyrestyle): edit attributes on one or more traces -- [`relayout!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlyrelayout): edit attributes on the layout -- [`update!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlyupdate): combination of `restyle!` and `relayout!` -- [`react!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlyreact): In place updating of all traces and layout in plot. More efficient than constructing an entirely new plot from scratch, but has the same effect. -- [`addtraces!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlyaddtraces): add traces to a plot at specified indices -- [`deletetraces!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlydeletetraces): delete specific traces from a plot -- [`movetraces!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlymovetraces): reorder traces in a plot -- [`redraw!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlyredraw): for a redraw of an entire plot -- [`purge!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlypurge): completely remove all data and layout from the chart +- [`restyle!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlyrestyle): Edit attributes on one or more traces +- [`relayout!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlyrelayout): Edit attributes on the layout +- [`update!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlyupdate): A combination of `restyle!` and `relayout!` +- [`react!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlyreact): In-place updating of all traces and layout in plot. More efficient than constructing an entirely new plot from scratch, but has the same effect. +- [`addtraces!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlyaddtraces): Add traces to a plot at specified indices +- [`deletetraces!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlydeletetraces): Delete specific traces from a plot +- [`movetraces!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlymovetraces): Reorder traces in a plot +- [`redraw!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlyredraw): Redraw an entire plot +- [`purge!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlypurge): Completely remove all data and layout from the chart - [`extendtraces!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlyextendtraces): Extend specific attributes of one or more traces with more data by appending to the end of the attribute - [`prependtraces!`](https://plotly.com/javascript/plotlyjs-function-reference/#plotlyprependtraces): Prepend additional data to specific attributes on one or more traces @@ -52,20 +54,20 @@ A common task is to construct subpots, or plots with more than one set of axes. This is possible using the declarative plotly.js syntax, but can be tedious at best. -`PlotlyJS.jl` provides a convenient syntax for constructing what we will -call regular grids of subplots. By regular we mean a square grid of plots. +PlotlyJS.jl provides a convenient syntax for constructing what we will +call regular grids of subplots. By regular we mean a square grid of plots like a matrix. -To do this we will make a pun of the `vcat`, `hcat`, and `hvcat` functions from +To do this we adapt the `vcat`, `hcat`, and `hvcat` functions from `Base` and leverage the array construction syntax to build up our subplots. Suppose we are working with the following plots: ```@repl subplots using PlotlyJS # hide -p1 = Plot(scatter(;y=randn(3))) -p2 = Plot(histogram(;x=randn(50), nbinsx=4)) -p3 = Plot(scatter(;y=cumsum(randn(12)), name="Random Walk")) -p4 = Plot([scatter(;x=1:4, y=[0, 2, 3, 5], fill="tozeroy"), +p1 = plot(scatter(;y=randn(3))) +p2 = plot(histogram(;x=randn(50), nbinsx=4)) +p3 = plot(scatter(;y=cumsum(randn(12)), name="Random Walk")) +p4 = plot([scatter(;x=1:4, y=[0, 2, 3, 5], fill="tozeroy"), scatter(;x=1:4, y=[3, 5, 1, 7], fill="tonexty")]) ``` @@ -78,7 +80,7 @@ If we wanted to combine `p1` and `p2` as subplots side-by-side, we would do If instead we wanted two rows and one column we could ```@example subplots -[p3; p4] +[p2 p3; p4] ``` Finally, we can make a 2x2 grid of subplots: @@ -92,7 +94,7 @@ Finally, we can make a 2x2 grid of subplots: New in PlotlyBase version 0.6.5 (PlotlyJS version 0.16.4) -As of version 0.16.4, we can also create a non-rectangular grid of subplots using this syntax. +We can also create a non-rectangular grid of subplots using this syntax. For example: @@ -100,19 +102,19 @@ For example: [p1 p2 p3 p4; p2 p4; p1] ``` -### `make_subplots` +### The `make_subplots` function !!! note New in PlotlyBase version 0.6.4 (PlotlyJS version 0.16.3) -As of version 0.16.3, there is another option for creaing subplots: the `make_subplots` function +There is another option for creaing subplots: the `make_subplots` function. This function takes a number of keyword arguments and allows fine grained control over the layout and labels for subplots. Consider the example below: ```@example subplots -p = make_subplots( +sp = make_subplots( rows=5, cols=2, specs=[Spec() Spec(rowspan=2) Spec() missing @@ -121,18 +123,18 @@ p = make_subplots( Spec() Spec()] ) -add_trace!(p, scatter(x=[1, 2], y=[1, 2], name="(1,1)"), row=1, col=1) -add_trace!(p, scatter(x=[1, 2], y=[1, 2], name="(1,2)"), row=1, col=2) -add_trace!(p, scatter(x=[1, 2], y=[1, 2], name="(2,1)"), row=2, col=1) -add_trace!(p, scatter(x=[1, 2], y=[1, 2], name="(3,1)"), row=3, col=1) -add_trace!(p, scatter(x=[1, 2], y=[1, 2], name="(5,1)"), row=5, col=1) -add_trace!(p, scatter(x=[1, 2], y=[1, 2], name="(5,2)"), row=5, col=2) +add_trace!(sp, scatter(x=[1, 2], y=[1, 2], name="(1,1)"), row=1, col=1) +add_trace!(sp, scatter(x=[1, 2], y=[1, 2], name="(1,2)"), row=1, col=2) +add_trace!(sp, scatter(x=[1, 2], y=[1, 2], name="(2,1)"), row=2, col=1) +add_trace!(sp, scatter(x=[1, 2], y=[1, 2], name="(3,1)"), row=3, col=1) +add_trace!(sp, scatter(x=[1, 2], y=[1, 2], name="(5,1)"), row=5, col=1) +add_trace!(sp, scatter(x=[1, 2], y=[1, 2], name="(5,2)"), row=5, col=2) -relayout!(p, height=600, width=600, title_text="specs examples") -p.plot +relayout!(sp, height=600, width=600, title_text="specs examples") +plot(sp.plot) ``` -More examples are being worked on at this time (2021-07-14), but for now you can view the docs for [`make_subplots`](@ref) to get an idea of what else is possible. +You can view the docs for [`make_subplots`](@ref) to get a further idea of what else is possible. ## Saving figures @@ -167,9 +169,9 @@ The figure format could be specified with the `format` keyword, the default form **Display on the screen** -*PlotlyJS.jl* overloads the `Base.show` method to hook into Julia's rich display system: +PlotlyJS.jl overloads the `Base.show` method to hook into Julia's rich display system: ```julia -Base.show(io::IO, ::MIME, p::Union{PlotlyBase.Plot}) +Base.show(io::IO, ::MIME, p::Union{PlotlyBase.Plot, PlotlyJS.SyncPlot}) ``` Internally, this `Base.show` implementation calls `savefig(io, p)`, and the `MIME` argument allows to specify the output format. diff --git a/docs/src/syncplots.md b/docs/src/syncplots.md index 56f25fd7..72c3567b 100644 --- a/docs/src/syncplots.md +++ b/docs/src/syncplots.md @@ -10,7 +10,7 @@ We'll also discuss how to integrate with various front-ends. ## `Plot` -Recall that the definition of the `Plot` object is +The full definition of the `Plot` object is ```julia mutable struct Plot{TT<:AbstractVector{<:AbstractTrace},TL<:AbstractLayout,TF<:AbstractVector{<:PlotlyFrame}} @@ -22,7 +22,7 @@ mutable struct Plot{TT<:AbstractVector{<:AbstractTrace},TL<:AbstractLayout,TF<:A end ``` -Given one or more `AbstractTrace`s and optionally a `Layout`, we construct a +Given one or more traces (with a subtypes of `AbstractTrace`) and optionally a `Layout`, we construct a `Plot` object with any of the following constructors ```julia @@ -42,15 +42,15 @@ Plot(data::AbstractTrace) Plot(data::AbstractTrace, layout::AbstractLayout) ``` -Notice that none of the recommended constructors have you pass the `divid` -field manually. This is an internal field used to allow the display and -unique identification of multiple plots in a single web page. +Notice that none of the recommended constructors require you to pass the `divid` +field manually (this is an internal field to enable the +unique identification and display of multiple plots in a single web page). ### [Convenience methods](@id constructors) There are also a number of convenience methods to the `Plot` function that will -attempt to construct the traces for you. They have the following signatures -that show a variety of arguments that can be used to create a plot: +attempt to construct the traces for you. The following signatures +show the variety of arguments that can be used to create a plot: ```@docs PlotlyBase.Plot @@ -58,24 +58,24 @@ PlotlyBase.Plot Here are some examples: -```@example -t = range(0, 3, 41); +```@example plot_methods +using PlotlyJS p0 = Plot([0, 1, 3], [10, 5, 2]) -plot(p1) +plot(p0) ``` -```@example +```@example plot_methods t = range(0, 3, 41); p1 = Plot(t, [2sin.(t) 3cos.(t) cos.(t).-sin.(t)], Layout(showlegend=true)) plot(p1) ``` -```@example +```@example plot_methods p2 = Plot(x -> (x - 0.6)^2, -2, 2, Layout(showlegend=false)) plot(p2) ``` -```@example +```@example plot_methods p3 = Plot([sin, cos], 0, 2*pi) plot(p3) ``` @@ -133,14 +133,16 @@ time of writing this includes [Jupyter notebooks](https://jupyter.org/), [Jupyterlab](https://github.com/jupyterlab/jupyterlab), [Mux.jl](https://github.com/JuliaWeb/Mux.jl) web apps, and Electron windows from [Blink.jl](https://github.com/JuliaGizmos/Blink.jl). -Please see the [WebIO.jl documentation](https://juliagizmos.github.io/WebIO.jl/latest/gettingstarted/#Getting-Started) +Please see the +[WebIO.jl documentation](https://juliagizmos.github.io/WebIO.jl/latest/gettingstarted) for additional information. When using PlotlyJS.jl at the Julia REPL a plot will automatically be displayed in two possible ways. -A `Plot()` call will try to launch the application that handles `.html` -files on the user's computer, typically their default browser. +A `Plot()` call will create a temporary HTML file with the plot embedded inside. +PlotlyJS.jl code will then try to launch the application that handles `.html` +files on the user's computer, typically their default browser. A `plot()` call will launch a new Electron window. This is a dedicated browser window we have full control over. To see a plot `p`, just type `p` by @@ -166,7 +168,7 @@ display(p) # usually optional WebIO.on(p["hover"]) do data if haskey(data, "points") pt = first(data["points"]) - println("\nYou hovered over the point x=", pt["x"], ", y=", pt["y"])) + println("\nYou hovered over the point x=", pt["x"], ", y=", pt["y"]) end end ``` From 4f15d903f180b9879d70ab2ac58cefc17e3a959e Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 31 Mar 2026 17:17:43 +1100 Subject: [PATCH 6/9] Linking fixes --- docs/src/building_traces_layouts.md | 2 +- docs/src/index.md | 2 +- docs/src/manipulating_plots.md | 2 +- docs/src/syncplots.md | 8 +++----- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/docs/src/building_traces_layouts.md b/docs/src/building_traces_layouts.md index 87657568..348ce4f9 100644 --- a/docs/src/building_traces_layouts.md +++ b/docs/src/building_traces_layouts.md @@ -330,7 +330,7 @@ the [Violin](@ref) example page more details. A _facet_ is another name for a plot displaying a subset of a larger dataset. When plotting a `DataFrame` (let's call it `df`), the keyword arguments -`facet_row` and `facet_col` allow you to create a _matrix_ of [subplots](@ref Subplots). +`facet_row` and `facet_col` allow you to create a _matrix_ of [subplots](@ref subplot_intro). The rows of this matrix correspond to the array `unique(df[:facet_row])`, where `:facet_row` is a placeholder for the actual symbol passed as the `facet_row` argument. diff --git a/docs/src/index.md b/docs/src/index.md index e9cd6f8e..ee142520 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -47,7 +47,7 @@ to download the latest updates to the plotly.js JavaScript library. PlotlyJS.jl comes with built-in support for saving figures to files via the integration between PlotlyBase.jl (a dependency of PlotlyJS.jl) and Plotly's -kaleido tool (via the PlotlyKaleido.jl package). +kaleido tool (via the [PlotlyKaleido.jl](https://github.com/JuliaPlots/PlotlyKaleido.jl) package). See [exporting figures](https://juliaplots.org/PlotlyJS.jl/stable/manipulating_plots/#Saving-figures) for more information. diff --git a/docs/src/manipulating_plots.md b/docs/src/manipulating_plots.md index 26992e8e..b647f2ee 100644 --- a/docs/src/manipulating_plots.md +++ b/docs/src/manipulating_plots.md @@ -48,7 +48,7 @@ consult the docstrings or [API Documentation](@ref). `prependtraces!` to set attributes that are arrays. The semantics are a bit subtle. Check the docstring for details and examples -## Subplots +## [Subplots](@id subplot_intro) A common task is to construct subpots, or plots with more than one set of axes. This is possible using the declarative plotly.js syntax, but can be tedious at diff --git a/docs/src/syncplots.md b/docs/src/syncplots.md index 72c3567b..719eb99f 100644 --- a/docs/src/syncplots.md +++ b/docs/src/syncplots.md @@ -134,17 +134,15 @@ time of writing this includes [Jupyter notebooks](https://jupyter.org/), [Mux.jl](https://github.com/JuliaWeb/Mux.jl) web apps, and Electron windows from [Blink.jl](https://github.com/JuliaGizmos/Blink.jl). Please see the -[WebIO.jl documentation](https://juliagizmos.github.io/WebIO.jl/latest/gettingstarted) +[WebIO.jl documentation](https://juliagizmos.github.io/WebIO.jl/latest/gettingstarted/) for additional information. When using PlotlyJS.jl at the Julia REPL a plot will automatically be displayed in two possible ways. - -A `Plot()` call will create a temporary HTML file with the plot embedded inside. +1. A `Plot()` call will create a temporary HTML file with the plot embedded inside. PlotlyJS.jl code will then try to launch the application that handles `.html` files on the user's computer, typically their default browser. - -A `plot()` call will launch a new Electron window. This is a dedicated +2. A `plot()` call will launch a new Electron window. This is a dedicated browser window we have full control over. To see a plot `p`, just type `p` by itself at the REPL and execute the line. Alternatively you can call `display(p)`. From 6f5ca924c958a86dff9b2a00444573a9c04eecf0 Mon Sep 17 00:00:00 2001 From: James Foster <38274066+jd-foster@users.noreply.github.com> Date: Thu, 9 Apr 2026 14:06:23 +1000 Subject: [PATCH 7/9] Typo --- docs/src/manipulating_plots.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/manipulating_plots.md b/docs/src/manipulating_plots.md index b647f2ee..effdea40 100644 --- a/docs/src/manipulating_plots.md +++ b/docs/src/manipulating_plots.md @@ -17,7 +17,7 @@ them here, but consult the package [API Documentation](@ref) for more exhaustive All exported functions from the [plotly.js API](https://plotly.com/javascript/plotlyjs-function-reference/) have been exposed to Julia and operate on both `Plot` and `SyncPlot` instances. -Each of these functions has semantics that match the semantics of plotly.js library. +Each of these functions has semantics that match the semantics of the plotly.js library. In PlotlyJS.jl these functions are spelled: From 27d8ea65556b9fe6577ff54169fc99aece3afbbb Mon Sep 17 00:00:00 2001 From: James Foster <38274066+jd-foster@users.noreply.github.com> Date: Thu, 9 Apr 2026 14:06:48 +1000 Subject: [PATCH 8/9] Remove word --- docs/src/manipulating_plots.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/manipulating_plots.md b/docs/src/manipulating_plots.md index effdea40..0313dafe 100644 --- a/docs/src/manipulating_plots.md +++ b/docs/src/manipulating_plots.md @@ -55,7 +55,7 @@ This is possible using the declarative plotly.js syntax, but can be tedious at best. PlotlyJS.jl provides a convenient syntax for constructing what we will -call regular grids of subplots. By regular we mean a square grid of plots like a matrix. +call regular grids of subplots. By regular we mean a grid of plots like a matrix. To do this we adapt the `vcat`, `hcat`, and `hvcat` functions from `Base` and leverage the array construction syntax to build up our subplots. From 6ba06dd59270402ec345894d00e9a29b4deb6321 Mon Sep 17 00:00:00 2001 From: James Foster Date: Thu, 9 Apr 2026 14:11:11 +1000 Subject: [PATCH 9/9] Typo --- docs/src/manipulating_plots.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/manipulating_plots.md b/docs/src/manipulating_plots.md index 0313dafe..08d7737d 100644 --- a/docs/src/manipulating_plots.md +++ b/docs/src/manipulating_plots.md @@ -50,7 +50,7 @@ consult the docstrings or [API Documentation](@ref). ## [Subplots](@id subplot_intro) -A common task is to construct subpots, or plots with more than one set of axes. +A common task is to construct subplots, or plots with more than one set of axes. This is possible using the declarative plotly.js syntax, but can be tedious at best.