Commit e35f5c06 authored by Bertrand  NÉRON's avatar Bertrand NÉRON
Browse files

provide a schema of the genome whith the genes and their respective label.
and some controls 
 - left/right translation with a control panel
 - left/right by grabbing the paper
 - zoom in/out  with a control panel
 - zoom in/out with the mouswheel up/down
 
resize the view when the widow is resized

color each gene according to the "gene match" the gene match color chart is defined in color.css ( issue #872 )
constraint translation on Xaxis only ( issue #868 )
parent 915fbdcb
......@@ -6,5 +6,6 @@
// ".*\\.bak$"
"\\.project" ,
"\\.couchapprc",
".*\\.swp$"
".*\\.swp$",
"\\.svn"
]
/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
* Licensed under the MIT License (LICENSE.txt).
*
* Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
* Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
* Thanks to: Seamus Leahy for adding deltaX and deltaY
*
* Version: 3.0.6
*
* Requires: 1.2.2+
*/
(function($) {
var types = ['DOMMouseScroll', 'mousewheel'];
if ($.event.fixHooks) {
for ( var i=types.length; i; ) {
$.event.fixHooks[ types[--i] ] = $.event.mouseHooks;
}
}
$.event.special.mousewheel = {
setup: function() {
if ( this.addEventListener ) {
for ( var i=types.length; i; ) {
this.addEventListener( types[--i], handler, false );
}
} else {
this.onmousewheel = handler;
}
},
teardown: function() {
if ( this.removeEventListener ) {
for ( var i=types.length; i; ) {
this.removeEventListener( types[--i], handler, false );
}
} else {
this.onmousewheel = null;
}
}
};
$.fn.extend({
mousewheel: function(fn) {
return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
},
unmousewheel: function(fn) {
return this.unbind("mousewheel", fn);
}
});
function handler(event) {
var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0;
event = $.event.fix(orgEvent);
event.type = "mousewheel";
// Old school scrollwheel delta
if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta/120; }
if ( orgEvent.detail ) { delta = -orgEvent.detail/3; }
// New school multidimensional scroll (touchpads) deltas
deltaY = delta;
// Gecko
if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
deltaY = 0;
deltaX = -1*delta;
}
// Webkit
if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; }
if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; }
// Add event and delta to the front of the arguments
args.unshift(event, delta, deltaX, deltaY);
return ($.event.dispatch || $.event.handle).apply(this, args);
}
})(jQuery);
.gene_sctC { background-color: blue}
.gene_sctD { background-color: yellow}
.gene_sctF { background-color: red}
.gene_sctI { background-color: green}
.gene_sctJ { background-color: orange}
.gene_sctL { background-color: pink}
\ No newline at end of file
.gene_sctC { background-color: BlueViolet }
.gene_sctD { background-color: Blue}
.gene_sctD2{ background-color: DarkCyan}
.gene_sctF { background-color: Cyan}
.gene_sctI { background-color: Aqua}
.gene_sctJ { background-color: DarkGreen}
.gene_sctL { background-color: Green}
.gene_sctN { background-color: ForestGreen}
.gene_sctO { background-color: LimeGreen}
.gene_sctQ { background-color: GreenYellow}
.gene_sctR { background-color: YellowGreen}
.gene_sctS { background-color: Yellow}
.gene_sctT { background-color: Gold}
.gene_sctU { background-color: GoldenRod}
.gene_sctV { background-color: Orange}
.gene_sycD { background-color: DarkOrange}
.gene_sycN { background-color: OrangeRed}
.gene_yopB { background-color: Red}
.gene_yopD { background-color: FireBrick}
.gene_yopN { background-color: Maroon}
\ No newline at end of file
......@@ -46,6 +46,17 @@ td{
margin: 0;
}
#genes_schema{
width: 1820px;
border:1px solid black;
padding:0;
margin-right:10px;
margin-left:10px;
}
body {cursor: default;}
.grabbing{
cursor: url("../images/closedhand.cur") , default !important;
}
.grabbable{
cursor: url("../images/openhand.cur") , default !important;
}
......@@ -4,163 +4,226 @@
<title>secretion system {{code}}</title>
<link rel="stylesheet" href="../../style/main.css" type="text/css">
<link rel="stylesheet" href="../../style/color.css" type="text/css">
<script src="/_utils/script/jquery.js" type="text/javascript"></script>
<script src="/_utils/script/jquery.couch.js" type="text/javascript"></script>
<script src="../../script/jquery.mousewheel.js" type="text/javascript"></script>
<script src="../../script/raphael-min.js" type="text/javascript"></script>
<script src="../../script/popup.js" type="text/javascript"></script>
<script type="text/javascript">
function getdoc( docID ){
var dbname = document.location.href.split('/')[3];
$.couch.db(dbname).openDoc( docID, {
success:function( doc ) {
var min = doc.genes[0].begin ;
var max = 0;
for( var i = 0 ;i<doc.genes.length ; i++ ){
var beg = doc.genes[i].begin ;
var end = doc.genes[i].end ;
if(beg<min){min = beg;}
if(end>max){max = end;}
}
//var width = $("#genes_schema").attr("width");
//console.log(["width", width] );
var paper_l = $("#genes_schema").width();
var paper_h = 250;
var genome_offset = 45;
var genes_offset= 10;
var coef = ( paper_l - (genome_offset+genes_offset)*2 ) / ( max - min );
var genome_orig = min;
var Y_genome = 55 ;
Raphael.fn.draw_genome = function(){
var genome_l = paper_l -(2* genome_offset);
return this.path( ["M", genome_offset , Y_genome, "h", genome_l ,"a25,5 -1 0,1 0,5h",(-1*(genome_l)),"a25,5 0 0,1 0,-5z" ]).attr({fill: "#aaa", stroke:"#aaa", "stroke-width":"1"} );
};
var Gene = function Gene( gene_info ){
var g_arrow = paper.draw_gene(gene_info);
this.arrow = g_arrow[0];
this.popup = paper.draw_gene_popup( g_arrow[1] , g_arrow[2] , gene_info);
this.arrow.mouseover( show.bind(this));
this.arrow.mouseout( hide.bind(this) );
this.zoom = zoom;
this.translate = translate;
};
Raphael.fn.draw_gene_popup = function( start, stop, gene_info ){
var popup = this.set()
var label = this.set();
var txt = {font: '12px Helvetica, Arial', fill: "#fff"};
var title = {font: '12px Helvetica, Arial', fill: "#aaf"};
label.push(this.text(60, 12, "gene id: "+gene_info.id ).attr(title));
label.push(this.text(60, 27, "begin: "+gene_info.begin ).attr(txt));
label.push(this.text(60, 42, "end: " +gene_info.end ).attr(txt));
label.hide();
popup.push( label );
var frame = this.popup( start +( (stop -start)/2 ) , 100, label , "bottom").attr({fill: "#000", stroke: "#666", "stroke-width": 2, "fill-opacity": .7});
frame.hide();
popup.push( frame );
return popup;
};
Raphael.fn.draw_gene = function( gene_info ){
var arrow_beg = Math.round((gene_info.begin - genome_orig)*coef)+genome_offset+genes_offset;
var arrow_end = Math.round((gene_info.end - genome_orig)*coef)+genome_offset+genes_offset;
var bd_l = Math.round((arrow_end - arrow_beg)*3/5);
var hd_l = Math.round((arrow_end - arrow_beg)*2/5);
var arrow ;
if( gene_info.strand =='D' ){
arrow = this.path( ["M", arrow_beg, Y_genome-28, "m0 20h", bd_l, "v-20l", hd_l, " 30l", (-1*hd_l),"30v-20h",(-1*bd_l),"z"]).attr({fill: "#00f", stroke: "none", "stroke-dasharray": "-", "fill-opacity": 0.9});
}else{
arrow = this.path( ["M", arrow_beg, Y_genome-28, "m0 30l",hd_l, "-30v20h", bd_l, "v20h", (-1*bd_l),"v20z"]).attr({fill: "#0f0", stroke: "none", "stroke-dasharray": "-", "fill-opacity": 0.9});
}
return [arrow , arrow_beg ,arrow_end ];
};
success:function( doc ) {
var min = doc.genes[0].begin ;
var max = 0;
for( var i = 0 ;i<doc.genes.length ; i++ ){
var beg = doc.genes[i].begin ;
var end = doc.genes[i].end ;
if(beg<min){min = beg;}
if(end>max){max = end;}
}
var paper_w= $("#genes_schema").width();
var paper_h= 250;
var genome_offset= 45;
var genes_offset= 10;
var coef= (paper_w - (genome_offset+genes_offset)*2 )/(max - min);
var genome_orig= min;
var Y_genome= 55 ;
Raphael.fn.draw_genome = function(){
var genome_l = paper_w -(2* genome_offset);
return this.path( ["M", genome_offset , Y_genome, "h", genome_l ,"a25,5 -1 0,1 0,5h",(-1*(genome_l)),"a25,5 0 0,1 0,-5z" ]).attr({fill: "#aaa", stroke:"#aaa", "stroke-width":"1"} );
};
var Gene = function Gene( gene_info ){
var g_arrow = paper.draw_gene(gene_info);
this.arrow = g_arrow[0];
this.popup = paper.draw_gene_popup( g_arrow[1] , g_arrow[2] , gene_info);
this.arrow.mouseover( gene_show.bind(this));
this.arrow.mouseout( gene_hide.bind(this) );
this.zoom = gene_zoom;
this.translate = gene_translate;
};
Raphael.fn.draw_gene_popup = function( start, stop, gene_info ){
var popup = this.set();
var label = this.set();
var txt = {font: '12px Helvetica, Arial', fill: "#fff"};
var title = {font: '12px Helvetica, Arial', fill: "#aaf"};
label.push(this.text(60, 12, "gene id: "+gene_info.id ).attr(title));
label.push(this.text(60, 27, "begin: "+gene_info.begin ).attr(txt));
label.push(this.text(60, 42, "end: "+gene_info.end ).attr(txt));
label.hide();
popup.push( label );
var frame = this.popup( start +( (stop -start)/2 ) , 100, label , "bottom").attr({fill: "#000", stroke: "#666", "stroke-width": 2, "fill-opacity": .7});
frame.hide();
popup.push( frame );
return popup;
};
Raphael.fn.draw_gene = function( gene_info ){
var arrow_beg = Math.round((gene_info.begin - genome_orig)*coef)+genome_offset+genes_offset;
var arrow_end = Math.round((gene_info.end - genome_orig)*coef)+genome_offset+genes_offset;
var bd_l = Math.round((arrow_end - arrow_beg)*3/5);
var hd_l = Math.round((arrow_end - arrow_beg)*2/5);
var arrow ;
if( gene_info.strand =='D' ){
arrow = this.path( ["M", arrow_beg, Y_genome-28, "m0 20h", bd_l, "v-20l", hd_l, " 30l", (-1*hd_l),"30v-20h",(-1*bd_l),"z"]);
}else{
arrow = this.path( ["M", arrow_beg, Y_genome-28, "m0 30l",hd_l, "-30v20h", bd_l, "v20h", (-1*bd_l),"v20z"]);
}
if(!gene_info.match){
arrow.attr({fill: "white", stroke: "black", "stroke-dasharray": "-", "fill-opacity": 0.5});
}else{
var color=$( ".gene_"+gene_info.match).css( "backgroundColor" );
arrow.attr({fill: color, stroke: "none", "stroke-dasharray": "-", "fill-opacity": 0.9});
}
return [arrow , arrow_beg ,arrow_end ];
};
function gene_zoom( factor , ori ){
var bf_box = this.arrow.getBBox();
this.arrow.scale( factor, 1 , ori ,Y_genome );
var af_box = this.arrow.getBBox();
this.popup.translate( (af_box.x+(af_box.width/2 )) - (bf_box.x+(bf_box.width /2 )) , 0);
};
function gene_translate( dx , dy ){
var bf_box = this.arrow.getBBox(false);
this.arrow.translate( dx , dy );
var af_box = this.arrow.getBBox(false);
this.popup.translate((af_box.x + (af_box.width /2 )) - (bf_box.x + (bf_box.width /2 )) , (af_box.y-bf_box.y));
};
function gene_show(){
this.popup.show();
};
function gene_hide(){
this.popup.hide();
};
Raphael.fn.control = function( x , y , genes , genome ){
var west= this.path( ["M", x-40, y]+ "l20 -12 a70, 40 0 0,0 0, 24z").attr({fill:"blue"});//West
west.mousedown( function(){
for(var i = 0 ;i<genes.length ; i++){ genes[i].translate( -50 , 0); }
genome.translate( -50 , 0);
});
var east = this.path( ["M", x+40, y]+ "l-20 -12 a70, 40 0 0,1 0, 24z").attr({fill:"blue"});//East
east.mousedown( function(){
for(var i=0;i<genes.length; i++){ genes[i].translate(+50, 0);}
genome.translate(+50, 0);
});
this.circle( x , y , 20).attr({stroke:"black", "stroke-width": 2});
var genome_box= genome.getBBox();
var Xori_scale= genome_box.x+genome_box.width /2 ;
var zoom_in = this.set();
zoom_in.push(this.circle( x , y+9 , 8).attr({fill:"blue"}));//plus
zoom_in.push(this.rect( x-4 , y+7.5 , 8 ,3 ).attr({fill:"white", stroke:"white"}));//plus
zoom_in.push(this.rect( x-1.5 , y+5 , 3 ,8 ).attr({fill:"white", stroke:"white" }));//plus
zoom_in.mousedown( function(){
for(var i= 0 ;i<genes.length ; i++){
var g= genes[i] ;
genes[i].zoom(1.25 , Xori_scale);
}
genome.scale(1.25 ,1,Xori_scale ,Y_genome )
});
function zoom( factor , ori ){
var bf_box = this.arrow.getBBox();
this.arrow.scale( factor, 1 , ori ,Y_genome );
var af_box = this.arrow.getBBox();
this.popup.translate( (af_box.x + (af_box.width /2 )) - (bf_box.x + (bf_box.width /2 )) , 0);
};
function translate( dx , dy ){
var bf_box = this.arrow.getBBox(false);
this.arrow.translate( dx , dy );
var af_box = this.arrow.getBBox(false);
this.popup.translate( (af_box.x + (af_box.width /2 )) - (bf_box.x + (bf_box.width /2 )) , (af_box.y-bf_box.y));
};
function show(){
this.popup.show();
};
function hide(){
this.popup.hide();
};
Raphael.fn.control = function( x , y , genes , genome ){
this.circle( x , y , 42).attr({ fill:"white" ,"fill-opacity": 0.75 });
north = this.path( ["M", x, y-40 ]+ "l12 20 a40, 70 0 0,0 -24, 0z").attr({fill:"blue"});//North
north.mousedown( function(){
for(var i = 0 ;i<genes.length ; i++){ genes[i].translate( 0 , -20);}
genome.translate( 0 , -20);
});
var west= this.path( ["M", x-40, y]+ "l20 -12 a70, 40 0 0,0 0, 24z").attr({fill:"blue"});//West
west.mousedown( function(){
for(var i = 0 ;i<genes.length ; i++){ genes[i].translate( -50 , 0); }
genome.translate( -50 , 0);
});
var south = this.path( ["M", x, y+40]+ "l12 -20 a40, 70 0 0,1 -24, 0z").attr({fill:"blue"});//South
south.mousedown( function(){
for(var i = 0 ;i<genes.length ; i++){ genes[i].translate( 0 , +20);}
genome.translate( 0 , +20);
});
var east = this.path( ["M", x+40, y]+ "l-20 -12 a70, 40 0 0,1 0, 24z").attr({fill:"blue"});//East
east.mousedown( function(){
for(var i = 0 ;i<genes.length ; i++){ genes[i].translate( +50 , 0);}
genome.translate( +50 , 0);
});
this.circle( x , y , 20).attr({stroke:"black", "stroke-width": 2});
var genome_box = genome.getBBox();
var Xori_scale = genome_box.x + genome_box.width /2 ;
var zoom_in = this.set();
zoom_in.push( this.circle( x , y+9 , 8).attr({fill:"blue"}));//plus
zoom_in.push(this.rect( x-4 , y+7.5 , 8 ,3 ).attr({fill:"white", stroke:"white"}));//plus
zoom_in.push(this.rect( x-1.5 , y+5 , 3 ,8 ).attr({fill:"white", stroke:"white" }));
zoom_in.mousedown( function(){
for(var i = 0 ;i<genes.length ; i++){
var g = genes[i] ;
genes[i].zoom(1.25 , Xori_scale); }
genome.scale( 1.25 ,1,Xori_scale ,Y_genome )
});
var zoom_out = this.set();
zoom_out.push(this.circle( x , y-9 , 8).attr({fill:"blue"}));//moins
zoom_out.push(this.rect( x-4 , y-10.5 , 8 ,3 ).attr({fill:"white", stroke:"white"}));//moins
zoom_out.mousedown( function(){
for(var i = 0 ;i<genes.length ; i++){ genes[i].zoom( 0.8 , Xori_scale); }
genome.scale( 0.8 ,1,Xori_scale ,Y_genome );
})
};
var paper = Raphael("genes_schema", paper_l, paper_h );
var genome = paper.draw_genome();
var genes = new Array();
for(var i = 0 ;i<doc.genes.length ; i++){
var g = new Gene( doc.genes[i] ) ;
genes.push(g);
};
var genome_box = genome.getBBox();
var Xori_scale = genome_box.x + genome_box.width /2 ;
for(var i = 0 ;i<doc.genes.length ; i++){
for(var i = 0 ;i<genes.length ; i++){ genes[i].zoom( 1.01 , Xori_scale); }
};
ctr = paper.control( 50 , paper_h-50 , genes , genome );
},
var zoom_out = this.set();
zoom_out.push(this.circle( x , y-9 , 8).attr({fill:"blue"}));//moins
zoom_out.push(this.rect( x-4 , y-10.5 , 8 ,3 ).attr({fill:"white", stroke:"white"}));//moins
zoom_out.mousedown( function(){
for(var i = 0 ;i<genes.length ; i++){
genes[i].zoom( 0.8 , Xori_scale);
}
genome.scale( 0.8 ,1,Xori_scale ,Y_genome );
});
};
var paper = Raphael("genes_schema", paper_w, paper_h );
var background = paper.rect( 0 , 0 , paper_w , paper_h).attr( {stroke:"none", fill:"white"});//pour recevoir les evts
var genesNgenome= paper.set();
var genome= paper.draw_genome();//bar grise
genesNgenome.push( genome );
var genes = new Array();
for(var i = 0 ;i<doc.genes.length ; i++){
var g = new Gene( doc.genes[i] ) ;//fleche+popup
genes.push(g);
genesNgenome.push(g.arrow , g.popup);
};
var genome_box = genome.getBBox();
var Xori4scale = genome_box.x + genome_box.width /2 ;
for(var i = 0 ;i<doc.genes.length ; i++){
for(var i = 0 ;i<genes.length ; i++){ genes[i].zoom( 1.01 , Xori4scale); }
};
ctrl_panel = paper.control( 50 , paper_h-30 , genes , genome );
var curr_paper_width = $("#genes_schema").width();
$(window).bind("resize" , function(Evt){
console.log( "resize");
var gs = $("#genes_schema")
var new_width = gs.width();
paper.setSize( gs.width() , paper_h);
var scale_factor = (new_width -2* genome_offset)/(curr_paper_width -2* genome_offset);
var Xori4scale = genome_offset;
genome.scale( scale_factor, 1 , Xori4scale ,Y_genome );
for(var i= 0 ;i<genes.length ; i++){ genes[i].zoom( scale_factor , Xori4scale); }
background.scale( scale_factor,1,0,0 );
curr_paper_width= new_width;
});
var intOverallDelta= 0 ;
$("#genes_schema").mousewheel(function(objEvent, intDelta){
objEvent.stopImmediatePropagation();
var x = objEvent.pageX;
if (intDelta > 0){
intOverallDelta++;
genome.scale( 1.25, 1 , objEvent.pageX ,Y_genome );
for(var i = 0 ;i<genes.length ; i++){ genes[i].zoom( 1.25 , objEvent.pageX); }
}
else if (intDelta < 0){
intOverallDelta--;
genome.scale( 0.8, 1 , objEvent.pageX ,Y_genome );
for(var i=0 ;i<genes.length ; i++){ genes[i].zoom( 0.8 , objEvent.pageX); }
}
return false;//prevent to scroll the window
});
var drag_mousedown= function(x ,y,event) {
this.ox = event.screenX;
this.oy = event.screenY;
this.attr({
opacity: .5
});
};
var drag_mousemove= function(dx, dy,x ,y ,event) {
for(var i = 0 ;i<genes.length ; i++){ genes[i].translate(event.screenX - this.ox , 0); }
genome.translate( event.screenX - this.ox, 0);
this.ox = event.screenX;
this.oy = event.screenY;
};
var drag_mouseup= function(x,y,event){
dragging = false;
this.attr({
opacity: 1
});
};
genesNgenome.drag( drag_mousemove, drag_mousedown, drag_mouseup, genesNgenome, genesNgenome, genesNgenome );
background.drag( drag_mousemove, drag_mousedown, drag_mouseup, genesNgenome, genesNgenome, genesNgenome );
$("#genes_schema").bind("mousedown" , function( evt ){
$(this).toggleClass( "grabbing" ).toggleClass( "grabbable" );
});
$("#genes_schema").bind("mouseup" , function(){
$(this).toggleClass( "grabbable" ).toggleClass( "grabbing" );
});
},
error: function(status) { console.log(status); }
});
};
$(document).ready( getdoc( "{{code}}"));
</script>
</head>
......@@ -180,8 +243,7 @@
<li>taxonomy: {{taxonomy}}</li>
<li>type: {{type}}</li> {{/replicon}}
</ul>
<div id="genes_schema"></div>
<p id="test"></p>
<div id="genes_schema" class="grabbable"></div>
<h3>Genes</h3>
<table>
<thead>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment