@gmod/jbrowse
Version:
JBrowse - client-side genome browser
146 lines (127 loc) • 3.62 kB
JavaScript
define( [
'dojo/_base/declare'
],
function( declare ) {
var Range = declare( null,
/**
* @lends JBrowse.Model.Range.prototype
*/
{
/**
* Adapted from a combination of Range and _Compound in the
* Dalliance Genome Explorer, (c) Thomas Down 2006-2010.
*/
constructor: function() {
this._ranges =
arguments.length == 2 ? [ { min: arguments[0], max: arguments[1] } ] :
0 in arguments[0] ? dojo.clone( arguments[0] ) :
[ arguments[0] ];
},
min: function() {
return this._ranges[0].min;
},
max: function() {
return this._ranges[this._ranges.length - 1].max;
},
contains: function(pos) {
for (var s = 0; s < this._ranges.length; ++s) {
var r = this._ranges[s];
if ( r.min <= pos && r.max >= pos ) {
return true;
}
}
return false;
},
isContiguous: function() {
return this._ranges.length > 1;
},
ranges: function() {
return this._ranges.map( function(r) {
return new Range( r.min, r.max );
});
},
toString: function() {
return this._ranges
.map(function(r) { return '['+r.min+'-'+r.max+']'; })
.join(',');
},
union: function(s1) {
var s0 = this;
var ranges = s0.ranges().concat(s1.ranges()).sort( this.rangeOrder );
var oranges = [];
var current = ranges[0];
for (var i = 1; i < ranges.length; ++i) {
var nxt = ranges[i];
if (nxt.min() > (current.max() + 1)) {
oranges.push(current);
current = nxt;
} else {
if (nxt.max() > current.max()) {
current = new Range(current.min(), nxt.max());
}
}
}
oranges.push(current);
if (oranges.length == 1) {
return oranges[0];
} else {
return new Range(oranges);
}
},
intersection: function( s1 ) {
var s0 = this;
var r0 = s0.ranges();
var r1 = s1.ranges();
var l0 = r0.length, l1 = r1.length;
var i0 = 0, i1 = 0;
var or = [];
while (i0 < l0 && i1 < l1) {
var s0 = r0[i0], s1 = r1[i1];
var lapMin = Math.max(s0.min(), s1.min());
var lapMax = Math.min(s0.max(), s1.max());
if (lapMax >= lapMin) {
or.push(new Range(lapMin, lapMax));
}
if (s0.max() > s1.max()) {
++i1;
} else {
++i0;
}
}
if (or.length == 0) {
return null; // FIXME
} else if (or.length == 1) {
return or[0];
} else {
return new Range(or);
}
},
coverage: function() {
var tot = 0;
var rl = this.ranges();
for (var ri = 0; ri < rl.length; ++ri) {
var r = rl[ri];
tot += (r.max() - r.min() + 1);
}
return tot;
},
rangeOrder: function( a, b ) {
if( arguments.length < 2 ) {
b = a;
a = this;
}
if (a.min() < b.min()) {
return -1;
} else if (a.min() > b.min()) {
return 1;
} else if (a.max() < b.max()) {
return -1;
} else if (b.max() > a.max()) {
return 1;
} else {
return 0;
}
}
});
return Range;
});