Visualize.Layout.Sankey (Visualize v0.2.35)

Copy Markdown View Source

Sankey diagram layout for visualizing flow between nodes.

Creates flow diagrams where the width of links is proportional to the flow quantity. Commonly used for showing energy transfers, money flows, or any directed weighted graph.

The layout is a port of d3-sankey: columns come from the alignment function over the longest-path depth of every node, one scale sizes both node heights and link widths, and the vertical positions are relaxed towards the ideal link positions with two-sided collision resolution.

Examples

nodes = [
  %{id: "a", name: "Source A"},
  %{id: "b", name: "Source B"},
  %{id: "c", name: "Target C"},
  %{id: "d", name: "Target D"}
]

links = [
  %{source: "a", target: "c", value: 10},
  %{source: "a", target: "d", value: 5},
  %{source: "b", target: "c", value: 8},
  %{source: "b", target: "d", value: 12}
]

sankey = Visualize.Layout.Sankey.new()
  |> Visualize.Layout.Sankey.size(400, 300)
  |> Visualize.Layout.Sankey.node_width(20)
  |> Visualize.Layout.Sankey.node_padding(10)
  |> Visualize.Layout.Sankey.compute(nodes, links)

# Access computed positions
sankey.nodes  # Nodes with x0, x1, y0, y1 coordinates
sankey.links  # Links with source/target nodes and path data

Summary

Functions

Computes the Sankey layout from nodes and links.

Generates a horizontal link path using cubic Bezier curves.

Sets the number of relaxation iterations

Generates SVG path data for a link

Generates SVG path data for all links

Sets a custom link sorting function.

Creates a new Sankey layout

Sets the node alignment method (d3-sankey's sankeyLeft, sankeyRight, sankeyCenter and sankeyJustify).

Sets the vertical padding between nodes

Sets the node width

Returns the nodes grouped by layer

Sets the diagram size

Types

sankey_link()

@type sankey_link() :: %{
  :source => any(),
  :target => any(),
  :value => number(),
  optional(:y0) => number(),
  optional(:y1) => number(),
  optional(:width) => number(),
  optional(:path) => String.t()
}

sankey_node()

@type sankey_node() :: %{
  :id => any(),
  optional(:name) => String.t(),
  optional(:x0) => number(),
  optional(:x1) => number(),
  optional(:y0) => number(),
  optional(:y1) => number(),
  optional(:value) => number(),
  optional(:depth) => non_neg_integer(),
  optional(:height) => non_neg_integer(),
  optional(:layer) => non_neg_integer(),
  optional(:source_links) => [map()],
  optional(:target_links) => [map()]
}

t()

@type t() :: %Visualize.Layout.Sankey{
  height: number(),
  iterations: non_neg_integer(),
  link_sort: (sankey_link(), sankey_link() -> boolean()) | nil,
  links: [sankey_link()],
  node_align: :left | :right | :center | :justify,
  node_padding: number(),
  node_width: number(),
  nodes: [sankey_node()],
  width: number()
}

Functions

compute(sankey, nodes, links)

@spec compute(t(), [sankey_node()], [sankey_link()]) :: t()

Computes the Sankey layout from nodes and links.

Returns the sankey struct with computed node positions and link paths.

iterations(sankey, n)

@spec iterations(t(), non_neg_integer()) :: t()

Sets the number of relaxation iterations

new()

@spec new() :: t()

Creates a new Sankey layout

node_align(sankey, align)

@spec node_align(t(), :left | :right | :center | :justify) :: t()

Sets the node alignment method (d3-sankey's sankeyLeft, sankeyRight, sankeyCenter and sankeyJustify).

  • :left - every node at its depth (longest path from a source)
  • :right - every node at L - height (longest path to a sink), so sinks share the last column
  • :center - a node with incoming links at its depth, a node with only outgoing links one column before its nearest target, an isolated node at 0
  • :justify - every node without outgoing links in the last column, others at their depth (default)

node_padding(sankey, padding)

@spec node_padding(t(), number()) :: t()

Sets the vertical padding between nodes

node_width(sankey, width)

@spec node_width(t(), number()) :: t()

Sets the node width

nodes_by_layer(sankey)

@spec nodes_by_layer(t()) :: [[sankey_node()]]

Returns the nodes grouped by layer

size(sankey, width, height)

@spec size(t(), number(), number()) :: t()

Sets the diagram size