// Universal Sequence Maps (hoding Object for CGR operations console.log('CGR toolbox :-)'); // Overloading String and Array - watch out! String.prototype.reverse=function(){ // sort characters of a string return this.split('').reverse().toString().replace(/,/g,''); } String.prototype.sort=function(){ // sort characters of a string return this.split('').sort().toString().replace(/,/g,''); } Array.prototype.max=function(){ // returns maximum value return this.reduce(function(x1,x2){if(x1>x2){return x1}else{return x2}}); } Array.prototype.min=function(){ // returns maximum value return this.reduce(function(x1,x2){if(x1 forward'); this.cgrLong(i,'cgrForward'); console.log((i*2+2)+'/'+(this.cube.length*2)+' mapping axis <'+this.cube[i]+'> backward'); this.cgrLong(i,'cgrBackward'); this.bin[i]=[]; // free memory } console.log('packing CGR coordinates ...') console.log('... forward ...') var c=[]; for(i=0;i')} this.bin[j]=this.seq.split('').map(function(si){ if (abc.match(new RegExp(si))){return 0} else {return 1} }) } break; //default : // this.alphabet } } this.cgr = function(bin,s,ith){ // CGR with recursive seed if (!ith){ith=0} var n = bin.length; if (!s){s=bin[bin.length-1]} // start seed with last value of bin var y=[]; y[0]=s+(bin[0]-s)/2; for(var i=1;i1){y[i]=1;x=x-1} else{y[i]=0} x = x*2;i++; } return y; } this.bin2int = function (B){//converts binary vector into integer return B.slice().reverse().map(function(x,i){return x*Math.pow(2,i)}).reduce(function(a,b){return a+b}); } this.decode = function(xy,n){// decode numerical coordinates var bin2int = this.bin2int; var decodeBin = this.decodeBin; var abc = this.abc; var bb = xy.map(function(x){return decodeBin(x)}); bb = this.transpose(bb).map(function(x){return bin2int(x)}); bb = bb.map(function(x){return abc[x]}); return bb.toString().replace(/,/g,''); } // run USM map automatically is a sequence is provided this.L = function (a,b){ // distance between two coordinates var d=0; while((Math.pow(2,d)!=Infinity)&Math.round(a*Math.pow(2,d))==Math.round(b*Math.pow(2,d))){d++} if(Math.pow(2,d)==Infinity){d=64} // stop at the numerical resolution return d; } this.distCGR = function (a,b){ // distance between two CGR positions, a and b //var ab=this.transpose([a,b]); // such that each position is an array of elements with two coordinates, one from each sequence var dist = this.L; return this.transpose([a,b]).map(function(x){return dist(x[0],x[1])}).min(); } this.mapReduce = function (x,map,reduce){ return reduce(x.map(map)) } this.distProfile= function (s){// Distance to another sequence, s if (typeof(s)=='string'){ s=new usm(s,this.abc,this.pack); } if (s.abc!==this.abc){throw('unequal alphabets')} if (s.pack!==this.pack){throw('unequal encode packing')} //var dist = this.distCGR; //var distCoord //var dist = function(a,b){return this.transpose([a,b]).map(function(x){return this.L(x[0],x[1])}).min()}; var f = this.cgrForward.map(function(x){var x0=x; return s.cgrForward.map(function(x){return s.distCGR(x0,x)}).sum()}); var b = this.cgrBackward.map(function(x){var x0=x; return s.cgrBackward.map(function(x){return s.distCGR(x0,x)}).sum()}); return [f,b].transpose().sum(); } this.dist = function (x,y){ // Equation 5: distance between two usm coordinates for a position, i // each provided as a two element Array [cgrForward[i],cgrBackward[i]] var d=this.distCGR(x[0],y[0])+this.distCGR(x[1],y[1])-1; if (d<0){d=0} return d } this.distMap=function (sprobe,sbase){// Distance Map to a new probing sequence, sprobe if (typeof(sprobe)=='string'){sprobe = new usm(sprobe,this.abc,this.pack)} // in case the actual sequence was inputed if (!sbase){sbase=this} // return sbase.usm.map(function(x){return sprobe.usm.map(function(y){return sbase.dist(x,y)})}); } this.align=function(sprobe,sbase){ //align sequence sprobe to this sequence if (typeof(sprobe)=='string'){sprobe = new usm(sprobe,this.abc,this.pack)} // in case the actual sequence was inputed if (!sbase){sbase=this} // // start by considering a complete match and zoom in until such a subset is found var n = sprobe.seq.length , nn = sbase.seq.length; var A={posBase:[0],posProbe:[0],match:[0],ind:0} this.alignUsm=function(posStart,posEnd){ // defined here to capture align closure console.log([posStart,posEnd]); var inc = Math.floor((posEnd-posStart)/2);// increment var i=posStart+inc; var res=32;//some resolution //this.distCGR(x[0],y[0])+this.distCGR(x[1],y[1]) Eq 5 var d = sbase.cgrForward.map(function(cf,ii){return sbase.distCGR(cf,sprobe.cgrForward[i])+sbase.distCGR(sbase.cgrBackward[ii],sprobe.cgrBackward[i])}); var mm = jmat.max2(d); // lets code it here so we don't need jmat just yet: //var mm = d.reduce(function(a,b){return Math.max(a,b)}); if(mm[0]>0){mm[0]-=1};// var ind = mm[0],dmax=mm[1]; var j=A.posProbe.length; //var dF=sbase.distCGR(sbase.usm[mm[1]][0],sprobe.usm[i][0]); // forward distance var dF=sbase.distCGR(sbase.cgrForward[mm[1]],sprobe.cgrForward[i]); // forward distance if(dF>0){dF-=1} A.posBase[j]=mm[1]-dF; // using foward CGR to find start position if(A.posBase[j]<0){mm[0]-=(dF-mm[1]);dF=mm[1];A.posBase[j]=0} // check lower boundary for Base if((A.posBase[j]+dF)>nn){mm[0]-=A.posBase[j]+mm[0]-nn} // check upper boundary for Base A.posProbe[j]=i-dF; if(A.posProbe[j]<0){mm[0]-=(dF-i);dF=i;A.posProbe[j]=0;A.posBase[j]=mm[1]-dF;} // check lower boundary for Probe if((A.posProbe[j]+mm[0])>n){mm[0]-=A.posProbe[j]+mm[0]-n} // check upper boundary of Probe if(mm[0]>res){ // check if numerial resolution might have been exceeded var dFi=sbase.distCGR(sbase.cgrForward[A.posBase[j]],sprobe.cgrForward[A.posProbe[j]])-1; // additional forward distance while(dFi>0){ // if some was found A.posProbe[j]-=dFi;A.posBase[j]-=dFi; mm[0]+=dFi; dFi=sbase.distCGR(sbase.cgrForward[A.posBase[j]],sprobe.cgrForward[A.posProbe[j]])-1; } dFi=sbase.distCGR(sbase.cgrBackward[A.posBase[j]+mm[0]-1],sprobe.cgrBackward[A.posProbe[j]+mm[0]-1])-1; // backward distance at the end of match segment while(dFi>0){ // if some was found mm[0]+=dFi; dFi=sbase.distCGR(sbase.cgrBackward[A.posBase[j]+mm[0]-1],sprobe.cgrBackward[A.posProbe[j]+mm[0]-1])-1; } } A.match[j]=mm[0]; if(mm[0]>(A.match[A.ind])){A.ind=j}; // if this is the best match yet if(A.match[A.ind]15){ // it could be a url if(!!seq.slice(0,10).match(/:\/\//)){ console.log('using proxy '+jmat.webrwUrl+'\nto get fastA file '+seq+' ...'); this.loadFasta(seq,function(x){console.log('... file loaded ...')}, abc)} else{this.encode(seq,abc,pack)} } else{this.encode(seq,abc,pack,seed)} } else {if (abc){this.encode(abc,abc,pack,seed)}} // if alphabet is provided then identify cube anyway to enable decoding } usmDist=function(s1,s2,opt){ // Compares two USM encoded sequences if (!opt){opt='matrix'}; switch (opt) { case 'matrixForward': return s1.cgrForward.map(function(x){var x0=x; return s2.cgrForward.map(function(x){return s2.distCGR(x0,x)})}); break; case 'matrixBackward': return s1.cgrBackward.map(function(x){var x0=x; return s2.cgrBackward.map(function(x){return s2.distCGR(x0,x)})}); break; case 'matrix': //var f1,b1,f2,b2; //create two mirror (forward and backward) version of s1 and s2 fb1=s1.transpose([s1.cgrForward,s1.cgrBackward]); fb2=s2.transpose([s2.cgrForward,s2.cgrBackward]); return fb1.map(function(x){var x0=x; return fb2.map(function(x){var res=s1.distCGR(x0[0],x[0])+s1.distCGR(x0[1],x[1]);if(res>1){res=res-1};return res})}); break; case 'sum': break; case 'max': break; case 'min': break; } } // load jmat if(typeof(jmat)=='undefined'){ var s=document.createElement('script'); s.src='https://usm.github.io/jmat.js'; document.head.appendChild(s); }