veg / phylotree.js

Interactive viewer of phylogenetic trees
http://phylotree.hyphy.org
MIT License
168 stars 72 forks source link

Displaying Text besides the node labels #410

Open santule opened 2 years ago

santule commented 2 years ago

Hello,

I am trying to display some information about a node besides the node label in the tree. An example, is to display partial sequence of that particular node. Example I created rectangles beside the node but would like to add sequence letters in the rectangle boxes.

Screen Shot 2022-04-06 at 12 39 38 am

For this, I tried to create text svg element in the node-styler function. The only way I was able to display the custom text besides a node label is by doing the below. The below code adds the text "HELLO" to the node label.

var annotation = element.selectAll("text").data([data.data.name + " HELLO"]); annotation.enter().append ("text") annotation.attr ("y",-3/2).attr("x",20).text(function(d) {return d})

Screen Shot 2022-04-06 at 12 21 55 am

But this interfere with the drop down menu functionality on the node. What is the best option to display text inside the rectangle?

Thank you and appreciate your help.

spond commented 2 years ago

Dear @santule,

One option is to simply add more text to the name of the node that phylotree.js uses. This way all the events that are triggered by clicks on node names should work. \

In your example you could do something like (this is for >1.0.0)

renderedTree = {
  let rt = tree.render({
  height:height, 
  width:width,
  'left-right-spacing': 'fit-to-size', 
  'align-tips':true,
  'node-styler': colorNodesByName,
  'edge-styler': colorEdgesByTarget
  });
  rt.nodeLabel ((n)=>{
      return n.data.name + " HELLO";
  });

  return rt;
};

Best, Sergei

santule commented 2 years ago

Thank you for your quick reply. I was hoping to display the information on button click "show protein sequences" instead of loading it with tree initially. But I should be able to call render tree on button click, I will try it and update here. Appreciate your help and your library is the best one out there. I was able to load 10,000+ sequences very fast on the browser.

santule commented 2 years ago

I have managed to load the sequences info besides the node using combination of rectangle and text svg. It looks like so-

Screen Shot 2022-04-28 at 10 15 50 pm

But when you collapse nodes, the node name of the leaf node moves and the position of the sequence too. So the names don't look aligned anymore. This is because the rendered tree is updated with new positions of the collapsed nodes.

Screen Shot 2022-04-28 at 6 57 42 pm

But is there a way to fix this, so the node names and the sequence text beside them are always aligned?

Regards,

spond commented 2 years ago

Dear @santule,

Do you have a working example I could look at? Otherwise it's hard for me to guess what the issue is. Maybe just provide the node styler function?

Best, Sergei

santule commented 2 years ago

Dear @spond , Apologies for the delay in reply at my end.

The note styler function is pasted below. I have hardcode rightmost_leaf as 900 as I dont know what the right most position is when node styler is called. I believe the right most position is available once the tree is rendered. I also have try and error as once the nodes start collapsing , the element.style line gives an error as it cant access the node names.

When you start collapsing the internal nodes, the sequence displayed on the right start shifting as I think the tree renders again and the x/y positions are moved.

    function colorNodesByName (element, data) {
    node_colorizer (element, data);

    try{
        // get the node name
        var node_name = (data.data.name);
        var seq_node_data = data.data.annotation["seq_data"];

        // click to get node details
        element.on('click', function() {
            console.log(node_name)
            console.log(tree.getNodeByName(node_name))
        });

        // color the node as per the annotations
        element.style ("fill", data.data.annotation["node_color"]);

    }
    catch(err) {}

    // display sequence or properties of a node ////
    var font_size = 12;
    rightmost_leaf = 900;
    var x_shift = rightmost_leaf -  data.screen_x;
    //var x_shift = node_name.length * font_size
    console.log(node_name)
    console.log(x_shift)

    var annotation_g = element.selectAll("g").data(Array.from(seq_node_data)).enter().append("g");

    annotation_g.append("text")
    .attr ("y",font_size/4)
    .attr ("transform", null).attr ("x", function (d, i) {return  x_shift + font_size * i + font_size / 4;})
    .attr ("font-size",10)
    .style ("fill", function(d, i) { 
                    return attribute_to_color (d);
                   })
    .attr("font-weight", "bold")
    .text(function(d) {return d});

    annotation_g.append("rect")
        .attr ("width", font_size)
        .attr ("height", font_size)
        .attr ("y", -font_size/2)
        .attr("opacity", 0.5)
        .style("stroke-width",0)
        .style ("fill", function(d, i) { 
                    return attribute_to_color (d);
                   })
        .attr ("transform", null).attr ("x", function (d, i) {return  x_shift + font_size * i;});

}`

Appreciate and thanks for your help.