@gmod/jbrowse
Version:
JBrowse - client-side genome browser
82 lines (72 loc) • 3.63 kB
JavaScript
/**
* Mixin that adds _estimateGlobalStats method to a store, which
* samples a section of the features in the store and uses those to
* esimate the statistics of the whole data set.
*/
define([
'dojo/_base/declare',
'dojo/_base/array',
'dojo/Deferred',
'JBrowse/Errors'
],
function( declare, array, Deferred, Errors ) {
return declare( null, {
/**
* Fetch a region of the current reference sequence and use it to
* estimate the feature density of the store.
* @private
*/
_estimateGlobalStats: function( refseq ) {
var deferred = new Deferred();
refseq = refseq || this.refSeq;
var timeout = this.storeTimeout || 3000;
var startTime = new Date();
var statsFromInterval = function( length, callback ) {
var thisB = this;
var sampleCenter = refseq.start*0.75 + refseq.end*0.25;
var start = Math.max( 0, Math.round( sampleCenter - length/2 ) );
var end = Math.min( Math.round( sampleCenter + length/2 ), refseq.end );
var features = [];
//console.log(`${this.source} stats fetching ${refseq.name}:${start}..${end}`)
this._getFeatures({ ref: refseq.name, start: start, end: end},
function( f ) { features.push(f); },
function( error ) {
features = array.filter( features, function(f) { return f.get('start') >= start && f.get('end') <= end; } );
callback.call( thisB, length,
{
featureDensity: features.length / length,
_statsSampleFeatures: features.length,
_statsSampleInterval: { ref: refseq.name, start: start, end: end, length: length }
});
},
function( error ) {
callback.call( thisB, length, null, error );
});
};
var maybeRecordStats = function( interval, stats, error ) {
if( error ) {
if( error.isInstanceOf && error.isInstanceOf(Errors.DataOverflow) ) {
console.log( 'Store statistics found chunkSizeLimit error, using empty: '+(this.source||this.name) );
deferred.resolve( { featureDensity: 0, error: 'global stats estimation found chunkSizeError' } );
}
else {
deferred.reject( error );
}
} else {
var refLen = refseq.end - refseq.start;
if( stats._statsSampleFeatures >= 300 || interval * 2 > refLen || error ) {
console.log( 'Store statistics: '+(this.source||this.name), stats );
deferred.resolve( stats );
} else if( ((new Date()) - startTime) < timeout ) {
statsFromInterval.call( this, interval * 2, maybeRecordStats );
} else {
console.log( 'Store statistics timed out: '+(this.source||this.name) );
deferred.resolve( { featureDensity: 0, error: 'global stats estimation timed out' } );
}
}
};
statsFromInterval.call( this, 100, maybeRecordStats );
return deferred;
}
});
});