Heatmaps
SomeGraphs.Heatmaps
—
Module
Graphs for showing a 2D matrix.
SomeGraphs.Heatmaps.HeatmapGraph
—
Type
A graph showing a heatmap. See
HeatmapGraphData
and
HeatmapGraphConfiguration
.
SomeGraphs.Heatmaps.heatmap_graph
—
Function
function heatmap_graph(;
[figure_title::Maybe{AbstractString} = nothing,
entries::MatrixValuesData = MatrixValuesData(),
cells::MatrixEntitiesData = MatrixEntitiesData(),
rows::HeatmapAxisData = HeatmapAxisData(),
columns::HeatmapAxisData = HeatmapAxisData(),
configuration::HeatmapGraphConfiguration = HeatmapGraphConfiguration()]
)::HeatmapGraph
Create a
HeatmapGraph
by initializing only the
HeatmapGraphData
fields (with an optional
HeatmapGraphConfiguration
).
SomeGraphs.Heatmaps.HeatmapGraphData
—
Type
@kwdef mutable struct HeatmapGraphData <: AbstractGraphData
figure_title::Maybe{AbstractString} = nothing
entries::MatrixValuesData = MatrixValuesData()
cells::MatrixEntitiesData = MatrixEntitiesData()
rows::HeatmapAxisData = HeatmapAxisData()
columns::HeatmapAxisData = HeatmapAxisData()
end
The data for a graph showing a heatmap (matrix) of entries.
This is shown as a 2D image where each matrix entry is a small rectangle with some color. Due to Plotly limitation, colors must be continuous. The
entries
values are required; their title is the title of the colors scale. The
cells
hold the hovers of the entries. The hover for each rectangle is a combination of the hovers of the cell, of its row and of its column.
The
rows
and
columns
hold the data of each axis (see
HeatmapAxisData
).
Valid combinations of the fields controlling order and clustering are:
data
order
|
data
arrange_by
|
data
groups
|
config
reorder
|
config
dendogram_size
|
config
linkage
|
config
metric
|
result tree | result order | notes |
|---|---|---|---|---|---|---|---|---|---|
nothing
|
nothing
|
ignored |
nothing
|
nothing
|
nothing
|
nothing
|
Not computed | Original data order | Do not cluster, use the original data order (default) |
nothing
|
nothing
/
AbstractMatrix{<:Real}
|
ignored |
nothing
|
Any |
nothing
/ Any
|
nothing
/ Any
|
ehclust
of original order with
linkage
or
WardLinkage
|
Original data order | Cluster, preserving the original order |
nothing
|
nothing
|
ignored |
SameOrder
|
nothing
/ Any
|
nothing
|
nothing
|
Same as other axis | Same as other axis | Square matrices only |
nothing
|
nothing
/
AbstractMatrix{<:Real}
|
nothing
|
OptimalHclust
/
RCompatibleHclust
|
nothing
/ Any
|
nothing
/ Any
|
nothing
/ Any
|
hclust
with
linkage
or
WardLinkage
|
hclust
with
reorder
|
Cluster using
linkage
and branch
reorder
|
nothing
|
nothing
/
AbstractMatrix{<:Real}
|
Any |
OptimalHclust
/
RCompatibleHclust
|
nothing
/ Any
|
nothing
/ Any
|
nothing
/ Any
|
ehclust
with
groups
and
linkage
or
WardLinkage
|
hclust
with
groups
and
reorder
|
Cluster using
groups
,
linkage
and branch
reorder
|
nothing
|
nothing
/
AbstractMatrix{<:Real}
|
nothing
|
SlantedHclust
/
SlantedPreSquaredHclust
|
nothing
/ Any
|
nothing
/ Any
|
nothing
/ Any
|
hclust
with
linkage
or
WardLinkage
, then
reorder_hclust
by
slanted_orders
|
reorder_hclust
by
slanted_orders
|
Cluster, then slant preserving the tree |
nothing
|
nothing
/
AbstractMatrix{<:Real}
|
Any |
SlantedHclust
/
SlantedPreSquaredHclust
|
nothing
/ Any
|
nothing
/ Any
|
nothing
/ Any
|
hclust
with
groups
and
linkage
or
WardLinkage
, then
reorder_hclust
by
slanted_orders
|
reorder_hclust
by
slanted_orders
|
Cluster using
groups
, then slant preserving the tree
|
nothing
|
nothing
/
AbstractMatrix{<:Real}
|
ignored |
SlantedOrder
/
SlantedPreSquaredOrder
|
nothing
/ Any
|
nothing
/ Any
|
nothing
/ Any
|
ehclust
of
slanted_orders
with
linkage
or
WardLinkage
|
slanted_orders
|
Slant, then cluster preserving the slanted order |
Hclust
|
nothing
|
ignored |
nothing
|
nothing
/ Any
|
nothing
|
nothing
|
Hclust
tree
|
Hclust
order
|
Force a specific tree and order on the data |
Hclust
|
nothing
/
AbstractMatrix{<:Real}
|
ignored |
SlantedHclust
/
SlantedPreSquaredHclust
|
nothing
/ Any
|
nothing
|
nothing
|
reorder_hclust
by
slanted_orders
|
reorder_hclust
by
slanted_orders
|
Slant, preserving a given tree |
AbstractVector{<:Integer}
|
nothing
|
ignored |
nothing
|
nothing
|
nothing
|
nothing
|
Not computed |
order
permutation
|
Do not cluster, use the specified order |
AbstractVector{<:Integer}
|
nothing
|
ignored |
nothing
|
Any |
nothing
/ Any
|
nothing
/ Any
|
ehclust
of
order
with
linkage
or
WardLinkage
|
order
permutation
|
Cluster, preserving the specified order |
AbstractVector{<:Integer}
|
nothing
|
nothing
|
ReorderHclust
|
nothing
/ Any
|
nothing
/ Any
|
nothing
/ Any
|
hclust
with
linkage
or
WardLinkage
|
reorder_hclust
by data
order
|
Cluster, then reorder branches to be close to
order
|
AbstractVector{<:Integer}
|
nothing
|
Any |
ReorderHclust
|
nothing
/ Any
|
nothing
/ Any
|
nothing
/ Any
|
ehclust
with
groups
and
linkage
or
WardLinkage
|
reorder_hclust
by data
order
|
Cluster, then reorder branches to be close to
order
|
All other combinations are invalid. Note:
-
When calling
hclustand/orehclustand/orslanted_orders, then specifyingarrange_bywill use it instead of the displayed data matrix. -
When calling
hclustand/orehclust, then specifying ametricwill be used instead ofEuclideanto compute the distances matrix. -
Specifying
groupsonly impacts the tree and order when computing a new clustering without other order constraints. They can still be specified to denote gaps in the heatmap, even when they do not impact the tree and/or order.
SomeGraphs.Heatmaps.HeatmapAxisData
—
Type
@kwdef mutable struct HeatmapAxisData
names::VectorValuesData = VectorValuesData()
entities::VectorEntitiesData = VectorEntitiesData()
order::Maybe{Union{Hclust, AbstractVector{<:Integer}}} = nothing
groups::VectorValuesData = VectorValuesData()
subgroups::VectorValuesData = VectorValuesData()
arrange_by::Maybe{AbstractMatrix{<:Real}} = nothing
annotations::AbstractVector{AnnotationData} = AnnotationData[]
annotations_order::Maybe{AbstractVector{<:Integer}} = nothing
end
The data of one axis (the rows or the columns) of a
HeatmapGraphData
. The
names
are strings, one per entry, shown as the tick labels; their title is the axis title. The
entities
hold the hovers and mask of the entries. The
annotations
are shown to the side of the axis. If
annotations_order
is specified, they are shown in that order; it describes all the annotations, including the ones that are not
is_shown
.
By default, if reordering the entries, this is based on the
entries.matrix
of the graph. You can override this by specifying an
arrange_by
matrix. Only the reordered dimension needs to match the
entries.matrix
(the rows
arrange_by
must have the same number of rows, and the columns
arrange_by
the same number of columns); the other dimension holds whatever features you want to cluster by, and need not match. For efficiency the rows
arrange_by
matrix should be in row-major layout, but that's not critical.
Alternatively you can force the order of the entries by specifying the
order
permutation. You can also specify an
Hclust
object as the order. If you ask for a dendogram and did not specify such a clustering, one will be computed.
If
groups
values (numbers or strings, one per entry) are specified, then a gap can be added between entries of different groups. Groups can also be used to constrain the computed clustering. The
subgroups
are a second, finer level of grouping nested in the groups. Neither has a title.
Hidden entries (see the mask of
VectorEntitiesData
) are not drawn, but they are still part of the data: the clustering sees them, and the
order
(a permutation or a tree) always describes all the entries, hidden ones included. This way the order computed for one graph (see
heatmap_order
) can be given to another graph of the same data, whether or not the two hide the same entries. At least one entry must be shown.
SomeGraphs.Heatmaps.HeatmapGraphConfiguration
—
Type
@kwdef mutable struct HeatmapGraphConfiguration <: AbstractGraphConfiguration
figure::FigureConfiguration = FigureConfiguration()
entries::EntriesConfiguration = EntriesConfiguration()
rows::HeatmapAxisConfiguration = HeatmapAxisConfiguration()
columns::HeatmapAxisConfiguration = HeatmapAxisConfiguration()
origin::HeatmapOrigin = HeatmapBottomLeft
final_order::Maybe{HeatmapGraphOrder} = nothing
end
Configure a graph showing a heatmap.
This displays a matrix of values using a rectangle at each position. Due to Plotly's limitations, you still to manually tweak the graph size for best results; there's no way to directly control the width and height of the rectangles.
The
entries
configure the entries (see
EntriesConfiguration
); the
rows
and
columns
configure each axis (see
HeatmapAxisConfiguration
).
The
final_order
caches the computed order of the rows and the columns; access it through the graph's
order
(e.g., for generating other graphs in an identical order). It is computed once, whether the graph's figure is generated or its order is asked for first.
Nothing detects that the cache went stale. Call
reset_order!
if anything it was computed from is changed after it was computed - that is, the
reorder
,
linkage
and
metric
of the axes configuration, and the
entries.matrix
and the
order
,
arrange_by
,
groups
and
subgroups
of the axes data. The groups are easy to forget: they constrain the clustering, so saving the same graph twice, grouped differently each time, silently reuses the order of the first grouping unless the cache is reset in between.
SomeGraphs.Heatmaps.EntriesConfiguration
—
Type
@kwdef mutable struct EntriesConfiguration <: Validated
colors::ColorsConfiguration = ColorsConfiguration()
end
Configure the entries of a heatmap. The
colors
map the values of the entries to colors. Due to Plotly's limitations, only continuous color palettes are supported.
SomeGraphs.Heatmaps.HeatmapAxisConfiguration
—
Type
@kwdef mutable struct HeatmapAxisConfiguration <: Validated
title::Maybe{AbstractString} = nothing
annotations::AnnotationSize = AnnotationSize()
reorder::Maybe{HeatmapReorder} = nothing
linkage::Maybe{HeatmapLinkage} = nothing
metric::Maybe{PreMetric} = nothing
include_hidden::Bool = true
groups_gap::Maybe{Integer} = 1
subgroups_gap::Maybe{Integer} = nothing
dendogram_size::Maybe{Real} = nothing
dendogram_line::LineConfiguration = LineConfiguration()
end
Configure one axis (the rows or the columns) of a heatmap. The
title
is the title of the axis. The
annotations
are the sizes of the annotations shown to the side of the axis.
You can use
reorder
to reorder the entries of the axis. When specifying
linkage
, by default, the clustering uses the
Euclidean
distance metric. You can override this by specifying the
metric
.
By default, a computed clustering sees all the entries of the axis, hidden ones included, so hiding some entries does not move the rest. Set
include_hidden
to
false
to cluster the shown entries only. Either way the resulting order and tree (see
heatmap_order
) describe all the entries; when the hidden ones were left out of the clustering, they come last, joined to the root of the tree. This has no effect on an
Hclust
given in the data, which is used as is.
If groups are specified for the entries in the
HeatmapAxisData
, they can be used to constrain the clustering, and/or to create visible gaps in the heatmap (between entries of different groups). The
groups_gap
is the number of fake entries to added between the separated entries. That is, the default gap of 1 will add a blank gap of one entry between adjacent entries of different groups. A gap of
nothing
will not be shown.
If subgroups are also specified, they are a second, finer level of grouping nested in the groups; each group is contiguous, and within it each subgroup is contiguous. Their
subgroups_gap
works the same way, and defaults to
nothing
because the usual reason to specify subgroups is to constrain the clustering rather than to show gaps.
Each level is placed independently: a level specified by numbers is laid out in the order of these numbers, and a level specified by names is laid out by the clustering. Numbering both levels therefore lays the entries out in the order of their (group, subgroup) pair, and numbering just the groups keeps the groups in a fixed order while clustering the subgroups inside each of them.
If you specify
dendogram_size
, then you should either specify linkage (for computing a clustering) or must specify
Hclust
order in the data. The dendogram tree will be shown to the side of the data. The size is specified in the usual inconvenient units (fractions of the total graph size) because Plotly.
If a dendogram tree is shown, the
dendogram_line
can be used to control it. The default color is black. The
is_filled
field shouldn't be set as it has no meaning here.
SomeGraphs.Heatmaps.HeatmapReorder
—
Type
Specify how to reorder the rows and/or columns.
-
OptimalHclustordershclustbranches using the (better) Bar-Joseph method. -
RCompatibleHclustordershclustbranches in the same (bad) way thatRdoes. -
ReorderHclustreordershclustbranches to be as close as possible to a given order (usingreorder_hclust). -
SlantedHclustandSlantedPreSquaredHclustordershclustbranches usingSlanter(usingslanted_ordersandreorder_hclust). -
SlantedOrderandSlantedPreSquaredOrderusesslanted_orders(if a tree is needed, usesehclustto create a tree preserving this order). -
SameOrderorders the rows/columns in the same way as the other axis. This can only be applied to square matrices and can't be specified for both axes.
SomeGraphs.Heatmaps.HeatmapGraphOrder
—
Type
struct HeatmapGraphOrder
rows_order::AbstractVector{<:Integer}
rows_hclust::Maybe{Hclust}
columns_order::AbstractVector{<:Integer}
columns_hclust::Maybe{Hclust}
end
The computed final order and clustering of the rows and the columns of a heatmap graph, as returned by
heatmap_order
.
-
rows_orderis the order of the rows of the data, that is, the index of the original row shown at each position. This is always a permutation of1:n_rows, which for an axis that isn't reordered at all is the identity. -
rows_hclustis the tree the rows were clustered by, ornothingif they weren't clustered (they were left alone, given an explicit order, or slanted without a tree). -
columns_orderandcolumns_hclustare the same for the columns.
These describe the order of the data, not the order it is displayed in; applying the
origin
is up to whoever shows the graph, as is skipping the hidden rows and columns (the order and the tree include them).
SomeGraphs.Heatmaps.heatmap_order
—
Function
heatmap_order(graph::HeatmapGraph)::HeatmapGraphOrder
Return the
HeatmapGraphOrder
of a heatmap
graph
, that is, the final order of its rows and columns and the trees they were clustered by, without rendering it.
You can just write
graph.order
instead of
heatmap_order(graph)
. Either way the order is only computed once; showing the graph will reuse it, and vice versa.
Use this to list the entries in the order they are shown:
ordered_rows_names = graph.data.rows.names.vector[graph.order.rows_order]
Use it to show several graphs in the same order, so they can be compared. Cluster one of them, then give the rest its order (and, if they use the same groups, they will also have the same gaps):
graph.configuration.columns.reorder = OptimalHclust
other_graph.data.columns.order = graph.order.columns_order
If the graphs also show a dendogram, give them the tree instead of the order. This arranges them in the same order and draws the same tree above each of them (this only makes sense if the graphs share the same columns, as the tree refers to the original column indices):
graph.configuration.columns.reorder = OptimalHclust
graph.configuration.columns.dendogram_size = 0.1
other_graph.data.columns.order = graph.order.columns_hclust
other_graph.configuration.columns.dendogram_size = 0.1
SomeGraphs.Heatmaps.reset_order!
—
Function
reset_order!(graph::HeatmapGraph)::Nothing
Forget the
HeatmapGraphOrder
cached in the graph's
final_order
, so that asking for the graph's
order
(or showing it) will compute it again. Call this after changing anything the order was computed from.
SomeGraphs.Heatmaps.HeatmapLinkage
—
Type
Specify the linkage to use when performing hierarchical clustering (
hclust
/
ehclust
). The default is
WardLinkage
.
SomeGraphs.Heatmaps.HeatmapOrigin
—
Type
Specify where the origin (row 1 column 1) should be displayed. The Plotly default is
HeatmapBottomLeft
.
Examples:
Default (serves as a baseline to compare with when modifying options):
using SomeGraphs
graph = heatmap_graph(;
entries = MatrixValuesData([
4 1 5;
3 2 4;
2 3 3;
1 4 2;
]),
rows = HeatmapAxisData(; names = VectorValuesData(["A", "B", "C", "D"])),
columns = HeatmapAxisData(; names = VectorValuesData(["X", "Y", "Z"])),
)
using PlotlyDocumenter
to_documenter(graph.figure)
Flip axes (non-mutating):
using SomeGraphs
graph = heatmap_graph(;
entries = MatrixValuesData([
4 1 5;
3 2 4;
2 3 3;
1 4 2;
]),
rows = HeatmapAxisData(; names = VectorValuesData(["A", "B", "C", "D"])),
columns = HeatmapAxisData(; names = VectorValuesData(["X", "Y", "Z"])),
)
flipped = flip_axes(graph)
using PlotlyDocumenter
to_documenter(flipped.figure)
Flip axes (in-place):
using SomeGraphs
graph = heatmap_graph(;
entries = MatrixValuesData([
4 1 5;
3 2 4;
2 3 3;
1 4 2;
]),
rows = HeatmapAxisData(; names = VectorValuesData(["A", "B", "C", "D"])),
columns = HeatmapAxisData(; names = VectorValuesData(["X", "Y", "Z"])),
)
flip_axes!(graph)
using PlotlyDocumenter
to_documenter(graph.figure)
Annotations:
using SomeGraphs
graph = heatmap_graph(;
entries = MatrixValuesData([
4 1 5;
3 2 4;
2 3 3;
1 4 2;
]),
rows = HeatmapAxisData(;
names = VectorValuesData(["A", "B", "C", "D"]),
annotations = [AnnotationData(; values = VectorValuesData([1, 0.5, 0, 1], "score"))],
),
columns = HeatmapAxisData(;
names = VectorValuesData(["X", "Y", "Z"]),
annotations = [
AnnotationData(;
values = VectorValuesData(["yes", "maybe", "no"], "is_special"),
colors = ColorsConfiguration(;
palette = Dict("yes" => "black", "maybe" => "darkgray", "no" => "lightgray"),
),
),
],
),
)
using PlotlyDocumenter
to_documenter(graph.figure)
Dendograms:
using SomeGraphs
graph = heatmap_graph(;
entries = MatrixValuesData([
4 1 5;
3 2 4;
2 3 3;
1 4 2;
]),
rows = HeatmapAxisData(;
names = VectorValuesData(["A", "B", "C", "D"]),
annotations = [AnnotationData(; values = VectorValuesData([1, 0.5, 0, 1], "score"))],
),
columns = HeatmapAxisData(;
names = VectorValuesData(["X", "Y", "Z"]),
annotations = [
AnnotationData(;
values = VectorValuesData(["yes", "maybe", "no"], "is_special"),
colors = ColorsConfiguration(;
palette = Dict("yes" => "black", "maybe" => "darkgray", "no" => "lightgray"),
),
),
],
),
)
graph.configuration.rows.reorder = OptimalHclust
graph.configuration.columns.reorder = OptimalHclust
graph.configuration.rows.dendogram_size = 0.2
graph.configuration.columns.dendogram_size = 0.2
using PlotlyDocumenter
to_documenter(graph.figure)
Gaps:
using SomeGraphs
graph = heatmap_graph(;
entries = MatrixValuesData([
4 1 5;
3 2 4;
2 3 3;
1 4 2;
]),
rows = HeatmapAxisData(;
names = VectorValuesData(["A", "B", "C", "D"]),
annotations = [AnnotationData(; values = VectorValuesData([1, 0.5, 0, 1], "score"))],
groups = VectorValuesData([1, 1, 2, 2]),
),
columns = HeatmapAxisData(;
names = VectorValuesData(["X", "Y", "Z"]),
annotations = [
AnnotationData(;
values = VectorValuesData(["yes", "maybe", "no"], "is_special"),
colors = ColorsConfiguration(;
palette = Dict("yes" => "black", "maybe" => "darkgray", "no" => "lightgray"),
),
),
],
groups = VectorValuesData(["L", "M", "M"]),
),
)
graph.configuration.rows.reorder = OptimalHclust
graph.configuration.columns.reorder = OptimalHclust
graph.configuration.rows.dendogram_size = 0.2
graph.configuration.columns.dendogram_size = 0.2
using PlotlyDocumenter
to_documenter(graph.figure)
Subgroups (a 2nd level of grouping nested in the groups). The groups are numbered, so they are shown in the order of their numbers; the subgroups are named, so they are placed by the clustering, but each of them is still contiguous inside its group:
using SomeGraphs
graph = heatmap_graph(;
entries = MatrixValuesData([
4 1 5 2 4 1;
3 2 4 3 3 2;
2 3 3 4 2 3;
1 4 2 5 1 4;
]),
rows = HeatmapAxisData(; names = VectorValuesData(["A", "B", "C", "D"])),
columns = HeatmapAxisData(;
names = VectorValuesData(["U", "V", "W", "X", "Y", "Z"]),
groups = VectorValuesData([1, 1, 1, 2, 2, 2]),
subgroups = VectorValuesData(["P", "Q", "P", "R", "R", "S"]),
),
)
graph.configuration.columns.reorder = OptimalHclust
graph.configuration.columns.subgroups_gap = 1
using PlotlyDocumenter
to_documenter(graph.figure)
Hide some rows. The hidden ones are still part of the data, so they still count in the colors scale (unless
include_hidden
is disabled in its axis):
using SomeGraphs
graph = heatmap_graph(;
entries = MatrixValuesData([
4 1 5;
3 2 4;
2 3 3;
1 4 2;
]),
rows = HeatmapAxisData(;
names = VectorValuesData(["A", "B", "C", "D"]),
entities = VectorEntitiesData(; mask = [true, false, true, true]),
),
columns = HeatmapAxisData(; names = VectorValuesData(["X", "Y", "Z"])),
)
using PlotlyDocumenter
to_documenter(graph.figure)
Index
-
SomeGraphs.Heatmaps -
SomeGraphs.Heatmaps.EntriesConfiguration -
SomeGraphs.Heatmaps.HeatmapAxisConfiguration -
SomeGraphs.Heatmaps.HeatmapAxisData -
SomeGraphs.Heatmaps.HeatmapGraph -
SomeGraphs.Heatmaps.HeatmapGraphConfiguration -
SomeGraphs.Heatmaps.HeatmapGraphData -
SomeGraphs.Heatmaps.HeatmapGraphOrder -
SomeGraphs.Heatmaps.HeatmapLinkage -
SomeGraphs.Heatmaps.HeatmapOrigin -
SomeGraphs.Heatmaps.HeatmapReorder -
SomeGraphs.Heatmaps.heatmap_graph -
SomeGraphs.Heatmaps.heatmap_order -
SomeGraphs.Heatmaps.reset_order!