Creating a Sankey diagram

133 views
Skip to first unread message

bstaats

unread,
Apr 23, 2010, 4:04:23 PM4/23/10
to protovis
Does anyone have suggestions for implementing a Sankey diagram?

My attempts so far using directed arcs, line interpolate, lineJoin
etc.. (without cobbling together several lines and arcs) all have been
unsuccessful. The missing peace is generating the appropriate S curve
between two nodes (not an arc).

For example
http://www.svgopen.org/2003/papers/RenderingGraphs/index.html
http://www.sankey-diagrams.com/

Any pointers or guidance would be greatly appreciated. Thanks!

--
You received this message because you are subscribed to the Google Groups "protovis" group.
To post to this group, send email to prot...@googlegroups.com.
To unsubscribe from this group, send email to protovis+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/protovis?hl=en.

Mike Bostock

unread,
Apr 24, 2010, 12:50:42 PM4/24/10
to prot...@googlegroups.com
Have you tried the new spline interpolation for lines in 3.2?

http://gitorious.org/protovis

Mike

bstaats

unread,
Apr 26, 2010, 2:16:33 PM4/26/10
to protovis
I have used line interpolate in 3.2. However, there are a few problems
getting it to work.

1. Using the segmented(true) flag so each line can be a different
width (like a sankey) negates any interpolation.
2. Also, it doesn't appear you can get a controlled S curve between
two points with the line interpolation.

Am I wrong? Is there a another way?

Thanks

On Apr 24, 12:50 pm, Mike Bostock <mbost...@cs.stanford.edu> wrote:
> Have you tried the new spline interpolation for lines in 3.2?
>
> http://gitorious.org/protovis
>
> Mike
>
>
>
>
>
> On Fri, Apr 23, 2010 at 1:04 PM, bstaats <brian.sta...@gmail.com> wrote:
> > Does anyone have suggestions for implementing a Sankey diagram?
>
> > My attempts so far using directed arcs, line interpolate, lineJoin
> > etc.. (without cobbling together several lines and arcs) all have been
> > unsuccessful. The missing peace is generating the appropriate S curve
> > between two nodes (not an arc).
>
> > For example
> >http://www.svgopen.org/2003/papers/RenderingGraphs/index.html
> >http://www.sankey-diagrams.com/
>
> > Any pointers or guidance would be greatly appreciated. Thanks!
>
> > --
> > You received this message because you are subscribed to the Google Groups "protovis" group.
> > To post to this group, send email to prot...@googlegroups.com.
> > To unsubscribe from this group, send email to protovis+u...@googlegroups.com.
> > For more options, visit this group athttp://groups.google.com/group/protovis?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups "protovis" group.
> To post to this group, send email to prot...@googlegroups.com.
> To unsubscribe from this group, send email to protovis+u...@googlegroups.com.
> For more options, visit this group athttp://groups.google.com/group/protovis?hl=en.

Vadim

unread,
Apr 26, 2010, 2:28:11 PM4/26/10
to protovis
Hey!
It's funny that you should mention it. I am just working on the curved
segmented lines and areas. (The lines are done, the areas will be done
before the end of day).
I will be pushing the code to:
http://gitorious.org/~vad/protovis/vads-protovis

...and submitting merge requests to the main repository.

I will post here when that is done.

Best regards,
Vadim

Vadim Ogievetsky

unread,
Apr 26, 2010, 2:23:30 PM4/26/10
to prot...@googlegroups.com
Hey!
It's funny that you should mention it. I am just working on the curved
segmented lines and areas. (The lines are done, the areas will be done
before the end of day).
I will be pushing the code to:
http://gitorious.org/~vad/protovis/vads-protovis

...and submitting merge requests to the main repository.

I will post here when that is done.

Best regards,
Vadim

bstaats

unread,
Apr 26, 2010, 4:49:48 PM4/26/10
to protovis
Excellent! I look forward to your commit. Did you workup a sankey
example (or other test) using the new changes? That would be icing on
the cake!

Thanks Vadim!

Vadim

unread,
Apr 27, 2010, 3:33:58 AM4/27/10
to protovis
Hi Brian,

I have committed all the segmented drawing code to
http://gitorious.org/~vad/protovis/vads-protovis soon it will be
reviewed and be part of the main branch but meanwhile you can download
it straight from my repository if you like. I have uploaded some of
the basic code tests here: http://vadim.ogievetsky.com/projects/segmented-spline/

I also had a look at the Sankey diagrams and bashed together a simple,
quick and dirty example (http://vadim.ogievetsky.com/projects/sankey/
sankey.html) it does not use any of the segmented code but the awesome
new monotone interpolator came in very handy.

Best regards,
Vadim

bstaats

unread,
Apr 27, 2010, 9:05:47 AM4/27/10
to protovis
Fantastic! You rock!

Digging into it now!

On Apr 27, 3:33 am, Vadim <vadi...@gmail.com> wrote:
> Hi Brian,
>
> I have committed all the segmented drawing code tohttp://gitorious.org/~vad/protovis/vads-protovissoon it will be

bstaats

unread,
May 14, 2010, 1:30:48 PM5/14/10
to protovis
Vadim, et. al.

I am working on a Sankey layout (pv.Layout.Sankey) based on your
recent commits. The goal is render a Sankey diagram from a directed
graph.

I spent ~2 days trying to learn the way pv.Layout.Network etc.. works
in order to accomplish the goal... Its time for some help/guidance.

My 1st step is to get something close to a simple Sankey using a 3
node directed graph in pv.Layout.Tree. I am having a difficult time
understanding how the lines between the nodes are drawn in order to
use one of the fancy interpolate algorithms to create/control the 'S'
curves between the nodes. Ive tried a few approaches but no dice. Any
direction/guidance would be greatly appreciated. Below is the basic
example I am working from. Thanks!


var h = 600,
w = 600,
m = 20,
b = 100
treegraph = { n1:50,
n2:50
};

var vis = new pv.Panel()
.width(w)
.height(h)
.margin(m);

var layout = vis.add(pv.Layout.Tree)
.nodes(pv.dom(treegraph).nodes())
.depth(w)
.breadth(b)
.orient("left");

layout.link.add(pv.Line)
/*
Something magical happens here
*/
.segmented(true)
.interpolate("monotone");

layout.node.add(pv.Dot);
layout.label.add(pv.Label);

vis.render();

On Apr 27, 3:33 am, Vadim <vadi...@gmail.com> wrote:
> Hi Brian,
>
> I have committed all the segmented drawing code tohttp://gitorious.org/~vad/protovis/vads-protovissoon it will be
> reviewed and be part of the main branch but meanwhile you can download
> it straight from my repository if you like. I have uploaded some of
> the basic code tests here:http://vadim.ogievetsky.com/projects/segmented-spline/
>
> I also had a look at theSankeydiagrams and bashed together a simple,
> quick and dirty example (http://vadim.ogievetsky.com/projects/sankey/sankey.html) it does not use any of the segmented code but the awesome
> new monotone interpolator came in very handy.
>
> Best regards,
> Vadim
>
> On Apr 26, 1:49 pm, bstaats <brian.sta...@gmail.com> wrote:
>
>
>
>
>
> > Excellent! I look forward to your commit. Did you workup asankey
> > example (or other test) using the new changes? That would be icing on
> > the cake!
>
> > Thanks Vadim!
>
> > On Apr 26, 2:28 pm, Vadim <vadi...@gmail.com> wrote:
>
> > > Hey!
> > > It's funny that you should mention it. I am just working on the curved
> > > segmented lines and areas. (The lines are done, the areas will be done
> > > before the end of day).
> > > I will be pushing the code to:http://gitorious.org/~vad/protovis/vads-protovis
>
> > > ...and submitting merge requests to the main repository.
>
> > > I will post here when that is done.
>
> > > Best regards,
> > > Vadim
>
> > > On Apr 26, 11:16 am, bstaats <brian.sta...@gmail.com> wrote:
>
> > > > I have used line interpolate in 3.2. However, there are a few problems
> > > > getting it to work.
>
> > > > 1. Using the segmented(true) flag so each line can be a different
> > > > width (like asankey) negates any interpolation.

Mike Bostock

unread,
May 14, 2010, 2:13:24 PM5/14/10
to prot...@googlegroups.com
> layout.link.add(pv.Line)

This statement adds a new Line mark to the layout, extending from the
`layout.link` mark prototype, which provides useful properties for
inheritance, such as positioning the control points of the line using
the `x` and `y` attributes of the associated node data:

.left(function(d) d.x)
.top(function(d) d.y)

The magic is that the Line is not added directly to the layout, but
instead added to a new Panel that is replicated for each link in the
graph. We could rewrite the `add` to be explicit, which would look
like this:

layout.add(pv.Panel)
.data(function() layout.links())
.add(pv.Line)
.data(function(p) [p.sourceNode, p.targetNode])
.left(function(d) d.x)
.top(function(d) d.y)
...

We want to draw a line between every pair of connected nodes, i.e., a
line per link. The Line mark renders a polyline (or a spline) with any
number of control points. In this case, however, our lines have
exactly two control points: the source node and the target node. So,
the data associated with the Line is an array of two nodes, and the
data associated with the enclosing Panel is the array of all links.

So, one simple way that you can implement your own network layout is
to initialize the `x` and `y` attributes of the node data, which will
result in setting the positions of the nodes and the links between
them. Another way that you can do it is to override the `top` and
`left` properties of the node prototype:

layout.node
.top(... a function to set the top position ...)
.left(... a function to set the left position ...);

Subsequent calls to layout.node.add and layout.link.add will inherit
the overridden top and left properties. There's a simple example of
this in Gitorious at tests/layout/network.html.

Mike

bstaats

unread,
May 14, 2010, 3:31:04 PM5/14/10
to protovis
Thanks Mike, that helps clarify a few things.

It sounds like what I need to do is add control points (steps) between
the two nodes and not necessarily change the 'x' and 'y' attributes of
the source and target nodes. Correct?

My question now is there a better way of doing this without adding
ghost nodes between the two real ones?

Unless advised differently, I would take the data associated with the
line (source and target nodes) and add 2 more (nodes, marks, or
other?) between the 2 original nodes in order to give a total of 4
control points. Then override the 'top' and 'left' properties of the 2
inner points to create the desired 'S' shape. Is this a sound
strategy? Will adding "ghost" nodes muck with anything else going on
under the hood?

Thanks for your input!

Mike Bostock

unread,
May 14, 2010, 3:59:20 PM5/14/10
to prot...@googlegroups.com
> It sounds like what I need to do is add control points (steps) between
> the two nodes and not necessarily change the 'x' and 'y' attributes of
> the source and target nodes. Correct?

Yep. You probably want to change the `data` property for the `link`
prototype so that it returns the array of control points. You can
represent the control points as objects with `x` and `y` attributes,
and the existing link `top` and `left` properties will work as-is. If
you only change the data property for the link prototype, it won't
affect the other mark prototypes (node and label).
Reply all
Reply to author
Forward
0 new messages