Plotting with SharpPlot#
The goal of this notebook is to show how SharpPlot can be used for the production of high quality graphs in Dyalog jupyter notebooks. It is shown, as an example, how to create a nice looking graph with a custom format. However, the notebook is not intended to be a comprehensive tutorial on the usage of SP. For further details, refer to the official documentation (take into account that this documentation is written for the C# version of SP; check the Rosetta stone to see how to translate these commands into Dyalog APL).
)clear ⍝ begin on a clean workspace
⎕IO←0 ⍝ for convenience
clear ws
Sample data#
Let’s generate some sample data to have something to work with. Initially, we use the user command ]plot
to display the data.
(y1 y2) ← 1 2 ○⊂ x ← 0.1×⍳101 ⍝ sin and cos
]plot (y1 y2) x
The ]plot
command only allows very basic functionality (displaying functions with a common x-axis using different plotting methods), with no configuration options. For instance, if we have different “sampling rates”, we won’t be able to use ]plot
to create a single plot.
y1 ← 1 ○ x1 ← 0.1×⍳101 ⍝ sin
y2 ← 2 ○ x2 ← (0.02×○3)×⍳51 ⍝ cos
data ← (sin cos) ← (y1 x1) (y2 x2) ⍝ data to plot
In order to create more advanced graphs, we will use SP. First, we will do it directly in the workspace, and at the end we will define our own Plot
function.
Plotting#
Initialization#
The sharpplot
workspace provides a InitCauseway
function that will initialize everything required to work with SP from Dyalog APL (as well as some additional functionality which won’t be discussed here). After running it, we will have a Causeway
namespace. Then, we create a new instance of the Causeway.SharpPlot
class, that we will use to interact with SP.
⍝ Init
'InitCauseway'⎕CY'sharpplot'
InitCauseway ⍬
sp←⎕NEW Causeway.SharpPlot
Formatting#
Several sp
fields and methods can be used to adjust the format of our plot. We will define the format of gridlines, labels, captions, and lines. A large number of formatting options are available. The SP User Manual contains more information on format and styles.
⍝ Format
sp.XAxisStyle←Causeway.XAxisStyles.GridLines
sp.YAxisStyle←Causeway.YAxisStyles.(GridLines+AtEndCaption)
sp.SetKeyFont 9.5 System.Drawing.Color.Black
sp.SetXCaptionFont 9.5 System.Drawing.Color.Black
sp.SetYCaptionFont 9.5 System.Drawing.Color.Black
sp.SetXLabelFont 7.5 System.Drawing.Color.Black
sp.SetYLabelFont 7.5 System.Drawing.Color.Black
sp.XLabelFormat←'0.00'
sp.YLabelFormat←'0.00'
sp.SetPenWidths 2
sp.SetColors ⊂'black'
Ranges and labels#
Next, we set up the key and axis labels, as well as the limits of the plot. In order to define these limits, we need to find the maximum and minimum values in all the curves:
⍝ Labels
sp.XCaption←,'x'
sp.YCaption←,'y',⎕UCS 10 ⍝ add newline to leave some space
sp.SetKeyText⊂'sin' 'cos'
⍝ Limits
(ya xa)←⌊⌿⌊/¨↑data
(yw xw)←⌈⌿⌈/¨↑data
(xa,'≤ x ≤',xw) (ya,'≤ y ≤',yw)
sp.SetYRange ya yw
sp.SetXRange xa xw
┌──────────┬──────────┐ │0 ≤ x ≤ 10│¯1 ≤ y ≤ 1│ └──────────┴──────────┘
Plot and display#
To plot, we use the sp.DrawLineGraph
function.
⍝ Plot
sp.DrawLineGraph¨data
The plot is already created, but we still need to display it. Alternatively, we could save it as an image or pdf file, for example. To render the plot inside the jupyter notebook, we first generate a SVG graph with sp.RenderSvg
. Then, the ]html
command sends the generated SVG to the browser.
⍝ Display
]html sp.RenderSvg Causeway.SvgMode.FixedAspect
Plotting ~~function~~ operator#
To finish, we are going to put everything together. We want to define a plotting function, but we will need more than two parameters, so we define a custom operator instead. There are many options that could be added to such a function or operator. The intention is not to provide a very complete and configurable implementation, but just to show how to define your own.
The Plot
operator is defined as a tradop. This method is preferred above a dfn or a tacit function because it matches better with the procedural style of the SP interface. More specifically, there are SP methods, such as sp.SetColors
, which do not return any value, so the resulting dfn or tacit function would be awkward.
Plot
takes two operands, which will be the labels of the x and y axis, a dataset as right argument and, optionally, a list of colors as left argument. The dataset consists of a list of curves, where each curve is composed of a name and yx data. We handle as a special case a single curve (¯4<≡data
) and apply “scalar extension” to the left argument ((≢data)⍴⊆colors
) so that the user can easily specify a common color for all curves. In order to make it possible to set an individual color for each curve, we plot them inside a :For
loop.
]dinput
svg←{colors}(xlabel Plot ylabel) data;InitCauseway;Causeway;System;sp;fc;fl;fs;fmt;names;xa;xw;ya;yw
⍝ eg: 'red' 'blue' ('xlabel'Plot'ylabel') ('series1' (y1 x1)) ('series2' (y2 x2))
⍝ Init
:If 0=⎕NC'Causeway'
'InitCauseway'⎕CY'sharpplot'
InitCauseway ⍬
:EndIf
sp←⎕NEW Causeway.SharpPlot
⍝ Format
sp.XAxisStyle←Causeway.XAxisStyles.GridLines
sp.YAxisStyle←Causeway.YAxisStyles.(GridLines+AtEndCaption)
(fc fl fs) ← System.Drawing.Color.Black 9.5 7.5 ⍝ font color, large size, small size
sp.SetXCaptionFont fl fc ⋄ sp.SetXLabelFont fs fc
sp.SetYCaptionFont fl fc ⋄ sp.SetYLabelFont fs fc
sp.SetKeyFont fl fc
fmt←'0.00' ⋄ sp.XLabelFormat←fmt ⋄ sp.YLabelFormat←fmt
sp.SetPenWidths 2
⍝ Curves
:If 0=⎕NC'colors'
colors ← ⊂'black'
:EndIf
:If ¯4<≡data
(names data)←data
data←,⊂data
:Else
(names data)←↓⍉↑data ⍝ names and data
:EndIf
colors ← (≢data)⍴⊆colors ⍝ "scalar extension"
⍝ Labels
sp.XCaption←,xlabel
sp.YCaption←,ylabel,⎕UCS 10 ⍝ add newline to leave some space
sp.SetKeyText⊂names
⍝ Limits
(ya xa)←⌊⌿⌊/¨↑data
(yw xw)←⌈⌿⌈/¨↑data
sp.SetYRange ya yw
sp.SetXRange xa xw
⍝ Plot and display
:For i :In ⍳≢data
sp.SetColors i⌷colors
sp.DrawLineGraph i⊃data
:EndFor
svg←sp.RenderSvg Causeway.SvgMode.FixedAspect
The return of Plot
is the plot as SVG, so we use ]html
to display it.
⍝ eg
]html 'red' 'blue' ('x'Plot'y') ('sin' sin) ('cos' cos) ⍝ sin and cos, with colors
]html 'purple' ('x'Plot'y') 'log' ((⍟1↓x) x) ⍝ single curve
]html ('Time [s]'Plot'Distance [m]') ('a = 20' ((x×100+10×x) x)) ('a = 0' ((x×100) x)) ⍝ default color