Scatter Plots

SomeGraphs.Scatters.points_graph — Function
function points_graph(;
    [figure_title::Maybe{AbstractString} = nothing,
    x::VectorValuesData = VectorValuesData(),
    y::VectorValuesData = VectorValuesData(),
    points::PointsData = PointsData(),
    borders::BordersData = BordersData(),
    edges::EdgesData = EdgesData(),
    vertical_bands::BandsData = BandsData(),
    horizontal_bands::BandsData = BandsData(),
    diagonal_bands::BandsData = BandsData(),
    selection::SelectionData = SelectionData(),
    configuration::PointsGraphConfiguration = PointsGraphConfiguration()]
)::PointsGraph

Create a PointsGraph by initializing only the PointsGraphData fields (with an optional PointsGraphConfiguration ).

SomeGraphs.Scatters.PointsGraphData — Type
@kwdef mutable struct PointsGraphData <: AbstractGraphData
    figure_title::Maybe{AbstractString} = nothing
    x::VectorValuesData = VectorValuesData()
    y::VectorValuesData = VectorValuesData()
    points::PointsData = PointsData()
    borders::BordersData = BordersData()
    edges::EdgesData = EdgesData()
    vertical_bands::BandsData = BandsData()
    horizontal_bands::BandsData = BandsData()
    diagonal_bands::BandsData = BandsData()
    selection::SelectionData = SelectionData()
end

The data for a scatter graph of points.

The x and y values are required, numeric, and of the same size (the number of points); their titles are the axis titles. If specified, the points and borders colors and sizes values must also be of the same size, as must the hovers and masks. Colors can be explicit color names if no palette is specified in the configuration; otherwise, they are either numeric values or category names depending on the type of palette specified. Sizes are the diameter in pixels (1/96th of an inch); border sizes are added to the point sizes. The colors titles are used for the legends, if the legend of the relevant colors configuration is shown (you can't show it if the colors data contains explicit color names). Similarly, the sizes titles are used for the legends of sizes, if the legend of the relevant sizes configuration is shown.

The edges draw straight lines between pairs of points; see EdgesData .

The selection marks an area of the graph and the points inside it; see SelectionData .

The masks of the points, borders and edges allow disabling an arbitrary subset of them. This is often more convenient than excluding the data from the arrays. This is also useful for defining points which are only used to draw edges between them and aren't drawn as actual points. The properties of excluded entities, other than their coordinates, are ignored (e.g., the colors of masked points need not be valid color names). Numeric values are the exception: they must be finite whether the entity is drawn or not.

If the points and/or edges order is specified, we reorder the points and/or edges accordingly. This allows controlling which points and/or edges will appear on top of the others. Due to Plotly limitations, when using categorical colors, all the points (or edges) of one category must all be either above or below all the points of each other category. We therefore compute an overall priority for each category as the mean reordered index of all the points (or edges) of that category, and reorder the categories based on that.

SomeGraphs.Scatters.PointsData — Type
@kwdef mutable struct PointsData
    colors::VectorValuesData = VectorValuesData()
    sizes::VectorValuesData = VectorValuesData()
    entities::VectorEntitiesData = VectorEntitiesData()
end

The per-point data of a PointsGraphData , other than the coordinates: the colors and sizes values, and the names, hovers, mask and order of the points ( entities ). The order is the order the points are drawn in. It mirrors the points of the PointsGraphConfiguration .

In the rendered figure, the points may be split between several traces (e.g., one per category of colors). Each trace holds the (1-based) index of the entity of each of its points in its customdata . This allows mapping a selection in an interactive figure back to the entities.

SomeGraphs.Scatters.BordersData — Type
@kwdef mutable struct BordersData
    colors::VectorValuesData = VectorValuesData()
    sizes::VectorValuesData = VectorValuesData()
    mask::Maybe{Union{AbstractVector{Bool}, BitVector}} = nothing
end

The per-point data of the borders of a PointsGraphData : the colors and sizes values, and the mask of the borders. Borders share the hovers and order of the points. It mirrors the borders of the PointsGraphConfiguration .

SomeGraphs.Scatters.EdgesData — Type
@kwdef mutable struct EdgesData
    points::Maybe{AbstractVector{<:Tuple{Integer, Integer}}} = nothing
    colors::VectorValuesData = VectorValuesData()
    sizes::VectorValuesData = VectorValuesData()
    styles::Maybe{AbstractVector{LineStyle}} = nothing
    entities::VectorEntitiesData = VectorEntitiesData()
end

The edges of a PointsGraphData : straight lines between pairs of points (given by their indices). The colors and sizes (widths) override the edges , and the styles override the edges_style , of the PointsGraphConfiguration per edge. The entities hold the names, hovers, mask and order of the edges; the order is the order the edges are drawn in.

Note

Continuous colors for edges are not implemented due to the difficulty of getting Plotly to render them, and given we didn't find (m)any use cases for them.

SomeGraphs.Scatters.SelectionData — Type
@kwdef mutable struct SelectionData
    box::Maybe{Tuple{Real, Real, Real, Real}} = nothing
    polygon::Maybe{AbstractVector{<:Tuple{Real, Real}}} = nothing
end

The selection of a PointsGraphData : an area of the graph. The area is either a box (the minimal X, maximal X, minimal Y and maximal Y), or a polygon (the X and Y of each of its vertices), but not both. The coordinates are in the same units as the x and y data, like the offsets of BandsData .

The area is rendered as a Plotly selection, so Plotly draws its outline and highlights the points inside it. A polygon's edges are straight lines in the drawn graph, which they wouldn't be in the original units if an axis is in log scale.

Selecting points in an interactive figure does not change this field; the new selection is available through the interactive figure's own API (e.g., Plotly's FigureWidget.on_selection ).

SomeGraphs.Scatters.PointsGraphConfiguration — Type
@kwdef mutable struct PointsGraphConfiguration <: AbstractGraphConfiguration
    figure::FigureConfiguration = FigureConfiguration()
    x_axis::AxisConfiguration = AxisConfiguration(; expand_fraction = 0.01)
    y_axis::AxisConfiguration = AxisConfiguration(; expand_fraction = 0.01)
    points::ScattersConfiguration = ScattersConfiguration()
    borders::ScattersConfiguration = ScattersConfiguration(; sizes = SizesConfiguration(; smallest = 2, span = 8))
    edges::ScattersConfiguration = ScattersConfiguration(; sizes = SizesConfiguration(; smallest = 2, span = 8))
    edges_style::LineStyle = SolidLine
    edges_over_points::Bool = true
    vertical_bands::BandsConfiguration = BandsConfiguration()
    horizontal_bands::BandsConfiguration = BandsConfiguration()
    diagonal_bands::BandsConfiguration = BandsConfiguration()
end

Configure a graph for showing a scatter of points and/or edges.

The sizes of the borders and of the edges are 2 to 10 pixels by default, which is the most the legend of their sizes can draw.

If edges_over_points is set, the edges will be plotted above the points; otherwise, the points will be plotted above the edges. Edges are plotted using the edges_style unless the styles are specified in the data.

The borders is used if the PointsGraphData contains the borders colors, sizes and/or mask, or if the borders specifies a fixed color or size. This allows displaying some additional data per point.

Using the vertical_bands , horizontal_bands and/or diagonal_bands you can partition the graph into regions. The diagonal_bands can only be used if both axes are linear or both axes are in (the same) log scale, and both axes have the same percent . They are parallel to the X = Y line. For linear axes, the offset is additive, (Y = X + offset). For log scale axes, the offset is multiplicative (Y = X * offset), and the offset must be positive. This is a rare case where we must break orthogonality between flags, as switching between linear and log scales must be accompanied by patching the diagonal band offsets to match.

Note

There is no legend here. Instead you probably want to show the legend of the colors and/or sizes of the points , borders and/or edges . There's no way to create a legend for edge styles.

Note

Continuous colors for edges are not implemented due to the difficulty of getting Plotly to render them, and given we didn't find (m)any use cases for them.

SomeGraphs.Scatters.ScattersConfiguration — Type
@kwdef mutable struct ScattersConfiguration <: Validated
    colors::ColorsConfiguration = ColorsConfiguration()
    sizes::SizesConfiguration = SizesConfiguration()
end

Configure points (or borders, which are just larger points drawn under the actual points) or edges in a scatter graph. Point sizes are the diameter of the points. Border sizes are added to the point sizes. Edge sizes are the width of the lines.

Examples:

Default (serves as a baseline to compare with when modifying options):

using SomeGraphs
graph = points_graph(; x = VectorValuesData(collect(0:10) .* 10), y = VectorValuesData(collect(0:10) .^ 2))
using PlotlyDocumenter
to_documenter(graph.fig)

Flip axes (non-mutating):

using SomeGraphs
graph = points_graph(; x = VectorValuesData(collect(0:10) .* 10), y = VectorValuesData(collect(0:10) .^ 2))
flipped = flip_axes(graph)
using PlotlyDocumenter
to_documenter(flipped.fig)

Flip axes (in-place):

using SomeGraphs
graph = points_graph(; x = VectorValuesData(collect(0:10) .* 10), y = VectorValuesData(collect(0:10) .^ 2))
flip_axes!(graph)
using PlotlyDocumenter
to_documenter(graph.fig)

Borders:

using SomeGraphs
graph = points_graph(; x = VectorValuesData(collect(0:10) .* 10), y = VectorValuesData(collect(0:10) .^ 2))
graph.configuration.borders.colors.fixed = "black"
graph.configuration.borders.sizes.fixed = 1
using PlotlyDocumenter
to_documenter(graph.fig)

Edges:

using SomeGraphs
graph = points_graph(;
    x = VectorValuesData(collect(0:10) .* 10),
    y = VectorValuesData(collect(0:10) .^ 2),
    edges = EdgesData(; points = [(1, 8), (2, 9), (3, 10), (4, 11)]),
)
using PlotlyDocumenter
to_documenter(graph.fig)

Selection (box):

using SomeGraphs
graph = points_graph(;
    x = VectorValuesData(collect(0:10) .* 10),
    y = VectorValuesData(collect(0:10) .^ 2),
    selection = SelectionData(; box = (25, 75, 5, 50)),
)
using PlotlyDocumenter
to_documenter(graph.fig)

Selection (polygon):

using SomeGraphs
graph = points_graph(;
    x = VectorValuesData(collect(0:10) .* 10),
    y = VectorValuesData(collect(0:10) .^ 2),
    selection = SelectionData(; polygon = [(10, 0), (90, 40), (70, 90), (0, 30)]),
)
using PlotlyDocumenter
to_documenter(graph.fig)

Diagonal bands (linear scales):

using SomeGraphs
graph = points_graph(; x = VectorValuesData(collect(0:10) .* 10), y = VectorValuesData(collect(0:10) .^ 2))
graph.configuration.diagonal_bands.low.offset = -25
graph.configuration.diagonal_bands.middle.offset = 0
graph.configuration.diagonal_bands.high.offset = +25
using PlotlyDocumenter
to_documenter(graph.fig)

Diagonal bands (log scales):

using SomeGraphs
graph = points_graph(; x = VectorValuesData(collect(0:10) .* 10), y = VectorValuesData(collect(0:10) .^ 2))
graph.configuration.x_axis.scale.log_base = Log10Base
graph.configuration.y_axis.scale.log_base = Log10Base
graph.configuration.x_axis.scale.log_regularization = 1
graph.configuration.y_axis.scale.log_regularization = 1
graph.configuration.diagonal_bands.low.offset = 1 / 4
graph.configuration.diagonal_bands.middle.offset = 1
graph.configuration.diagonal_bands.high.offset = 4
using PlotlyDocumenter
to_documenter(graph.fig)

SomeGraphs.Scatters.points_density — Function
points_density(
    points_xs::AbstractVector{<:Real},
    points_ys::AbstractVector{<:Real},
)::AbstractVector{<:AbstractFloat}

Given a set of point coordinates, compute for each one the density of its environment. This can be used to color the points by density.

Examples:

using SomeGraphs
graph = points_graph()
graph.data.x.vector = [
    0.2698393176826803,
    0.21199888259395777,
    -1.1403772919081927,
    0.015375662421357001,
    -1.067372097104871,
    -0.05131680407322392,
    1.1476690271171557,
    0.2619998741581797,
    -0.3294624837610639,
    0.3990906575326256,
    0.016185972979333094,
    -0.6295842065710322,
    1.74273570356108,
    -1.612316716623975,
    -1.2696818434826393,
    -2.3942962323946806,
    -0.0683194741744384,
    -0.6991502371264332,
    1.3005476302710504,
    -0.3156364801379863,
]
graph.data.y.vector = [
    -0.1764741545510277,
    0.5007984744043152,
    -1.0092288051861404,
    0.28862095432807144,
    0.3216029374844889,
    1.1177946117474804,
    0.11865114901055787,
    -2.173777902643006,
    -0.5131646448399668,
    -0.4180196978042471,
    -1.7758801658517032,
    0.5019767811414706,
    0.6519383169746722,
    1.306115558967419,
    -0.6077449865370641,
    0.6968047575410379,
    1.7053341710917538,
    -0.6584463274588279,
    0.9034430051864035,
    -0.631083973233279,
]
graph.data.points.colors.vector = points_density(graph.data.x.vector, graph.data.y.vector)
graph.data.points.entities.order = sortperm(graph.data.points.colors.vector)
graph.configuration.points.colors.palette = "Viridis"
graph.configuration.points.sizes.fixed = 16
graph.configuration.figure.width = 200
graph.configuration.figure.height = 200
graph.configuration.x_axis.scale.minimum = -3
graph.configuration.y_axis.scale.minimum = -3
graph.configuration.x_axis.scale.maximum = 3
graph.configuration.y_axis.scale.maximum = 3
using PlotlyDocumenter
to_documenter(graph.fig)

SomeGraphs.Scatters.line_graph — Function
function line_graph(;
    [figure_title::Maybe{AbstractString} = nothing,
    x::VectorValuesData = VectorValuesData(),
    y::VectorValuesData = VectorValuesData(),
    points::VectorEntitiesData = VectorEntitiesData(),
    vertical_bands::BandsData = BandsData(),
    horizontal_bands::BandsData = BandsData(),
    diagonal_bands::BandsData = BandsData(),
    configuration::LineGraphConfiguration = LineGraphConfiguration()]
)::LineGraph

Create a LineGraph by initializing only the LineGraphData fields (with an optional LineGraphConfiguration ).

SomeGraphs.Scatters.LineGraphData — Type
@kwdef mutable struct LineGraphData <: AbstractGraphData
    figure_title::Maybe{AbstractString} = nothing
    x::VectorValuesData = VectorValuesData()
    y::VectorValuesData = VectorValuesData()
    points::VectorEntitiesData = VectorEntitiesData()
    vertical_bands::BandsData = BandsData()
    horizontal_bands::BandsData = BandsData()
    diagonal_bands::BandsData = BandsData()
end

The data for a single line graph.

The x and y values are required, numeric, and of the same size (the number of points); their titles are the axis titles. The points hold the hovers and mask of the points, which must be of the same size if specified. Masked points are left out of the line.

SomeGraphs.Scatters.LineGraphConfiguration — Type
@kwdef mutable struct LineGraphConfiguration <: AbstractGraphConfiguration
    figure::FigureConfiguration = FigureConfiguration()
    x_axis::AxisConfiguration = AxisConfiguration(; expand_fraction = 0.01)
    y_axis::AxisConfiguration = AxisConfiguration(; expand_fraction = 0.01)
    line::LineConfiguration = LineConfiguration()
    show_points::Bool = false
    points_size::Maybe{Real} = nothing
    points_color::Maybe{AbstractString} = nothing
    vertical_bands::BandsConfiguration = BandsConfiguration()
    horizontal_bands::BandsConfiguration = BandsConfiguration()
    diagonal_bands::BandsConfiguration = BandsConfiguration()
end

Configure a graph for showing a single line.

If show_points is set, each point is drawn, using the points_size and/or points_color if specified. The bands are similar to PointsGraphConfiguration .

Examples:

Default (serves as a baseline to compare with when modifying options):

using SomeGraphs
graph = line_graph(; x = VectorValuesData(collect(0:10) .* 10), y = VectorValuesData(collect(0:10) .^ 2))
using PlotlyDocumenter
to_documenter(graph.fig)

With points:

using SomeGraphs
graph = line_graph(; x = VectorValuesData(collect(0:10) .* 10), y = VectorValuesData(collect(0:10) .^ 2))
graph.configuration.show_points = true
using PlotlyDocumenter
to_documenter(graph.fig)

Filled:

using SomeGraphs
graph = line_graph(; x = VectorValuesData(collect(0:10) .* 10), y = VectorValuesData(collect(0:10) .^ 2))
graph.configuration.line.is_filled = true
using PlotlyDocumenter
to_documenter(graph.fig)

SomeGraphs.Scatters.lines_graph — Function
function lines_graph(;
    [figure_title::Maybe{AbstractString} = nothing,
    lines::AbstractVector{LineData} = LineData[],
    order::Maybe{AbstractVector{<:Integer}} = nothing,
    vertical_bands::BandsData = BandsData(),
    horizontal_bands::BandsData = BandsData(),
    diagonal_bands::BandsData = BandsData(),
    configuration::LinesGraphConfiguration = LinesGraphConfiguration()]
)::LinesGraph

Create a LinesGraph by initializing only the LinesGraphData fields (with an optional LinesGraphConfiguration ).

SomeGraphs.Scatters.LinesGraphData — Type
@kwdef mutable struct LinesGraphData <: AbstractGraphData
    figure_title::Maybe{AbstractString} = nothing
    lines::AbstractVector{LineData} = LineData[]
    order::Maybe{AbstractVector{<:Integer}} = nothing
    vertical_bands::BandsData = BandsData()
    horizontal_bands::BandsData = BandsData()
    diagonal_bands::BandsData = BandsData()
end

The data for a multi-line graph, a LineData per line.

The axes titles are the titles of the x (and y ) values of the lines: all the lines that give one must give the same. The name of every shown line is required if the legend of the LinesGraphConfiguration is shown.

If order is specified, we draw the lines in that order, so later lines appear on top of (or, when stacking, above) earlier ones.

SomeGraphs.Scatters.LineData — Type
@kwdef mutable struct LineData <: AbstractPartData
    x::VectorValuesData = VectorValuesData()
    y::VectorValuesData = VectorValuesData()
    points::VectorEntitiesData = VectorEntitiesData()
    name::Maybe{AbstractString} = nothing
    hover::Maybe{AbstractString} = nothing
    is_shown::Bool = true
    color::Maybe{AbstractString} = nothing
    width::Maybe{Real} = nothing
    style::Maybe{LineStyle} = nothing
    points_size::Maybe{Real} = nothing
    points_color::Maybe{AbstractString} = nothing
end

One line of a LinesGraphData . The x and y values are required, numeric, and of the same size (the number of points of this line). The points hold the hovers and mask of these points; masked points are left out of the line. The name is shown in the legend. The hover (if any) is prefixed to the hover of each point. A line which is not is_shown is left out of the graph. The color , width , style , points_size and points_color override the LinesGraphConfiguration for this line; a nothing means the configuration default is used.

SomeGraphs.Scatters.LinesGraphConfiguration — Type
@kwdef mutable struct LinesGraphConfiguration <: AbstractGraphConfiguration
    figure::FigureConfiguration = FigureConfiguration()
    x_axis::AxisConfiguration = AxisConfiguration(; expand_fraction = 0.01)
    y_axis::AxisConfiguration = AxisConfiguration(; expand_fraction = 0.01)
    line::LineConfiguration = LineConfiguration()
    show_points::Bool = false
    points_size::Maybe{Real} = nothing
    points_color::Maybe{AbstractString} = nothing
    vertical_bands::BandsConfiguration = BandsConfiguration()
    horizontal_bands::BandsConfiguration = BandsConfiguration()
    diagonal_bands::BandsConfiguration = BandsConfiguration()
    legend::LegendConfiguration = LegendConfiguration()
    stacking::Maybe{Stacking} = nothing
end

Configure a graph for showing multiple lines.

This is similar to LineGraphConfiguration , with the addition of the legend . If it is shown, then the data must specify the name of each shown line.

If stacking is specified, we stack the values on top of each other. Stacking can't be combined with a log y_axis . Stacking inserts points into the lines, so the points of the lines can't have names or hovers. With StackFractions , the (scaled) values must not be negative.

Examples:

Default (serves as a baseline to compare with when modifying options):

using SomeGraphs
graph = lines_graph(;
    lines = [
        LineData(; x = VectorValuesData(collect(0:10) .* 10), y = VectorValuesData(collect(0:10) .^ 2)),
        LineData(; x = VectorValuesData([0, 90]), y = VectorValuesData([50, 0])),
    ],
)
using PlotlyDocumenter
to_documenter(graph.fig)

Filled:

using SomeGraphs
graph = lines_graph(;
    lines = [
        LineData(; x = VectorValuesData(collect(0:10) .* 10), y = VectorValuesData(collect(0:10) .^ 2)),
        LineData(; x = VectorValuesData([0, 90]), y = VectorValuesData([50, 0])),
    ],
)
graph.configuration.line.is_filled = true
using PlotlyDocumenter
to_documenter(graph.fig)

Stacked:

using SomeGraphs
graph = lines_graph(;
    lines = [
        LineData(; x = VectorValuesData(collect(0:10) .* 10), y = VectorValuesData(collect(0:10) .^ 2)),
        LineData(; x = VectorValuesData([0, 90]), y = VectorValuesData([50, 0])),
    ],
)
graph.configuration.line.is_filled = true
graph.configuration.stacking = StackValues
using PlotlyDocumenter
to_documenter(graph.fig)

Fractions:

using SomeGraphs
graph = lines_graph(;
    lines = [
        LineData(; x = VectorValuesData(collect(0:10) .* 10), y = VectorValuesData(collect(0:10) .^ 2)),
        LineData(; x = VectorValuesData([0, 90]), y = VectorValuesData([50, 0])),
    ],
)
graph.configuration.line.is_filled = true
graph.configuration.stacking = StackFractions
using PlotlyDocumenter
to_documenter(graph.fig)

Percents:

using SomeGraphs
graph = lines_graph(;
    lines = [
        LineData(; x = VectorValuesData(collect(0:10) .* 10), y = VectorValuesData(collect(0:10) .^ 2)),
        LineData(; x = VectorValuesData([0, 90]), y = VectorValuesData([50, 0])),
    ],
)
graph.configuration.line.is_filled = true
graph.configuration.stacking = StackFractions
graph.configuration.y_axis.scale.percent = true
using PlotlyDocumenter
to_documenter(graph.fig)

Index