ideogram
Version:
Chromosome visualization with D3.js
69 lines (68 loc) • 28.8 kB
JavaScript
var Ideogram=function(d){this.config=JSON.parse(JSON.stringify(d));this.debug=!1;this.config.bandDir||(this.config.bandDir="../data/bands/");if(!this.config.container){var f="body";this.config.container=f}this.config.resolution||(this.config.resolution=850);!1==="showChromosomeLabels"in this.config&&(this.config.showChromosomeLabels=!0);this.config.chrMargin||(this.config.chrMargin=10);if(!this.config.orientation){var b="vertical";this.config.orientation=b}this.config.chrWidth||(this.config.chrWidth=
10);if(!this.config.chrHeight){var a=document.querySelector(f).getBoundingClientRect(),b="vertical"===b?a.height:a.width;"body"==f&&(b=500);this.config.chrHeight=b}this.config.showBandLabels||(this.config.showBandLabels=!1);this.config.brush||(this.config.brush=!1);this.config.rows||(this.config.rows=1);!1==="chrHeight"in d&&(d.chrHeight=500);this.bump=Math.round(d.chrHeight/125);this.adjustedBump=!1;200>d.chrHeight&&(this.adjustedBump=!0,this.bump=4);d.showBandLabels&&(this.config.chrMargin+=20);
this.initAnnotSettings();this.config.chrMargin=this.config.chrMargin+this.config.chrWidth+2*this.config.annotTracksHeight;d.onLoad&&(this.onLoadCallback=d.onLoad);d.onDrawAnnots&&(this.onDrawAnnotsCallback=d.onDrawAnnots);d.onBrushMove&&(this.onBrushMoveCallback=d.onBrushMove);this.coordinateSystem="iscn";this.maxLength={bp:0,iscn:0};this.organisms={9606:{commonName:"Human",scientificName:"Homo sapiens",scientificNameAbbr:"H. sapiens",assemblies:{"default":"GCF_000001305.14",GRCh38:"GCF_000001305.14",
GRCh37:"GCF_000001305.13"}},10090:{commonName:"Mouse",scientificName:"Mus musculus",scientificNameAbbr:"M. musculus",assemblies:{"default":"GCF_000000055.19"}},7227:{commonName:"Fly",scientificName:"Drosophlia melanogaster",scientificNameAbbr:"D. melanogaster"}};!this.config.annotationsPath&&!this.config.annotations||this.config.annotationHeight||(this.config.annotationHeight=3);this.chromosomesArray=[];this.bandsToShow=[];this.chromosomes={};this.numChromosomes=0;this.bandData={};this.init()};
Ideogram.prototype.getBands=function(d,f,b){var a={},c,h,k,g,l,e,m;"chrBands"===d.slice(0,8)&&(h="native");"undefined"===typeof chrBands&&"native"!==h?(c=/\t/,d=d.split(/\r\n|\n/),l=1):(c=/ /,d="native"===h?eval(d):d,l=0);e=d[0].split(c)[0];h="#chromosome"==e?"ncbi":"#chrom"==e?"ucsc":"native";e=d.length;if("ncbi"===h||"native"===h)for(;l<e;l++){if(h=d[l].split(c),g=h[0],"undefined"===typeof b||-1!==b.indexOf(g))!1===g in a&&(a[g]=[]),k=h[7],h[8]&&(k+=h[8]),h={chr:g,bp:{start:parseInt(h[5],10),stop:parseInt(h[6],
10)},iscn:{start:parseInt(h[3],10),stop:parseInt(h[4],10)},px:{start:-1,stop:-1,width:-1},name:h[1]+h[2],stain:k,taxid:f},a[g].push(h)}else if("ucsc"===h)for(;l<e;l++)h=d[l].split(c),h[0]==="chr"+chromosomeName&&(k=h[4],"n/a"===k&&(k="gpos100"),b=parseInt(h[1],10),m=parseInt(h[2],10),h={chr:h[0].split("chr")[1],bp:{start:b,stop:m},iscn:{start:b,stop:m},px:{start:-1,stop:-1,width:-1},name:h[3],stain:k,taxid:f},a[g].push(h));return a};
Ideogram.prototype.colorArms=function(d,f){var b=this;b.chromosomesArray.forEach(function(a,c){var h=a.bands,k=h[a.pcenIndex+1],g=a.id,l=b.config.chrMargin*(c+1),e=b.config.chrWidth;pcenStart=h[a.pcenIndex].px.start;qcenStop=k.px.stop;d3.select("#"+g).append("line").attr("x1",pcenStart).attr("y1",l+.2).attr("x2",pcenStart).attr("y2",l+e-.2).style("stroke",d);d3.select("#"+g).append("line").attr("x1",qcenStop).attr("y1",l+.2).attr("x2",qcenStop).attr("y2",l+e-.2).style("stroke",f);d3.selectAll("#"+
g+" .band").data(a.bands).style("fill",function(b,e){return e<=a.pcenIndex?d:f})});d3.selectAll(".p-ter.chromosomeBorder").style("fill",d);d3.selectAll(".q-ter.chromosomeBorder").style("fill",f)};
Ideogram.prototype.getChromosomeModel=function(d,f,b,a){var c={},h=this.config.chrHeight,k=this.maxLength,g,l;l=this.coordinateSystem;c.chrIndex=a;c.name=f;!0===this.config.fullChromosomeLabels&&(c.name=this.organisms[b].scientificNameAbbr+" chr"+c.name);c.id="chr"+f+"-"+b;c.length=d[d.length-1][l].stop;g=c.length;for(var e=a=0;e<d.length;e++)f=d[e],b=h*c.length/k[l]*(f[l].stop-f[l].start)/g,d[e].px={start:a,stop:a+b,width:b},a=d[e].px.stop,"acen"===f.stain&&"p"===f.name[0]&&(c.pcenIndex=e);c.width=
a;c.scale={};!0===this.config.multiorganism?(c.scale.bp=1,c.scale.iscn=h*g/k.bp):(c.scale.bp=h/k.bp,c.scale.iscn=h/k.iscn);c.bands=d;c.centromerePosition="";1==d[0].bp.stop-d[0].bp.start&&(c.centromerePosition="telocentric",c.bands=c.bands.slice(1));return c};
Ideogram.prototype.drawChromosomeLabels=function(d){var f,b;f=this;var a=f.config.chrMargin,c=f.config.chrWidth;d=f.chromosomesArray;b=c/2+a-8;"vertical"===f.config.orientation&&!0===f.config.showBandLabels&&(b=a+17);"vertical"===f.config.orientation?d3.selectAll(".chromosome").append("text").data(d).attr("class","chrLabel").attr("transform","rotate(-90)").attr("y",-16).each(function(d,k){var g,l;g=d.name.split(" ");var e=[];if(void 0!=g)for(e.push(g.slice(0,g.length-1).join(" ")),e.push(g[g.length-
1]),f.config.showBandLabels||(k+=1),g=a*k,g=-(g+b-c-2)+2*f.config.annotTracksHeight,k=0;k<e.length;k++)l="",0==k&&f.config.fullChromosomeLabels&&(l="italic"),d3.select(this).append("tspan").text(e[k]).attr("dy",k?"1.2em":0).attr("x",g).attr("text-anchor","middle").attr("class",l)}):d3.selectAll(".chromosome").append("text").data(d).attr("class","chrLabel").attr("x",-5).each(function(d,c){var g,l;g=d.name.split(" ");var e=[];if(void 0!=g)for(e.push(g.slice(0,g.length-1).join(" ")),e.push(g[g.length-
1]),g=a*c,g+=b,c=0;c<e.length;c++)l="",0==c&&f.config.fullChromosomeLabels&&(l="italic"),d3.select(this).append("tspan").text(e[c]).attr("dy",c?"1.2em":0).attr("y",g).attr("x",-8).attr("text-anchor","middle").attr("class",l)})};
Ideogram.prototype.drawBandLabels=function(d){var f,b,a,c;c=this;b=[];for(a in d)for(f in d[a])b.push(d[a][f]);var h={};for(d=chrIndex=0;d<b.length;d++){chrIndex+=1;chrModel=b[d];f=d3.select("#"+chrModel.id);var k=this.config.chrMargin*chrIndex,g;c=this;g=k;1==chrIndex&&"perspective"in this.config&&"comparative"==this.config.perspective&&(g+=18);h[chrModel.id]=[];f.selectAll("text").data(chrModel.bands).enter().append("g").attr("class",function(a,b){return"bandLabel bsbsl-"+b}).attr("transform",function(a){a=
c.round(-8+a.px.start+a.px.width/2);h[chrModel.id].push(a+13);return"translate("+a+","+(k-10)+")"}).append("text").text(function(a){return a.name});f.selectAll("line.bandLabelStalk").data(chrModel.bands).enter().append("g").attr("class",function(a,b){return"bandLabelStalk bsbsl-"+b}).attr("transform",function(a){return"translate("+c.round(a.px.start+a.px.width/2)+", "+g+")"}).append("line").attr("x1",0).attr("y1",0).attr("x2",0).attr("y2",-8)}for(d=0;d<b.length;d++){chrModel=b[d];var l=h[chrModel.id].length,
e;a=[];var m,n,p;for(f=e=0;f<l;f++)n=h[chrModel.id][f],!1===n<e+5?(a.push(f),m!==f&&(prevTextBoxLeft=h[chrModel.id][f],prevTextBoxWidth=36,p=prevTextBoxLeft+prevTextBoxWidth),n<p+5?(m=f,e=p):a.push(f)):(m=f,e=p);l=[];e=a.length;for(n=0;n<e;n++)f=a[n],l.push("#"+chrModel.id+" .bsbsl-"+f);this.bandsToShow=this.bandsToShow.concat(l)}};
Ideogram.prototype.rotateChromosomeLabels=function(d,f,b,a){var c,h,k,g,l,e,m,n;h=this.config.chrWidth;c=this.config.chrMargin*f;e=this.config.numAnnotTracks;k=this;"undefined"===typeof a||!a.hasOwnProperty("x")||1==a.x&&1==a.y?(g=-8,l=-16,a={x:1,y:1},m=""):(m="scale("+a.x+","+a.y+")",g=-6,l=""===a?-16:-14);"vertical"==b||""==b?d.selectAll("text.chrLabel").attr("transform",m).selectAll("tspan").attr("x",g).attr("y",function(a,c){var d=f-1;(1<e||""==b)&&--d;chrMargin2=-4;!0===k.config.showBandLabels&&
(chrMargin2=k.config.chrMargin+h+26);d*=k.config.chrMargin;0==1<e&&(d+=1);return d+chrMargin2}):(--f,chrMargin2=-h-2,!0===k.config.showBandLabels&&(chrMargin2=k.config.chrMargin+8),n=k.config.annotTracksHeight,"overlay"!==k.config.annotationsLayout&&(n*=2),d.selectAll("text.chrLabel").attr("transform","rotate(-90)"+m).selectAll("tspan").attr("x",function(b,e){c=k.config.chrMargin*f;g=-(c+chrMargin2)+3+n;return g/=a.x}).attr("y",l))};
Ideogram.prototype.rotateBandLabels=function(d,f,b){var a,c,h,k,g=this;k=d.selectAll(".bandLabel");a=this.config.chrMargin*f;h=d.attr("data-orientation");"undefined"==typeof b?(b={x:1,y:1},c=""):c="scale("+b.x+","+b.y+")";1==f&&"perspective"in this.config&&"comparative"==this.config.perspective?k.attr("transform",function(b){var e;e=8-a-26;b=g.round(2+b.px.start+b.px.width/2);return"rotate(-90)translate("+e+","+b+")"}).selectAll("text").attr("text-anchor","end"):"vertical"==h?k.attr("transform",function(b){var e;
e=8-a;b=g.round(2+b.px.start+b.px.width/2);return"rotate(-90)translate("+e+","+b+")"}).selectAll("text").attr("transform",c):(k.attr("transform",function(d){return"translate("+g.round(-8*b.x+d.px.start+d.px.width/2)+","+(a-10)+")"}).selectAll("text").attr("transform",c),d.selectAll(".bandLabelStalk line").attr("transform",c))};Ideogram.prototype.round=function(d){return Math.round(100*d)/100};
Ideogram.prototype.drawChromosome=function(d,f){var b,a,c,h,k,g,l,e;l=this;g=l.bump;k="telocentric"!=d.centromerePosition?g:Math.round(g/4)+3;b=d3.select("svg").append("g").attr("id",d.id).attr("class","chromosome");a=l.config.chrWidth;var m=l.config.chrMargin*f;b.selectAll("path").data(d.bands).enter().append("path").attr("id",function(a){a=a.name.replace(".","-");return d.id+"-"+a}).attr("class",function(a){var b="band "+a.stain;"acen"==a.stain&&(b+=" "+a.name[0]+"-cen");return b}).attr("d",function(b,
e){var c=l.round(b.px.width),f=l.round(b.px.start),h,n,q;q=0;"acen"==b.stain?(l.adjustedBump?(q=.35,c=.2,f-=.1,"q"===b.name[0]&&(f+=1.2)):c-=g/2,h=m+q,n=a/2-2*q,q=a-2*q,"p"==b.name[0]?b="M "+f+" "+h+" l "+c+" 0 q "+g+" "+n+" 0 "+q+" l -"+c+" 0 z":(l.adjustedBump&&(c+=.2),b="M "+(f+c+g/2)+" "+h+" l -"+c+" 0 q -"+(g+.5)+" "+n+" 0 "+q+" l "+c+" 0 z")):(0==e&&(f+=k-g/2,!0===l.config.multiorganism&&(f+=k)),l.adjustedBump&&"q"===b.name[0]&&(f+=1.8),e==d.bands.length-1&&(f-=k-g/2),b="M "+f+" "+m+" l "+c+
" 0 l 0 "+a+" l -"+c+" 0 z");return b});"telocentric"!=d.centromerePosition?b.append("path").attr("class","p-ter chromosomeBorder "+d.bands[0].stain).attr("d","M "+(k-g/2+.1)+" "+m+" q -"+k+" "+a/2+" 0 "+a):(b.append("path").attr("class","p-ter chromosomeBorder "+d.bands[0].stain).attr("d","M "+(k-3)+" "+m+" l -"+(k-2)+" 0 l 0 "+a+" l "+(k-2)+" 0 z"),b.insert("path",":first-child").attr("class","acen").attr("d","M "+(k-3)+" "+(m+.1*a)+" l "+(k+g/2+1)+" 0 l 0 "+.8*a+" l -"+(k+g/2+1)+" 0 z"));e=l.adjustedBump?
1.8:0;c=d.pcenIndex;var n=d.bands[c];h=d.bands[c+1];0<c?(c=n.px.start,h=h.px.stop+e):(c=2,h=document.querySelectorAll("#"+d.id+" .band")[0].getBBox().x);e=h+(d.width-h+1.3*e)-g/2-.5;b.append("line").attr("class","cb-p-arm-top chromosomeBorder").attr("x1",g/2).attr("y1",m).attr("x2",c).attr("y2",m);b.append("line").attr("class","cb-p-arm-bottom chromosomeBorder").attr("x1",g/2).attr("y1",a+m).attr("x2",c).attr("y2",a+m);b.append("line").attr("class","cb-q-arm-top chromosomeBorder").attr("x1",h).attr("y1",
m).attr("x2",e).attr("y2",m);b.append("line").attr("class","cb-q-arm-bottom chromosomeBorder").attr("x1",h).attr("y1",a+m).attr("x2",e).attr("y2",a+m);b.append("path").attr("class","q-ter chromosomeBorder "+d.bands[d.bands.length-1].stain).attr("d","M "+e+" "+m+" q "+g+" "+a/2+" 0 "+a)};
Ideogram.prototype.initTransformChromosome=function(d,f){if("vertical"==this.config.orientation){var b,a;a=this.config.chrWidth;b=this.config.chrMargin*f;this.config.showBandLabels||(f+=2);b+=(a-4)*(f-1);d.attr("data-orientation","vertical").attr("transform","rotate(90, "+(b-30)+", "+b+")");this.rotateBandLabels(d,f)}else d.attr("data-orientation","horizontal")};
Ideogram.prototype.rotateAndToggleDisplay=function(d){var f,b,a,c,h,k,g,l,e=this;f=d3.select("#"+d);b=e.chromosomes[e.config.taxid][d.split("-")[0].split("chr")[1]].chrIndex;otherChrs=d3.selectAll("g.chromosome").filter(function(a,b){return this.id!==d});g=e.config.orientation;l=f.attr("data-orientation");a=this.config.chrMargin*b;c=this.config.chrWidth;h=d3.select("#ideogram")[0][0].getBoundingClientRect();k=h.height;h=h.width;"vertical"==g?(chrLength=f[0][0].getBoundingClientRect().height,k=h/chrLength*
.97,scale="scale("+k+", 1.5)",inverseScaleX=2/k,inverseScaleY=1,this.config.showBandLabels||(b+=2),c=a+(c-4)*(b-1)-30,verticalTransform="rotate(90, "+c+", "+(c+30)+")",a=-1.5*(a-this.config.annotTracksHeight),this.config.showBandLabels&&(a+=25),horizontalTransform="rotate(0)translate(20, "+a+")"+scale):(chrLength=f[0][0].getBoundingClientRect().width,k=k/chrLength*.97,scale="scale("+k+", 1.5)",inverseScaleX=2/k,inverseScaleY=1,k=20,this.config.showBandLabels||(b+=2,k=15),c=a+(c-k)*(b-2),a=c+5,this.config.showBandLabels||
(c+=k,a+=k),verticalTransform="rotate(90, "+c+", "+a+")"+scale,horizontalTransform="");inverseScale="scale("+inverseScaleX+","+inverseScaleY+")";"vertical"!=l?("horizontal"==g&&otherChrs.style("display","none"),f.selectAll(".annot>path").attr("transform","vertical"==g?"":inverseScale),f.attr("data-orientation","vertical").transition().attr("transform",verticalTransform).each("end",function(){scale="vertical"==g?"":{x:inverseScaleY,y:inverseScaleX};e.rotateBandLabels(f,b,scale);e.rotateChromosomeLabels(f,
b,"horizontal",scale);"vertical"==g&&otherChrs.style("display","")})):(f.attr("data-orientation",""),"vertical"==g&&otherChrs.style("display","none"),f.selectAll(".annot>path").transition().attr("transform","vertical"==g?inverseScale:""),f.transition().attr("transform",horizontalTransform).each("end",function(){inverseScale="horizontal"==g?"vertical"==l?{x:1,y:1}:"":{x:inverseScaleX,y:inverseScaleY};e.rotateBandLabels(f,b,inverseScale);e.rotateChromosomeLabels(f,b,"",inverseScale);"horizontal"==g&&
otherChrs.style("display","")}))};Ideogram.prototype.convertBpToPx=function(d,f){var b,a;for(b=0;b<d.bands.length;b++)if(a=d.bands[b],f>=a.bp.start&&f<=a.bp.stop)return b=(a.iscn.stop-a.iscn.start)/(a.bp.stop-a.bp.start),b=a.iscn.start+(f-a.bp.start)*b,a=30+a.px.start+a.px.width*(b-a.iscn.start)/(a.iscn.stop-a.iscn.start);throw Error("Base pair out of range. bp: "+f+"; length of chr"+d.name+": "+a.bp.stop);};
Ideogram.prototype.convertPxToBp=function(d,f){var b,a;for(b=0;b<d.bands.length;b++)if(a=d.bands[b],f>=a.px.start&&f<=a.px.stop)return pxToIscnScale=(a.iscn.stop-a.iscn.start)/(a.px.stop-a.px.start),b=a.iscn.start+(f-a.px.start)*pxToIscnScale,bp=a.bp.start+(a.bp.stop-a.bp.start)*(b-a.iscn.start)/(a.iscn.stop-a.iscn.start),Math.round(bp);throw Error("Pixel out of range. px: "+bp+"; length of chr"+d.name+": "+a.px.stop);};
Ideogram.prototype.drawSynteny=function(d){var f=(new Date).getTime(),b,a,c,h,k,g,l,e,m;k=d3.select("svg").append("g").attr("class","synteny");for(g=0;g<d.length;g++)regions=d[g],b=regions.r1,a=regions.r2,l="#CFC","color"in regions&&(l=regions.color),e=1,"opacity"in regions&&(e=regions.opacity),b.startPx=this.convertBpToPx(b.chr,b.start),b.stopPx=this.convertBpToPx(b.chr,b.stop),a.startPx=this.convertBpToPx(a.chr,a.start),a.stopPx=this.convertBpToPx(a.chr,a.stop),c=document.querySelectorAll("#"+b.chr.id+
" path")[0].getBBox(),h=document.querySelectorAll("#"+a.chr.id+" path")[0].getBBox(),c=c.y-30,h=h.y-29,m=b.chr.id+"_"+b.start+"_"+b.stop+"___"+a.chr.id+"_"+a.start+"_"+a.stop,syntenicRegion=k.append("g").attr("class","syntenicRegion").attr("id",m).on("click",function(){var a=this,b=d3.selectAll(".syntenicRegion").filter(function(b,e){return this!==a});b.classed("hidden",!b.classed("hidden"))}).on("mouseover",function(){var a=this;d3.selectAll(".syntenicRegion").filter(function(b,e){return this!==
a}).classed("ghost",!0)}).on("mouseout",function(){d3.selectAll(".syntenicRegion").classed("ghost",!1)}),syntenicRegion.append("polygon").attr("points",c+", "+b.startPx+" "+c+", "+b.stopPx+" "+h+", "+a.stopPx+" "+h+", "+a.startPx).attr("style","fill: "+l+"; fill-opacity: "+e),syntenicRegion.append("line").attr("class","syntenyBorder").attr("x1",c).attr("x2",h).attr("y1",b.startPx).attr("y2",a.startPx),syntenicRegion.append("line").attr("class","syntenyBorder").attr("x1",c).attr("x2",h).attr("y1",
b.stopPx).attr("y2",a.stopPx);d=(new Date).getTime();this.debug&&console.log("Time in drawSyntenicRegions: "+(d-f)+" ms")};
Ideogram.prototype.initAnnotSettings=function(){this.config.annotationsPath||this.config.localAnnotationsPath||this.annots?(this.config.annotationHeight||(this.config.annotationHeight=3),this.config.numAnnotTracks=this.config.annotationTracks?this.config.annotationTracks.length:1,this.config.annotTracksHeight=this.config.annotationHeight*this.config.numAnnotTracks,"undefined"===typeof this.config.barWidth&&(this.config.barWidth=3)):this.config.annotTracksHeight=0;"undefined"===typeof this.config.annotationsColor&&
(this.config.annotationsColor="#F00")};
Ideogram.prototype.drawAnnots=function(d){var f,b,a,c=[],h;b=this.chromosomes[this.config.taxid];if("annots"in d[0])return this.drawProcessedAnnots(d);for(f in b)c.push({chr:f,annots:[]});for(f=0;f<d.length;f++)for(a=d[f],b=0;b<c.length;b++)if(a.chr===c[b].chr){h=[a.name,a.start,a.stop-a.start];"color"in a&&h.push(a.color);"shape"in a&&h.push(a.shape);c[b].annots.push(h);break}f=["name","start","length"];"color"in d[0]&&f.push("color");"shape"in d[0]&&f.push("shape");this.rawAnnots={keys:f,annots:c};
this.annots=this.processAnnotData(this.rawAnnots);this.drawProcessedAnnots(this.annots)};
Ideogram.prototype.processAnnotData=function(d){var f=d.keys;d=d.annots;var b,a,c,h,k,g,l,e,m;h=[];for(b=0;b<d.length;b++)for(k=d[b],h.push({chr:k.chr,annots:[]}),a=0;a<k.annots.length;a++){g=k.chr;e=k.annots[a];c={};for(m=0;m<f.length;m++)c[f[m]]=e[m];c.stop=c.start+c.length;l=this.chromosomes["9606"][g];m=this.convertBpToPx(l,c.start);l=this.convertBpToPx(l,c.stop);m=Math.round((m+l)/2)-28;l=this.config.annotationsColor;this.config.annotationTracks?(c.trackIndex=e[3],l=this.config.annotationTracks[c.trackIndex].color):
c.trackIndex=0;"color"in c&&(l=c.color);c.chr=g;c.chrIndex=b;c.px=m;c.color=l;h[b].annots.push(c)}return h};
Ideogram.prototype.getHistogramBars=function(d){var f=(new Date).getTime(),b,a,c,h,k,g,l,e,m,n,p=!1,r;e=[];g=this.config.barWidth;h=this.chromosomes[this.config.taxid];a=this.config.annotationsColor;r="histogramScaling"in this.config?this.config.histogramScaling:"relative";"undefined"===typeof this.maxAnnotsPerBar&&(this.maxAnnotsPerBar={},p=!0);for(c in h){chrModel=h[c];l=chrModel.chrIndex;lastBand=chrModel.bands[chrModel.bands.length-1];b=lastBand.px.stop;numBins=Math.round(b/g);m={chr:c,annots:[]};
for(b=0;b<numBins;b++)k=b*g-this.bump,bp=this.convertPxToBp(chrModel,k+this.bump),m.annots.push({bp:bp,px:k,count:0,chrIndex:l,chrName:c,color:a});e.push(m)}for(c in d)for(g=d[c].annots,b=d[c].chr,chrModel=h[b],l=chrModel.chrIndex,barAnnots=e[l-1].annots,b=0;b<g.length;b++)for(k=g[b],k=k.px,a=0;a<barAnnots.length-1;a++)if(m=barAnnots[a].px,n=barAnnots[a+1].px,k>m&&k<n){e[l-1].annots[a].count+=1;break}if(1==p||"relative"==r){for(b=h=0;b<e.length;b++)for(d=e[b].annots,a=0;a<d.length;a++)barCount=d[a].count,
barCount>h&&(h=barCount);this.maxAnnotsPerBar[c]=h}for(b=0;b<e.length;b++)for(d=e[b].annots,a=0;a<d.length;a++)barCount=d[a].count,height=barCount/this.maxAnnotsPerBar[c]*this.config.chrMargin,e[b].annots[a].height=height;d=(new Date).getTime();this.debug&&console.log("Time spent in getHistogramBars: "+(d-f)+" ms");return e};
Ideogram.prototype.drawProcessedAnnots=function(d){var f,b,a,c,h,k,g,l,e,m,n=this;f=this.config.chrMargin;b=this.config.chrWidth;a="tracks";this.config.annotationsLayout&&(a=this.config.annotationsLayout);"histogram"===a&&(d=n.getHistogramBars(d));c=n.config.annotationHeight;h="l -"+c+" "+2*c+" l "+2*c+" 0 z";k="m -"+c+", "+c+"a "+c+","+c+" 0 1,0 "+2*c+",0a "+c+","+c+" 0 1,0 -"+2*c+",0";d=d3.selectAll(".chromosome").data(d).selectAll("path.annot").data(function(a){return a.annots}).enter();"tracks"===
a?d.append("g").attr("id",function(a,b){return a.id}).attr("class","annot").attr("transform",function(a){return"translate("+a.px+","+((a.chrIndex+1)*f+b+a.trackIndex*c*2)+")"}).append("path").attr("d",function(a){if(!a.shape||"triangle"===a.shape)return"m0,0"+h;if("circle"===a.shape)return k}).attr("fill",function(a){return a.color}):"overlay"===a?d.append("polygon").attr("id",function(a,b){return a.id}).attr("class","annot").attr("points",function(a){g=a.px-.5;l=a.px+.5;e=(a.chrIndex+1)*f+b;m=(a.chrIndex+
1)*f;return g+","+e+" "+l+","+e+" "+l+","+m+" "+g+","+m}).attr("fill",function(a){return a.color}):"histogram"===a&&d.append("polygon").attr("class","annot").attr("points",function(a){g=a.px+n.bump;l=a.px+n.config.barWidth+n.bump;e=a.chrIndex*f+b;m=a.chrIndex*f+b+a.height;a=n.chromosomesArray[a.chrIndex-1].width;l>a&&(l=a);return g+","+e+" "+l+","+e+" "+l+","+m+" "+g+","+m}).attr("fill",function(a){return a.color});if(n.onDrawAnnotsCallback)n.onDrawAnnotsCallback()};
Ideogram.prototype.putChromosomesInRows=function(){var d=this.config.rows,f,b,a,c,h,k;f=Math.floor(this.numChromosomes/d);c=0;"g"!==d3.select("svg > *")[0][0].tagName&&(c=2);for(var g=1;g<d;g++)b=f*g+1+c,a=b+f,range="nth-child(n+"+b+"):nth-child(-n+"+a+")",h=this.config.chrHeight+20,b=b+1-c,a=this.config.chrWidth,k=this.config.chrMargin*b,this.config.showBandLabels||(b+=2),this.config.showChromosomeLabels&&(h+=12),rowWidth=k+(a-4)*b+8,d3.selectAll("#ideogram .chromosome:"+range).attr("transform",
function(a,b){return d3.select(this).attr("transform")+("translate("+h+", "+rowWidth+")")})};Ideogram.prototype.onBrushMove=function(){call(this.onBrushMoveCallback)};
Ideogram.prototype.createBrush=function(d,f){var b=this,a=b.config.chrWidth+6.5,c=b.chromosomesArray[0],h=c.bands[c.bands.length-1].bp.stop,k,g;g=[0];k=[0];for(var l,e=0;e<c.bands.length;e++)l=c.bands[e],g.push(l.bp.stop),k.push(l.px.stop);c=d3.scale.linear().domain(g).range(k);g=d3.select(".band")[0][0].getBBox().y-3.25;"undefined"===typeof d&&(d=Math.floor(h/10));"undefined"===typeof right&&(f=Math.ceil(2*d));h=d;k=f;b.selectedRegion={from:d,to:f,extent:f-d};b.brush=d3.svg.brush().x(c).extent([h,
k]).on("brush",function(){var a=b.brush.extent(),e=Math.floor(a[0]),a=Math.ceil(a[1]);b.selectedRegion={from:e,to:a,extent:a-e};if(b.onBrushMove)b.onBrushMoveCallback()});d3.select("#ideogram").append("g").attr("class","brush").attr("transform","translate(0, "+g+")").call(b.brush).selectAll("rect").attr("height",a)};Ideogram.prototype.onLoad=function(){call(this.onLoadCallback)};Ideogram.prototype.onDrawAnnots=function(){call(this.onDrawAnnotsCallback)};
Ideogram.prototype.getBandColorGradients=function(){var d,f,b,a,c,h="";d=[["gneg","#FFF","#FFF","#DDD"],["gpos25","#C8C8C8","#DDD","#BBB"],["gpos33","#BBB","#BBB","#AAA"],["gpos50","#999","#AAA","#888"],["gpos66","#888","#888","#666"],["gpos75","#777","#777","#444"],["gpos100","#444","#666","#000"],["acen","#FEE","#FEE","#FDD"]];for(var k=0;k<d.length;k++)f=d[k][0],b=d[k][1],a=d[k][2],c=d[k][3],h+='<linearGradient id="'+f+'" x1="0%" y1="0%" x2="0%" y2="100%">',h="gneg"==f?h+('<stop offset="70%" stop-color="'+
a+'" /><stop offset="95%" stop-color="'+c+'" /><stop offset="100%" stop-color="'+b+'" />'):h+('<stop offset="5%" stop-color="'+b+'" /><stop offset="15%" stop-color="'+a+'" /><stop offset="60%" stop-color="'+c+'" />'),h+="</linearGradient>";return h='<style>.gneg {fill: url("#gneg")} .gpos25 {fill: url("#gpos25")} .gpos33 {fill: url("#gpos33")} .gpos50 {fill: url("#gpos50")} .gpos66 {fill: url("#gpos66")} .gpos75 {fill: url("#gpos75")} .gpos100 {fill: url("#gpos100")} .acen {fill: url("#acen")} .stalk {fill: url("#stalk")} .gvar {fill: url("#gvar")} </style>'+
("<defs>"+(h+'<pattern id="stalk" width="2" height="1" patternUnits="userSpaceOnUse" patternTransform="rotate(30 0 0)"><rect x="0" y="0" width="10" height="2" fill="#CCE" /> <line x1="0" y1="0" x2="0" y2="100%" style="stroke:#88B; stroke-width:0.7;" /></pattern><pattern id="gvar" width="2" height="1" patternUnits="userSpaceOnUse" patternTransform="rotate(-30 0 0)"><rect x="0" y="0" width="10" height="2" fill="#DDF" /> <line x1="0" y1="0" x2="0" y2="100%" style="stroke:#99C; stroke-width:0.7;" /></pattern>')+
"</defs>")};
Ideogram.prototype.getTaxids=function(){var d,f,b,a,c,h,k,g;h="taxid"in this.config;this.config.multiorganism="organism"in this.config&&this.config.organism instanceof Array||h&&this.config.taxid instanceof Array;g=this.config.multiorganism;if("organism"in this.config){a=g?this.config.organism:[this.config.organism];f=[];k={};for(c=0;c<a.length;c++)for(d in b=a[c],this.organisms)this.organisms[d].commonName.toLowerCase()===b&&(f.push(d),g&&(k[d]=this.config.chromosomes[b]));this.config.taxids=f;g&&
(this.config.chromosomes=k)}g?(this.coordinateSystem="bp",h&&(f=this.config.taxid)):(h&&(f=[this.config.taxid]),this.config.taxids=f);return f};
Ideogram.prototype.initDrawChromosomes=function(d){var f=this.config.taxids,b,a=0,c,h,k,g,l;for(c=0;c<f.length;c++){b=f[c];k=this.config.chromosomes[b];this.chromosomes[b]={};for(h=0;h<k.length;h++)bands=d[a],a+=1,g=k[h],l=this.getChromosomeModel(bands,g,b,a),this.chromosomes[b][g]=l,this.chromosomesArray.push(l),this.drawChromosome(l,a);!0===this.config.showBandLabels&&this.drawBandLabels(this.chromosomes)}};
Ideogram.prototype.init=function(){function d(){e.config.annotationsPath&&d3.json(e.config.annotationsPath,function(a){e.rawAnnots=a});g="";e.config.showChromosomeLabels&&(g="horizontal"==e.config.orientation?g+"labeledLeft ":g+"labeled ");e.config.annotationsLayout&&"overlay"===e.config.annotationsLayout&&(g+="faint");var a;"vertical"===e.config.orientation?(a=e.config.chrHeight+30,1<e.config.rows&&(a=e.config.rows*(a-30))):a=e.config.chrMargin*e.numChromosomes+30;var c=e.getBandColorGradients();
d3.select(e.config.container).append("svg").attr("id","ideogram").attr("class",g).attr("width","97%").attr("height",a).html(c);b()}function f(){var a,b,c,d,f,h,g,l;n=[];if(!0===e.config.multiorganism)for(e.coordinateSystem="bp",h=e.config.taxids,k=0;k<h.length;k++);else"undefined"==typeof e.config.taxid&&(e.config.taxid=e.config.taxids[0]),d=e.config.taxid,h=[d],e.config.taxids=h;"chromosomes"in e.config&&(g=e.config.chromosomes);e.config.multiorganism&&(l=g);e.config.chromosomes={};var m=(new Date).getTime();
for(c=0;c<h.length;c++)for(d=h[c],f=e.bandData[d],e.config.multiorganism&&(g=l[d]),f=e.getBands(f,d,g),g=Object.keys(f),e.config.chromosomes[d]=g.slice(),e.numChromosomes+=e.config.chromosomes[d].length,d=0;d<g.length;d++)a=g[d],b=f[a],n.push(b),a=b[b.length-1].iscn.stop,b=b[b.length-1].bp.stop,a>e.maxLength.iscn&&(e.maxLength.iscn=a),b>e.maxLength.bp&&(e.maxLength.bp=b);c=(new Date).getTime();e.debug&&console.log("Time in processBandData: "+(c-m)+" ms")}function b(){try{var a=(new Date).getTime(),
b=0,d,f,g,k,p;e.initDrawChromosomes(n);for(k=b=0;k<h.length;k++)for(c=h[k],l=e.config.chromosomes[c],p=0;p<l.length;p++)b+=1,f=l[p],d=d3.select("#chr"+f+"-"+c),e.initTransformChromosome(d,b);if(e.config.annotationsPath){var r=function(){"undefined"!==typeof timeout&&window.clearTimeout(timeout);e.annots=e.processAnnotData(e.rawAnnots);e.drawProcessedAnnots(e.annots);e.initCrossFilter&&e.initCrossFilter()};e.rawAnnots?r():function v(){timeout=setTimeout(function(){e.rawAnnots?r():v()},50)}()}if(!0===
e.config.showBandLabels){var u=e.bandsToShow.join(","),w=(new Date).getTime();d3.selectAll(".bandLabel, .bandLabelStalk").style("display","none");d3.selectAll(u).style("display","");var x=(new Date).getTime();e.debug&&console.log("Time in showing bands: "+(x-w)+" ms");if("vertical"===e.config.orientation)for(g=0;g<e.chromosomesArray.length;g++)e.rotateChromosomeLabels(d3.select("#"+e.chromosomesArray[g].id),g)}!0===e.config.showChromosomeLabels&&e.drawChromosomeLabels(e.chromosomes);1<e.config.rows&&
e.putChromosomesInRows();!0===e.config.brush&&e.createBrush();e.config.annotations&&e.drawAnnots(e.config.annotations);if(e.config.armColors){var t=e.config.armColors;e.colorArms(t[0],t[1])}var y=(new Date).getTime();e.debug&&console.log("Time in drawChromosome: "+(y-a)+" ms");var z=(new Date).getTime();e.debug&&console.log("Time constructing ideogram: "+(z-m)+" ms");if(e.onLoadCallback)e.onLoadCallback();if(!("rotatable"in e.config&&!1===e.config.rotatable))d3.selectAll("g").on("click",function(){ideogram.rotateAndToggleDisplay(this.id)})}catch(A){console.log(A.stack)}}
var a,c,h,k,g,l,e=this,m=(new Date).getTime(),n=[],p=0,r=this.config.resolution;h=e.getTaxids();e.config.taxids=h;for(k=0;k<h.length;k++)c=h[k],e.config.assembly||(e.config.assembly="default"),a=e.organisms[c].assemblies[e.config.assembly],a={9606:"native/ideogram_9606_"+a+"_"+r+"_V1.js",10090:"native/ideogram_10090_"+a+"_NA_V2.js",7227:"ucsc/drosophila_melanogaster_dm6.tsv"},"undefined"===typeof chrBands?d3.xhr(e.config.bandDir+a[c]).on("beforesend",function(a){a.taxid=c}).get(function(a,b){e.bandData[b.taxid]=
b.response;p+=1;p==h.length&&(f(),d())}):(e.bandData[c]=chrBands,f(),d())};
//# sourceMappingURL=ideogram.js.map