d3-plugins
d3-plugins copied to clipboard
Add support for self-loops and cycles in sankeys
- Changes the logic of assigning breadths to first break the graph down into strongly connected components, layer out the resulting DAG the same way the current algo lays out nodes; then do a bfs from the obtained
root
of each SCC and lay out cycle members. - There are very weird artefacts at the endpoints of splines for wide splines, so I ended up replacing links with 2 splines to define the structure explicitly. Fill isn't as good as I want it to be, but I'm not sure about the best way to proceed.
Sample using existing data, and with a loop: http://bl.ocks.org/d/4658510/
The code is a bit rough -- I was mainly iterating to get something that looked decent first, can/will clean up as required.
Nice work! I like the visual technique you've used for the loop back.
^ Just cleaned up the code a bit, and reverted the link behaviour to the original for people who prefer to keep the same width nodes, while adding a reversibleLink function as an alternative for people creating cyclic sankey diagrams.
The reversible link function creates three parts that get filled correctly: basically so that reversed links are filled in correctly (see the attached screenshot: the bottom image is what was, with a single path filled in, and the top svg element is the new version, with 3 paths filled in making a ribbon)
New example (slightly more complex than the previous one) with cycles: http://bl.ocks.org/kunalb/raw/5140332/
@mbostock: was this ever checked into the main repo? If not, is there an ETA?
We have a case where we are dynamically getting data for Sankey, and having it work with loops would be nice, otherwise it causes a hang.
Thought I'd check in again - we've tried the suggested code ourselves, and it works pretty well. I'd love to see this integrated into the official sankey code.
@itay I guess the fact that chord widths aren't constant is probably a problem because that's pretty crucial for most sankey diagrams? I couldn't figure out a way to fit everything in cleanly enough with constant width diagrams... @mbostock any suggestions? I can try and iterate on this.
@kunalb: that's fair, thank you for pointing it out. I guess my main concern is that the current behavior with cycles is to cause the entire tab to crash essentially, since it is in an infinite loop. If it even just errored, that would be a start. Do you think it would be possible to modify your pull request to detect cycles and then throw an event?
That's fairly trivial: sent out a separate pull request: #78
@kunalb first of, thank you for adding that separate pull request. A quick question for you: with this pull request (adding cyclic link support), are there cases where some data without cycles is rendered worse than the old version (the one in d3-plugins)? Basically, is your PR regressing anything?
If not, it seems this is a net improvement, and one that we could iterate on.
The reason I'm pushing on this particular item is that we'd really like to include sankey visualization support in something that we're doing, but it's kind of a bummer that it either hangs/errors if your data has cycles. This is especially problematic for us because our data is dynamic and we can't control whether it is cyclic or not.
@mbostock: what can we do to help get this issue solved?
Running into the same problem. Any best practice when dealing with circular reference or standard code to follow?
@pkpp1233 You could patch this diff and use reversibleLink instead of Link. See the example in the documentation for reversibleLink.
@kunalb I know this is kind of old, but I tried using your sankey.js but my simple cycle sankey isn't rendering. Is there an update to D3 which breaks this?
@josephsiu not that I know of. Put up a gist somewhere so that I can take a look?
@kunalb Sorry for the false alarm. It was a separate issue. Your edits worked great for cycles! Thanks!
@kunalb, both of the examples (http://bl.ocks.org/kunalb/4658510 and http://bl.ocks.org/kunalb/5140332) fail to run in Chrome, the console complains about wrong MIME type for sankey.js, not sure if this is something happened with the last changes, or just the Gists are acting up…
@NPC Hm, looks like github doesn't allow hotlinking js files directly any more :). I set up one of the gists as an example at http://explog.in/notes/sankey/
@kunalb, wow, these look neat. Thanks for the updated example!
@kunalb , Thank you for your great work. Just one Question: Is there any possibility to change the color of the cycle-links, without changing the color of the "normal" links?
@Erfabes you choose the link color when you draw the links for both the normal and reversible links -- see the example at https://github.com/d3/d3-plugins/pull/39/files#diff-3aa14326cff02f35c6674920e9334c9fR79 ; that's completely controlled by you.
(FYI: as maintenance of d3-plugins stalled, I started a friendly (subtree) fork (see #133) of the sankey plugin at https://github.com/soxofaan/d3-plugin-captain-sankey)
I'm also working on rendering cycles at soxofaan/d3-plugin-captain-sankey#6
@kunalb for your sankey cycle code, if I were to include a marker-end on the path, where would I put it or what kind of modifications would be required to include it? I have tried to put it in the path objects but it doesn't show up...
Hope you can help! Thanks for a great addition to the D3 library!
//marker-end of path svg.append('marker') .attr('id', "end-arrow") .attr('markerHeight', 2.5) .attr('markerWidth', 2, 5) .attr('orient', 'auto') .attr('refX', -5) .attr('refY', 0) .attr('viewBox', '-5 -5 20 10') .append('path') .attr('d', 'M 0,0 m -5,-5 L 0,0 L -5,5 Z') //.attr("fill", "#2ca25f") .style("fill", "#969696") .style("stroke", "2")
var path1 = linkEnter.append("path") .attr("class", "link1") .attr("opacity", .5) .style("marker-end", "url(#end-arrow)") .attr("fill", null) .style("fill", function (d) { return d.target.color = color(d.target.name.replace(/ .*/, "")); }) .attr("d", path(1)) .attr("class", "linkish"); ;