Skip to content

Commit

Permalink
factor stats estimation out of BAM store into GlobalStatsEstimationMixin
Browse files Browse the repository at this point in the history
  • Loading branch information
rbuels committed Mar 7, 2013
1 parent 01f2e87 commit 022f7e5
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 51 deletions.
70 changes: 19 additions & 51 deletions src/JBrowse/Store/SeqFeature/BAM.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,26 @@ define( [
'JBrowse/Store/DeferredStatsMixin',
'JBrowse/Store/DeferredFeaturesMixin',
'JBrowse/Model/XHRBlob',
'JBrowse/Store/SeqFeature/GlobalStatsEstimationMixin',
'./BAM/Util',
'./BAM/File'
],
function( declare, array, Deferred, lang, Util, SeqFeatureStore, DeferredStatsMixin, DeferredFeaturesMixin, XHRBlob, BAMUtil, BAMFile ) {

var BAMStore = declare( [ SeqFeatureStore, DeferredStatsMixin, DeferredFeaturesMixin ],
function(
declare,
array,
Deferred,
lang,
Util,
SeqFeatureStore,
DeferredStatsMixin,
DeferredFeaturesMixin,
XHRBlob,
GlobalStatsEstimationMixin,
BAMUtil,
BAMFile
) {

var BAMStore = declare( [ SeqFeatureStore, DeferredStatsMixin, DeferredFeaturesMixin, GlobalStatsEstimationMixin ],

/**
* @lends JBrowse.Store.SeqFeature.BAM
Expand Down Expand Up @@ -59,10 +73,11 @@ var BAMStore = declare( [ SeqFeatureStore, DeferredStatsMixin, DeferredFeaturesM

this.bam.init({
success: dojo.hitch( this, '_estimateGlobalStats',
dojo.hitch( this, function(error) {
dojo.hitch( this, function( stats, error ) {
if( error )
this._failAllDeferred( error );
else {
this.globalStats = stats;
this._deferred.stats.resolve({success:true});
this._deferred.features.resolve({success:true});
}
Expand All @@ -85,53 +100,6 @@ var BAMStore = declare( [ SeqFeatureStore, DeferredStatsMixin, DeferredFeaturesM
}, errorCallback );
},

/**
* Fetch a region of the current reference sequence and use it to
* estimate the feature density in the BAM file.
* @private
*/
_estimateGlobalStats: function( finishCallback ) {

var statsFromInterval = function( refSeq, length, callback ) {
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 );
this.bam.fetch( refSeq.name, start, end, dojo.hitch( this, function( features, error) {
if ( error ) {
console.error( error );
callback.call( this, length, null, error );
}
else if( features ) {
features = array.filter( features, function(f) { return f.get('start') >= start && f.get('end') <= end; } );
callback.call( this, length,
{
featureDensity: features.length / length,
_statsSampleFeatures: features.length,
_statsSampleInterval: { ref: refSeq.name, start: start, end: end, length: length }
});
}
}));
};

var maybeRecordStats = function( interval, stats, error ) {
if( error ) {
finishCallback( error );
} else {
var refLen = this.refSeq.end - this.refSeq.start;
if( stats._statsSampleFeatures >= 300 || interval * 2 > refLen || error ) {
this.globalStats = stats;
console.log( 'BAM statistics: '+this.source, stats );
finishCallback();
} else {
statsFromInterval.call( this, this.refSeq, interval * 2, maybeRecordStats );
}
}
};

statsFromInterval.call( this, this.refSeq, 100, maybeRecordStats );
},


// called by getFeatures from the DeferredFeaturesMixin
_getFeatures: function( query, featCallback, endCallback, errorCallback ) {
var start = query.start;
Expand Down
61 changes: 61 additions & 0 deletions src/JBrowse/Store/SeqFeature/GlobalStatsEstimationMixin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* 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'
],
function( declare, array ) {

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( finishCallback ) {

var statsFromInterval = function( refSeq, length, callback ) {
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 );
this.bam.fetch( refSeq.name, start, end, dojo.hitch( this, function( features, error) {
if ( error ) {
console.error( error );
callback.call( this, length, null, error );
}
else if( features ) {
features = array.filter( features, function(f) { return f.get('start') >= start && f.get('end') <= end; } );
callback.call( this, length,
{
featureDensity: features.length / length,
_statsSampleFeatures: features.length,
_statsSampleInterval: { ref: refSeq.name, start: start, end: end, length: length }
});
}
}));
};

var maybeRecordStats = function( interval, stats, error ) {
if( error ) {
finishCallback( null, error );
} else {
var refLen = this.refSeq.end - this.refSeq.start;
if( stats._statsSampleFeatures >= 300 || interval * 2 > refLen || error ) {
console.log( 'Store statistics: '+(this.source||this.name), stats );
finishCallback( stats );
} else {
statsFromInterval.call( this, this.refSeq, interval * 2, maybeRecordStats );
}
}
};

statsFromInterval.call( this, this.refSeq, 100, maybeRecordStats );
}

});
});

0 comments on commit 022f7e5

Please sign in to comment.