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(),
    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()
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 show_legend is set for the relevant colors configuration (you can't specify show_legend if the colors data contains explicit color names).

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

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()
    order::Maybe{AbstractVector{<:Integer}} = nothing
end

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

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()
    order::Maybe{AbstractVector{<:Integer}} = nothing
end

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

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.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()
    edges::ScattersConfiguration = ScattersConfiguration(sizes = SizesConfiguration(smallest = 2))
    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.

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 either the borders_colors and/or borders_sizes . 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. 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 show_legend here. Instead you probably want to set the show_legend of the points , borders and/or edges . There's no way to create a legend for sizes or 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.figure)

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.figure)

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.figure)

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.figure)

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.figure)

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.figure)

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.log_scale = Log10Scale
graph.configuration.y_axis.log_scale = Log10Scale
graph.configuration.x_axis.log_regularization = 1
graph.configuration.y_axis.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.figure)

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.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.minimum = -3
graph.configuration.y_axis.minimum = -3
graph.configuration.x_axis.maximum = 3
graph.configuration.y_axis.maximum = 3
using PlotlyDocumenter
to_documenter(graph.figure)

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.figure)

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.figure)

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.figure)

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 show_legend is specified in the LinesGraphConfiguration .

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()
    show_legend::Bool = false
end

Configure a graph for showing multiple lines.

This is similar to LineGraphConfiguration , with the addition of show_legend . If this is set, then the data must specify the title to use for each line.

If stacking is specified, we stack the values on top of each other.

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.figure)

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.figure)

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.figure)

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.figure)

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.percent = true
using PlotlyDocumenter
to_documenter(graph.figure)

Index