/**
* This component uses the D3 library and specifically its implementation of the bundle algorithm to
* represent a network of protein interactions.
*
* @class
* @extends Biojs
*
* @author Gustavo A. Salazar
* @version 0.9.1_beta
* @category 1
*
* @requires jQuery Core 1.7.2
* @dependency
*
* @requires D3
* @dependency
*
* @requires InteractionsD3 CSS
* @dependency
*
* @param {Object} options An object with the options for the InteractionsD3 component.
*
* @option {string} target
* Identifier of the DIV tag where the component should be displayed.
* @option {string} width
* Width of the SVG element, if given in percentage, it will use it on proportion of the container
* @option {string} height
* Height of the SVG element, if given in percentage, it will use it on proportion of the container
* @option {string} radius
* Radius of the nodes representing the proteins
* @option {string} textLength
* Space in pixels to be reserved for the labels around the circle
*
* @example
* var instance = new Biojs.InteractionsBundleD3({
* target: "YourOwnDivId",
* });
* var pid=1;
* for (var i=0;i<100;i++)
* instance.addProtein({id:'p'+pid++,group:1,organism:"human"});
* for (var i=0;i<100;i++)
* instance.addProtein({id:'p'+pid++,group:1,organism:"TB"});
* for (var i=1;i<200;i++){
* instance.addInteraction("p"+(i),"p"+(100+i),{id:"p"+(i)+"_p"+(100+i),feature1:"value"});
* instance.addInteraction("p"+(i),"p"+(i%17),{id:"p"+(i)+"_p"+(i%17),feature1:"value"});
* }
* instance.restart();
*/
Biojs.InteractionsBundleD3 = Biojs.extend (
/** @lends Biojs.InteractionsBundleD3# */
{
cluster:null,
bundle:null,
vis:null,
splines:[],
model:{},
organisms:{},
proteins:[],
interactions:[],
interactionsA:{},
svg:null,
//Transformation values
tTranslate:null,
tScale:null,
constructor: function (options) {
var self = this;
self.cluster=null;
self.bundle=null;
self.vis=null;
self.splines=[];
self.model={"name":"", "children":[] };
self.organisms={};
self.proteins=[];
self.interactions=[];
self.svg=null;
self.interactionsA={};
this._container = $("#"+self.opt.target);
this._container.empty();
$(this._container).addClass("graphCircle");
var w = $(this._container).width(),
h = $(this._container).height();
w = (self.opt.width.indexOf("%")!=-1)?w*(self.opt.width.substring(0, self.opt.width.length-1)*1)/100.0:self.opt.width*1;
self.opt.width=w;
h = (self.opt.height.indexOf("%")!=-1)?h*(self.opt.height.substring(0, self.opt.height.length-1)*1)/100.0:self.opt.height*1;
self.opt.height=h;
var rx = w / 2,
ry = h / 2;
var tmpR=(rxb[1]){
return -1;
}else
return 1;
return a[0]-b[0];
});
},
_paintLegend:function(legend,type){
var self = this;
legend.filter(function(d) { return d[0]== "label" && d[1]==type; }).append("text")
.attr("x", self.opt.width/2 - 6)
.attr("y", 7-self.opt.height/2)
.attr("dy", ".35em")
.style("text-anchor", "end")
.style("font-size", "1.2em")
.text(type+":");
if (type.indexOf("Resize By")==0){
legend.filter(function(d) { return d[0]!="label" && d[1]==type; }).append("path")
.attr("class", "figure")
.attr("d", function(d) {
var h=2*self.opt.radius*Math.sqrt(d[0][2]);
return "M0,0L0,10M0,5L"+h+",5M"+h+",0L"+h+",10 ";
})
.attr("transform", function(d) {
return "translate(" + (self.opt.width/2 - 18 - 2*self.opt.radius*Math.sqrt(d[0][2])) + ", -" + self.opt.height/2 + ")";
})
.style("fill", "transparent")
.style("stroke", "black");
legend.filter(function(d) { return d[0]!="label" && d[1]== type; }).append("text")
.attr("x", function(d) {
return (self.opt.width/2 - 22 - 5*self.opt.radius);
})
.attr("y", 7-self.opt.height/2 )
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return (d[0][1]*1.0).toFixed(2); });
}else{
legend.filter(function(d) { return d[0]!="label" && d[1]==type; }).append("rect")
.attr("x", self.opt.width/2 - 18)
.attr("y", -self.opt.height/2)
.attr("width", 13)
.attr("height", 13)
.style("fill", function(d,i) {
if (typeof d[2]== "undefined")
return self.colors[i];
return d[2];
});
legend.filter(function(d) { return d[0]!="label" && d[1]== type; }).append("text")
.attr("x", self.opt.width/2 - 24)
.attr("y", 7-self.opt.height/2)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d[0]; });
}
},
_paintLegends: function(){
var self = this;
var w=18 + self.longestLegend*7 + 10;
var legendBlock = self.svg.insert("g",".link")
.attr("class", "legendBlock");
self._sortLegends();
legendBlock.append("rect")
.attr("x", self.opt.width/2 -w)
.attr("y", -self.opt.height/2)
.attr("height", 6 + self.legends.length *16)
.attr("width", w)
.style("fill", "#ddd")
.style("fill-opacity","0.4");
var legend = legendBlock.selectAll(".mainLegend")
.data(self.legends)
.enter().insert("g")
.attr("class", "mainLegend")
.attr("transform", function(d, i) { return "translate(0," + (3 + i * 16) + ")"; });
for (var i=0; i< self.legendTypes.length; i++)
self._paintLegend(legend,self.legendTypes[i]);
},
longestLegend:4,
legendTypes:[],
/**
* Adds a legend to the graphic
*
* @example
* instance.addLegends(["Legend red"],"Color","#FF0000");
* instance.restart();
*/
addLegends:function(legends,type,color){
var self = this;
if (self.legends==null) self.legends=[],self.legendTypes=[];
if (legends==null) {
self.legends = null;
self.legendTypes=[];
self.longestLegend=4;
return;
}
if (type=="Resize By")
type = type+ " "+legends[0];
if (self.legendTypes.indexOf(type)==-1) {
self.legends.push(["label",type]);
self.legendTypes.push(type);
if (type.length>self.longestLegend)
self.longestLegend=type.length;
}
if (type.indexOf("Resize By")==0){ //is a size label
self.legends.push([legends,type]);
} else //is a color label
for (var i=0;iself.longestLegend)
self.longestLegend=legends[i].length;
}
},
/**
* Hides the elements on the graphic that match the selector.
* Check the CSS3 selectors documentation to build a selector string
*
* @param {string} selector a string to represent a set of elements. Check the CSS3 selectors documentation to build a selector string
*
* @example
* instance.hide('[id *="node-p1"]');
*/
hide: function(selector){
var self=this;
self.vis.selectAll(selector).attr("visibility", 'hidden');
self.vis.selectAll(selector).selectAll(" .legend").attr("visibility", 'hidden');
},
/**
* Shows the elements on the graphic that match the selector.
* Check the CSS3 selectors documentation to build a selector string
*
* @param {string} selector a string to represent a set of elements. Check the CSS3 selectors documentation to build a selector string
*
* @example
* instance.show('[id *="node-p1"]');
*/
show: function(selector){
var self=this;
self.vis.selectAll(selector).attr("visibility", 'visible');
self.vis.selectAll(selector).selectAll(" .legend").attr("visibility",function(d) { return (d.showLegend)?"visible":"hidden";});
},
/**
* Highlight the elements on the graphic that match the selector.
* Check the CSS3 selectors documentation to build a selector string
*
* @param {string} selector a string to represent a set of elements. Check the CSS3 selectors documentation to build a selector string
*
* @example
* instance.highlight(".figure");
*/
highlight: function(selector){
var self=this;
self.vis.selectAll(selector).style("stroke", '#0f0');
},
/**
* Set the fill's color of the elements on the graphic that match the selector.
* Check the CSS3 selectors documentation to build a selector string
*
* @param {string} selector a string to represent a set of elements. Check the CSS3 selectors documentation to build a selector string
* @param {string} color a color in web format eg. #FF0000
*
* @example
* instance.setFillColor(".figure","#FF0000");
*/
setFillColor: function(selector,color){
var self=this;
self.vis.selectAll(selector).style("fill", color);
},
/**
* Set the stroke's color of the elements on the graphic that match the selector.
* Check the CSS3 selectors documentation to build a selector string
*
* @param {string} selector a string to represent a set of elements. Check the CSS3 selectors documentation to build a selector string
* @param {string} color a color in web format eg. #FF0000
*
* @example
* instance.setColor(".figure","#FF0000");
*/
setColor: function(selector,color){
var self=this;
self.vis.selectAll(selector).style("stroke", color);
},
/**
* Shows/Hide the legend(id) of the protein
*
* @param {string} protein the id of the protein to swap the visibility of the legend
*
* @example
* instance.swapShowLegend("#node-p"+(pid-1)+" .legend");
*/
showLegend: function(selector,typeLegend){
var self=this;
self.vis.selectAll(selector).selectAll(".legend").attr("visibility", "visible").text(function(d) {
d.typeLegend=typeLegend;
if (d.typeLegend=="id")
return d.id;
// else if (d.typeLegend.indexOf("features.")==0)
// return d.features[d.typeLegend.substr(9)];
else
return d.features[d.typeLegend];
});
},
/**
* Scales the area of a protein
*
* @param {string} protein the id of the protein to scale
* @param {integer} scale value to scale a node
*
* @example
* instance.setSizeScale("#figure_p188",4);
*/
setSizeScale: function(selector,scale){
var self=this;
self.vis.selectAll(selector).attr("r", function(d) {
d.size=scale;
return self.opt.radius*Math.sqrt(d.size);
});
},
/**
* Scales the size of the proteins which value has been modify by other means
*
* @param {string} selector a CSS3 selector to choose the nodes to resize
*
* @example
* var j=0;
* for (var i in instance.proteins)
* instance.proteins[i].size=1+(j++)%4;
* instance.refreshSizeScale(".figure");
*/
refreshSizeScale: function(selector){
var self=this;
self.vis.selectAll(selector).attr("r", function(d) {
return self.opt.radius*Math.sqrt(d.size);
});
},
/**
* Is the legend of the protein visible
*
* @param {string} selector a CSS3 selector to choose the legend
*
* @example
* alert(instance.isLegendVisible("#node_5 .legend"));
*/
isLegendVisible: function(selector){
var self=this;
return (self.vis.selectAll(selector).selectAll(".legend").attr("visibility")=="visible");
},
/**
* Shows/Hide the legend(id) of the protein
*
* @param {string} protein the id of the protein to swap the visibility of the legend
*
* @example
* instance.swapShowLegend("#node-p"+(pid-1)+" .legend");
*/
hideLegend: function(selector){
var self=this;
self.vis.selectAll(selector).selectAll(".legend").attr("visibility", "hidden");
},
/**
* Shows/Hide the legend(id) of the protein
*
* @param {string} protein the id of the protein to swap the visibility of the legend
*
* @example
* instance.swapShowLegend("#node-p"+(pid-1)+" .legend");
*/
swapShowLegend: function(selector){
var self=this;
self.vis.selectAll(selector).selectAll(".legend").attr("visibility", function(d) {
d.showLegend = !d.showLegend;
return (d.showLegend)?"visible":"hidden";
});
},
/**
*
* Resizing the graph depending on the size of the window.
*
* @param self
*/
_resize: function (self) {
var width = window.innerWidth, height = window.innerHeight;
self.vis.attr("width", width).attr("height", height);
self.force.size([width, height]).resume();
},
colors: [ "#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c", "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5", "#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f", "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5",
"#0077b4", "#11c7e8", "#227f0e", "#33bb78", "#44a02c", "#55df8a", "#662728", "#779896", "#8867bd", "#99b0d5", "#AA564b", "#BB9c94", "#CC77c2", "#DDb6d2", "#EE7f7f", "#FFc7c7", "#00bd22", "#11db8d", "#22becf", "#33dae5",
"#1f00b4", "#ae11e8", "#ff220e", "#ff3378", "#2c442c", "#98558a", "#d66628", "#ff7796", "#9488bd", "#c599d5", "#8cAA4b", "#c4BB94", "#e3CCc2", "#f7DDd2", "#7fEE7f", "#c7FFc7", "#bc0022", "#db118d", "#1722cf", "#9e33e5",
"#1f7700", "#aec711", "#ff7f22", "#ffbb33", "#2ca044", "#98df55", "#d62766", "#ff9877", "#946788", "#c5b099", "#8c56AA", "#c49cBB", "#e377FC", "#f7b6FD", "#7f7fEE", "#c7c7FF", "#bcbd00", "#dbdb11", "#17be22", "#9eda33"
]
});