Sankey - Highlight all connected paths from start to end

1,366 views
Skip to first unread message

Ashish Singh

unread,
Oct 5, 2013, 4:34:12 AM10/5/13
to d3...@googlegroups.com
Hi Guys,

I'm trying to highlight all the connected links and links of their target nodes till the end of the layout. 

The first level of highlighting can be easily achieved as follows - 

On node click, call highlight_paths(1);

function highlight_paths(stroke_opacity) {

  return function(d,i){

    d.sourceLinks.forEach(function(srcLnk){
      d3.select("#link"+srcLnk.id).style("stroke-opacity", stroke_opacity);
    });
    d.targetLinks.forEach(function(srcLnk){
      d3.select("#link"+srcLnk.id).style("stroke-opacity", stroke_opacity);
    });
  }

}

But I'm not yet able to write correctly a recursive algorithm to get all the sourceLinks and targetLinks of each of the connected source & target nodes.


Let me know your thoughts!

Thanks,
Ashish
   

Ashish Singh

unread,
Oct 5, 2013, 6:46:55 AM10/5/13
to d3...@googlegroups.com
So, I was going through the sankey layout code and found something very helpful! 
Based on that here is the function to highlight all the paths from the clicked node in both the directions - Forward ( Target ) and Backward (Source)

  function highlight_node_links(node,i){

      var remainingNodes=[],
          nextNodes=[],
         stroke_opacity = 0;

      if( d3.select(this).attr("data-clicked") == "1" ){
        d3.select(this).attr("data-clicked","0");
        stroke_opacity = 0.2;
      }else{
        d3.select(this).attr("data-clicked","1");
        stroke_opacity = 0.5;
      }

      // First object traverses in Forward and the second in Backward. Remove the one you want to disable
      var traverse = [{
                        linkType : "sourceLinks",
                        nodeType : "target"
                      },{
                        linkType : "targetLinks",
                        nodeType : "source"
                      }];

      traverse.forEach(function(step){
        node[step.linkType].forEach(function(link) {
          remainingNodes.push(link[step.nodeType]);
          highlight_link(link.id, stroke_opacity);
        });

        while (remainingNodes.length) {
          nextNodes = [];
          remainingNodes.forEach(function(node) {
            node[step.linkType].forEach(function(link) {
              nextNodes.push(link[step.nodeType]);
              highlight_link(link.id, stroke_opacity);
            });
          });
          remainingNodes = nextNodes;
        }
      });
  }

  function highlight_link(id,opacity){
    d3.select("#link-"+id).style("stroke-opacity", opacity);
  }

Patrick Martin

unread,
Oct 6, 2013, 10:17:42 PM10/6/13
to d3...@googlegroups.com
I am typing this out of memory so don't expect it to run, but I think that a breadth first search which finds all nodes it's connected to, could go something like this:

bfs(node, {});

function bfs(node, visited)
{
  visited[node.name] = true;
  node.sourceLinks.forEach( function(link) {
    if (!visited[link.name])
    {
      // do whatever here...
      bfs(link.target, visited);  // Or link.source, depending on what you want to do
    }
  });
}

I added a short circuit for cyclic links.

In the code, you could record nodes, whatever.  If it helps, I have recently done some work with Sankey recently over here:


I added a category field to the links for consistent color coding throughout the flow the the visualization.  You could likely do something similar for the purpose of highlighting.

I think this would be a useful feature to Sankey.

Good luck!

- Pat 

Shreeram Kushwaha

unread,
Oct 6, 2013, 11:45:47 PM10/6/13
to d3...@googlegroups.com
No need to write any recursive algo or BFS. A simple javascript will work here.

Just write a mouse event that when you take the mouse to the node the link in both directions should get highlighted.

A------B------C

I am assuming that this is what you want---

When you click or mouse hover on B, you want the link between A & B and B & C should get highlighted.

For this you first give a class name or id to the link between the nodes suppose for A & B you gave the id as A_B and similarly for B_C.
So, the function will be coded so that whenever you do mouse click or hover, it highlights all the links which have id = *_B (If B is the node which has been mouse hovered or clicked. * is acting as a wild character.)




--
You received this message because you are subscribed to the Google Groups "d3-js" group.
To unsubscribe from this group and stop receiving emails from it, send an email to d3-js+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Regards,

(Voice  +91-7849069144)
( Shreeram Kushwaha )
Software Engineer
Samsung R&D Institute India - Bangalore

Ashish Singh

unread,
Oct 8, 2013, 3:55:58 AM10/8/13
to d3...@googlegroups.com
Thanks Patrick.

Yea, the solution is to do a bread first search. 

Great job on the sankey color highlights there! Looks pretty cool!

In the bfs that I've implemented, I've also added direction so that only source or target links can be highlighted if needed.

Thanks for the suggestions! 

Ashish Singh

unread,
Oct 8, 2013, 4:01:02 AM10/8/13
to d3...@googlegroups.com
Thanks for dropping in Shreeram. 

I needed a BFS here as all the connections need to be highlighted. The adjacent links/nodes are already present in a nodes data.

Ashish Singh

unread,
Oct 8, 2013, 4:01:49 AM10/8/13
to d3...@googlegroups.com
Thanks for dropping in Shreeram. 

I needed a BFS here as all the connections need to be highlighted. The adjacent links/nodes are already present in a nodes data.

On Monday, 7 October 2013 09:15:47 UTC+5:30, Shreeram Kushwaha wrote:

Shreeram Kushwaha

unread,
Oct 8, 2013, 5:02:34 AM10/8/13
to d3...@googlegroups.com
Ok...
Can you plz share the code for the same to highlight all the links/connections?

Ashish Singh

unread,
Oct 8, 2013, 11:30:17 PM10/8/13
to d3...@googlegroups.com
I've already posted it after my question and here

Patrick Martin

unread,
Oct 9, 2013, 12:41:04 AM10/9/13
to d3...@googlegroups.com
Glad you got it working Ashish.

I liked Shreeram's idea of tagging related links and I implemented link-through highlighting.  The end result is over here.


I attached a linkid to each related link as I added them from the data:

relation.linkid = "L" + i;

Added the attribute to the graph links:

graph.links.push({ "source": d.source, "target": d.target, "value": +d.value,
      "category" : d.category, "linkid": d.linkid });

Then on mouseover and mouseout:

     .on("mouseover", function(d) {
        d3.selectAll("#" + d.linkid)//.style("stroke-opacity", 1)
        .call(dex.config.configureLink, config.mouseover.link);
      })
      .on("mouseout", function(d) {
        d3.selectAll("#" + d.linkid)//.style("stroke-opacity", config.link.stroke.opacity);
        .call(dex.config.configureLink, config.link);
      });

Which preserves the color.  the call function is calling some helper functions which are part of the DexCharts framework I am working on.

If interested, you can find it over here:


It's kind of like the Trifacta framework, but my focus isn't strictly on D3 but a bringing a mixture of WebGL for 3D, JQueryUI for UI controls, and D3 (maybe others) for data visualization.  And with a focus on multi-dimensional charts; or rather many charts which interact.  I find that charts which interact with other charts to more effective.

- Pat

On Saturday, October 5, 2013 4:34:12 AM UTC-4, Ashish Singh wrote:

ma...@hotmaple.com

unread,
Nov 22, 2013, 7:04:00 PM11/22/13
to d3...@googlegroups.com
I'm a bit new to D3 and really rusty at javascript... can you provide more detail where to implement & call this function?

I am using the D3 Sankey script from this source:  http://bost.ocks.org/mike/sankey/

I am attempting to load the function inline in the HTML source and calling it with an .on mouseover   event etc. etc. --- but nothing is happening.

could you perhaps link to a working example so I can see the code in working order & learn how to call it up?

Thanks!
Reply all
Reply to author
Forward
0 new messages