Comments (10)
Dear @pschwien82,
Not the prettiest solution, but should get your started: http://bl.ocks.org/spond/707878838762cb57d892a5d8e774d4e0
The idea is to use the callback invoked when each node is drawn (node_styler
) and add the desired graphical elements (in the example : 3 colored boxes) to the SVG element that is the node.
@stephenshank : if you look at the example, it exposes some of the limitations of the node styler callback, which we should discuss how to remedy. For example, there should be no need to manually handle rotations and shifts for radial layouts, and there needs to be a mechanism to request layout space for node labels to accommodate arbitrary elements.
Best,
Sergei
from phylotree.js.
I am working on this topic as well as part of a project for the university and I am interested in future updates.
what I managed to do so far is something like this:
I have three different categories of data and this is where I got so far.
I didn't use the node_styler but just append new svg elements at the end of the labels. I see now that the solution presented here might solve me a lot of effort actually.
So thank you very much :) and looking forward to new updates or examples
from phylotree.js.
Thank you Sergei,
this was a super fast response, I appreciate it.
We will try the code sample out in the next few days!
Best,
Patrick
from phylotree.js.
Hello again,
I used the code example for my project but I have some issues I cannot manage to solve.
My issue is on the resizing of the svg. More precisely, when I add "longer shapes" (so instead of the three squares presented in the code I want to bind "barplots", each bar on each node, showing a quantitative type of data) the issue I have is that on the linear layout the svg gets resized too small to show the whole "length" of the shapes.
I tried playing a bit with your example and maybe I didn't really understand how the
'left-right-spacing' and 'top-bottom-spacing' options work.
This is the code I am using:
`<script>
var example_tree = "(((glp1r_human:0.03295,g1sgd4_rabit:0.01369):0.30976,glr_human:0.27221):0.47235,(crfr1_human:0.64018,(grm1_human:0.10097,grm5_human:0.17333):3.05238):0.10081,calcr_human:0.71265);";
// tree from Yokoyama et al http://www.ncbi.nlm.nih.gov/pubmed/18768804
var tree = d3.layout.phylotree()
// create a tree layout object
.svg(d3.select("#tree_display")).align_tips(true).radial(true);
// render to this SVG element
var attribute_to_color = d3.scale.category10();
var standard_label = tree.branch_name();
tree.branch_name(function (node) {
return standard_label(node) + " ";
});
tree(d3.layout.newick_parser(example_tree));
tree.size([400, 400]);
var tree_attributes = {};
/* the following loop just populates an object with key : value pairs like
leaf_name -> [a,b,c], where a,b,c are random numbers in {0,1,2,3,4}
*/
var maximum_length = 0;
tree.traverse_and_compute (function (node) {
if (d3.layout.phylotree.is_leafnode (node)) {
tree_attributes[node.name] = [0,0,0].map (function () {return Math.floor(Math.random() * 5);});
maximum_length = maximum_length < node.name.length ? node.name.length : maximum_length;
}
});
tree.style_nodes(function (element, node_data) {
if (node_data.name in tree_attributes) { // see if the node has attributes
var node_label = element.select("text");
var font_size = parseFloat(node_label.style("font-size"));
var annotation = element.selectAll("rect").data(tree_attributes[node_data.name]);
annotation.enter().append("rect");
annotation.attr ("width", font_size)
.attr ("height", font_size)
.attr ("y", -font_size/2).style ("fill", function(d, i) {
return attribute_to_color(d);
});
var move_past_label = maximum_length * 0.75 * font_size;
if (tree.radial ()) {
var shifter = tree.shift_tip(node_data)[0];
annotation.attr("transform", "rotate (" + node_data.text_angle + ")")
.attr ("x", function (d, i) { return shifter > 0 ? shifter + font_size * i + move_past_label : shifter - font_size * (i+1) - move_past_label;})
} else {
var x_shift = tree.shift_tip (node_data)[0] + move_past_label;
annotation.attr ("transform", null).attr ("x", function (d, i) { return x_shift + font_size * i;});
}
}
});
tree.options({
'show-scale': true
'left-right-spacing': "fit-to-size",
// fit to given size top-to-bottom
'top-bottom-spacing': "fit-to-size"
// fit to given size left-to-right
//'selectable': false,
// make nodes and branches not selectable
//'collapsible': false,
// turn off the menu on internal nodes
//'transitions': false
// turn off d3 animations
})
$("#layout").on ("click", function (e) {
tree.radial ($(this).prop ("checked")).placenodes().update ();
});
// parse the Newick into a d3 hierarchy object with additional fields
tree.layout();`
The first output looks like this:
which is how the tree is supposed to look like.
When i switch view it looks like this:
Which is good. But when I switch again to radial, the tree changes and looks like this:
So, this is the issue I don't understand. Could you explain why this happens??
This project I am working on is part of an exam that I'll have in late June and if the output of the project will be functional then it might end up being used as an official tool on this website:
http://gpcrdb.org/
Therefore I am highly interested in solving the issue hereby presented.
Thanks for your help.
from phylotree.js.
Dear @carlotta-93,
I think both radial trees are the same, just that the second one uses an "annular" display near the center to space things out a bit differently. I will make a note to track down why the layout changes between the two iterations (it should be stable), but the tree is not wrong in either case.
I'll update this thread when I have a solution for stable rendering.
Best,
Sergei
from phylotree.js.
Hi @spond,
Thanks for your reply. I understand that now but the weird part is that the "annular" is not added when "fixed-size" is chosen instead of "fit-to-size".
For stable rendering you mean when "longer" shapes are added ? Shall I add some pictured to make the problem more clear ?
Thank you very much for your help.
from phylotree.js.
Dear @carlotta-93,
Yes, more pictures would be helpful. By stable rendering I mean that when you switch between radial and linear views, you should get the same renderings for each mode regardless of how many switches occur.
Best,
Sergei
from phylotree.js.
All right,
Firstly, I am using these options:
tree.options({ 'show-scale': true //'left-right-spacing': "fixed-step", // fit to given size top-to-bottom //'top-bottom-spacing': "fixed-step" // fit to given size left-to-right //'selectable': false, // make nodes and branches not selectable //'collapsible': false, // turn off the menu on internal nodes //'transitions': false // turn off d3 animations })
so the spacings are default to "fixed-step". And the tree is built with the same code as the example for the metadata. (there is option for width neither in the HTML nor the .js)
The problem with the "longer shapes" I have is the following
First layout:
Here the size of the svg is "arbitrary chosen" and everything is fine.
When I add "barplots" to show quantitative data this is what happens in radial layout:
So, some of the shapes are cut out from the svg (which mantains the same size)
If I switch to linear layout, this is what happens:
And the size of the svg is "resized" but it is too small in width.
If I change the size from the "inspection" board I get to see my barplots entirely:
What I would like to understand is why this happens and if there is a way to solve it.
I tries using "fit-to-size" with tree.size([800, 800]) exactly the same happens.
Thanks for your time
from phylotree.js.
Dear @carlotta-93,
It looks like you are toggling bar plots on and off. In order to understand what phylotree is doing at that moment, can you provide the code for your event handler for when the annotations are added?
Best,
Sergei
from phylotree.js.
Hi @spond,
Here is the code:
` function draw_quantitative_data(select_data, data_type){
tree.align_tips(true);
var maximum_length = 0;
var receptor_coverage = {}; // create object of GPCR_classes to bind to element
tree.get_nodes().forEach(function (node) {
if (d3.layout.phylotree.is_leafnode(node)) {
select_data.forEach(function (receptor) {
if(node.name === receptor.name){
receptor_coverage[node.name] = [0].map(function () {
return receptor.coverage
});
}
});
maximum_length = maximum_length < node.name.length ? node.name.length : maximum_length;
}
});
var coverage_tooltip = d3.select("body").append("div")
.attr("class", "coverage_tooltip")
.style("opacity", 0);
var max_rect_h = 30;
var yScale_radial = d3.scale.linear() // scale to draw the quantities relative to the max_rect_h
.domain([1, 0]) // change to max and min values from the type
.range([max_rect_h, 0]);
tree.style_nodes(function (element, node_data) {
if (node_data.name in receptor_coverage) { // see if the node has attributes
var node_label = element.select("text");
var font_size = parseFloat(node_label.style("font-size"));
var annotation = element.selectAll("rect").data(receptor_coverage[node_data.name]);
annotation.enter().append("rect").attr("class", "receptor_coverage");
annotation
.attr ("height", font_size)
.attr("width", function (d) {
return yScale_radial(d)
})
.attr ("y", -font_size/2)
.style("fill", "#DBB1CD")
.on("mouseover", function(d) { // add tooltip
coverage_tooltip.transition()
.style("opacity", .9);
coverage_tooltip.html(function(){
return ("Coverage: " + d)
})
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function() {
coverage_tooltip.transition().duration(100)
.style("opacity", 0);
});
var move_past_label = maximum_length * 0.65 * font_size;
if (tree.radial ()) {
var shifter = tree.shift_tip(node_data)[0];
annotation.attr("transform", "rotate (" + node_data.text_angle + ")")
.attr ("x", function (d, i) { return shifter > 0 ? shifter + font_size * i + move_past_label : shifter - font_size * (i+1) - move_past_label;})
} else {
var x_shift = tree.shift_tip (node_data)[0] + move_past_label;
annotation.attr ("transform", null).attr ("x", function (d, i) { return x_shift + font_size * i;});
}
}
});
tree.layout();`
The select_data arguments is an array of dictionaries as follows:
{ "name":"glr_human", "GPCR_class":"C (Glutamate)", "selectivity":["Gi/Go family", "Gq/G11 family", "Gs family"], "ligand_type":"Protein receptors", "coverage":0.6, "receptor_page":"http://gpcrdb.org/protein/glr_human/" },
Where coverage is a random number between 0 and 1
from phylotree.js.
Related Issues (20)
- Setting the font-size doesn't work HOT 3
- Newick files without lengths should not be coerced to distances of 1 HOT 1
- Node IDs are undefined HOT 4
- Some problems when I'm trying to use with react and electron HOT 5
- TS types HOT 2
- Allow menu to be shown on 'contextmenu'
- Is it possible to register a zoom callback on the tree? HOT 1
- Bug in escaping single quotes in Newick export HOT 1
- Does phylotree use a specific version of d3 HOT 2
- How to remove the label of tips?
- Scale bar in Phylotree.js HOT 2
- Lag when loading my large phylogeny in radical mode in observable
- How to color the bubble using different colors? HOT 2
- Test giving error due to missing file
- PhyloXML string not supported
- Error on PhyloXML trees with single-branch clades
- Error on PhyloXML documents with multiple phylogenies
- Using phylotree in vue3 HOT 4
- Feature request - face to face tree plot HOT 2
- A question about rendering HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from phylotree.js.