@gmod/jbrowse
Version:
JBrowse - client-side genome browser
139 lines (125 loc) • 4.69 kB
JavaScript
const { TribbleIndexedFile } = cjsRequire('@gmod/tribble-index')
const VCF = cjsRequire('@gmod/vcf')
define([
'dojo/_base/declare',
'JBrowse/Errors',
'dojo/_base/lang',
'JBrowse/Store/SeqFeature',
'JBrowse/Store/DeferredStatsMixin',
'JBrowse/Store/DeferredFeaturesMixin',
'JBrowse/Store/SeqFeature/GlobalStatsEstimationMixin',
'JBrowse/Model/XHRBlob',
'JBrowse/Model/BlobFilehandleWrapper',
'JBrowse/Model/VCFFeature',
],
function(
declare,
Errors,
lang,
SeqFeatureStore,
DeferredStatsMixin,
DeferredFeaturesMixin,
GlobalStatsEstimationMixin,
XHRBlob,
BlobFilehandleWrapper,
VCFFeature
) {
return declare( [ SeqFeatureStore, DeferredStatsMixin, DeferredFeaturesMixin, GlobalStatsEstimationMixin ],
{
constructor( args ) {
var thisB = this;
var idxBlob = args.idx ||
new BlobFilehandleWrapper(
new XHRBlob(
this.resolveUrl(
this.getConf('idxUrlTemplate',[]) || this.getConf('urlTemplate',[])+'.idx'
)
)
);
var fileBlob = args.file ||
new BlobFilehandleWrapper(
new XHRBlob(
this.resolveUrl(
this.getConf('urlTemplate',[]) ), { expectRanges: true }
)
);
this.indexedData = new TribbleIndexedFile({
filehandle: fileBlob,
tribbleFilehandle: idxBlob,
oneBasedClosed: true,
chunkSizeLimit: args.chunkSizeLimit || 2000000,
renameRefSeqs: n => this.browser.regularizeReferenceName(n)
});
this.getParser()
.then( function( parser ) {
thisB._deferred.features.resolve({success:true});
thisB._estimateGlobalStats()
.then(
function( stats ) {
thisB.globalStats = stats;
thisB._deferred.stats.resolve( stats );
},
lang.hitch( thisB, '_failAllDeferred' )
);
},
lang.hitch( thisB, '_failAllDeferred' )
);
},
getParser() {
if (!this._parser) {
this._parser = this.indexedData.getHeader()
.then(header => new VCF({header: header}))
}
return this._parser
},
_getFeatures( query, featureCallback, finishedCallback, errorCallback ) {
var thisB = this;
thisB.getParser().then(parser => {
const regularizedReferenceName = this.browser.regularizeReferenceName(query.ref)
thisB.indexedData.getLines(
regularizedReferenceName,
query.start,
query.end,
line => {
const variant = parser.parseLine(line)
const feature = new VCFFeature({
variant: variant,
parser: parser,
id: variant.ID.length ?
variant.ID[0] :
`chr${variant.CHROM}_pos${variant.POS}_ref${variant.REF}_alt${variant.ALT}`
})
featureCallback(feature)
}
)
.then(finishedCallback, error => {
if (errorCallback) {
if (error.message && error.message.indexOf('Too much data') >= 0) {
error = new Errors.DataOverflow(error.message)
}
errorCallback(error)
} else
console.error(error)
})
})
.catch(errorCallback)
},
/**
* Interrogate whether a store has data for a given reference
* sequence. Calls the given callback with either true or false.
*
* Implemented as a binary interrogation because some stores are
* smart enough to regularize reference sequence names, while
* others are not.
*/
hasRefSeq: function( seqName, callback, errorCallback ) {
return this.indexedData.index.hasRefSeq( seqName, callback, errorCallback );
},
saveStore: function() {
return {
urlTemplate: this.config.file.url,
idxUrlTemplate: this.config.idx.url
};
}
});
});