Markers
Markers is a layer for scatter plots. It can be created with the add_markers method.
import numpy as np
from whitecanvas import new_canvas
canvas = new_canvas("matplotlib")
layer = canvas.add_markers([0, 1, 2, 3], [0, 1, 1, 0])
canvas.show()
Symbol and size of the markers can easily be configured with the symbol and size
arguments.
import numpy as np
from whitecanvas import new_canvas
canvas = new_canvas("matplotlib")
for i, symbol in enumerate(["o", "s", "x", "+"]):
for j, size in enumerate([5, 10, 15, 20]):
x = [i - 0.2, i - 0.2, i + 0.2, i + 0.2]
y = [j - 0.2, j + 0.2, j - 0.2, j + 0.2]
layer = canvas.add_markers(x, y, symbol=symbol, size=size)
canvas.show()
Note
If the symbol is edge-only, its color and visibility are automatically updated to ensure the markers are informative.
Marker Properties
Markers layer has two namespaces: face and edge. face has following properties:
color... color of the faces. Any color-like object is accepted.hatch... hatch pattern of the faces. Should be one of"","-","|,"+","/","\\","x"or".".
Note
hatch is not supported in some backends.
edge has following properties:
color... color of the lines. Any color-like object is accepted.width... width of the lines. Should be a non-negative number.style... style of the lines. Should be one of"-",":","-.","--".
Note
style is not supported in some backends.
Methods for adding these layers always configure the face properties with the
arguments. You can use the with_edge method of the output layer to set edge
properties. This separation is very helpful to prevent the confusion of the arguments,
especially the colors.
import numpy as np
from whitecanvas import new_canvas
canvas = new_canvas("matplotlib")
canvas.add_markers(np.sin(np.arange(10)), color="yellow").with_edge(color="black")
canvas.show()
All the properties can be set via properties of face and edge, or the update
method.
layer.face.color = "yellow"
layer.face.hatch = "x"
layer.edge.color = "black"
layer.edge.width = 2
layer.edge.style = "--"
# use `update`
layer.face.update(color="yellow", hatch="x")
layer.edge.update(color="black", width=2, style="--")
Multi-face and Multi-edge Markers
Markers supports multi-face and multi-edge. This means that you can create a layer
with multiple colors, widths, etc.
To do this, you have to call with_face_multi or with_edge_multi method.
Here's an example of Markers with multi-faces.
import numpy as np
from whitecanvas import new_canvas
canvas = new_canvas("matplotlib")
layer = (
canvas
.add_markers(np.arange(10), np.sin(np.arange(10)))
.with_face_multi(color=np.random.random((10, 3))) # random colors
)
canvas.show()
After calling with_face_multi, the layer face property will return arrays instead
of scalar values.
layer.face.color # (N, 4) array of RGBA colors
layer.face.hatch # (N,) array of hatchs
layer.face.alpha # (N,) array of alpha values
Note
IDE can detect whether a Markers layer is multi-face or not. Markers class
is a generic class with type variables for the face types. Since with_face_multi
is correctly typed, IDE will recognize the returned layer as a multi-face layer.
Similarly, you can use with_edge_multi to create multi-edge markers.
import numpy as np
from whitecanvas import new_canvas
canvas = new_canvas("matplotlib")
layer = (
canvas
.add_markers(np.arange(10), np.sin(np.arange(10)))
.with_edge_multi(width=np.abs(np.sin(np.arange(10))) * 2.5)
)
canvas.show()
Multi-size Markers
with_size_multi method can be used to create multi-size markers.
import numpy as np
from whitecanvas import new_canvas
canvas = new_canvas("matplotlib")
layer = (
canvas
.add_markers(np.arange(10), np.sin(np.arange(10)))
.with_size_multi(np.abs(np.sin(np.arange(10))) * 16)
)
canvas.show()
Methods for Better Interpretability
Markers is implemented with the following methods to make the plot more interpretable.
Color by density
Scatter plot is good at visualizing the outliers, but not at telling the distribution
when the density is high. In this case, color_by_density method is very useful. It
colors the markers by the density of the points using kernel density estimation.
import numpy as np
from whitecanvas import new_row
rng = np.random.default_rng(999)
x = rng.normal(size=1000)
y = rng.normal(size=1000)
grid = new_row(2, backend="matplotlib")
(
grid
.add_canvas(0)
.update_labels(title="no coloring")
.add_markers(x, y)
)
(
grid
.add_canvas(1)
.update_labels(title="with coloring")
.add_markers(x, y)
.color_by_density(cmap="viridis")
)
grid.show()