-
Notifications
You must be signed in to change notification settings - Fork 199
/
IndexedFasta.js
109 lines (97 loc) · 3.54 KB
/
IndexedFasta.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
const LRU = cjsRequire('lru-cache')
const { IndexedFasta } = cjsRequire('@gmod/indexedfasta')
const { Buffer } = cjsRequire('buffer')
const fastaIndexedFilesCache = LRU(5)
const BlobFilehandleWrapper = cjsRequire('../../Model/BlobFilehandleWrapper')
define( [ 'dojo/_base/declare',
'JBrowse/Store/SeqFeature',
'JBrowse/Model/XHRBlob',
'JBrowse/Model/SimpleFeature',
'JBrowse/Store/DeferredFeaturesMixin'
],
function(
declare,
SeqFeatureStore,
XHRBlob,
SimpleFeature,
DeferredFeaturesMixin
) {
return declare( [ SeqFeatureStore, DeferredFeaturesMixin ],
{
/**
* Storage backend for sequences in indexed fasta files
* served as static text files.
* @constructs
*/
constructor: function(args) {
let dataBlob
if (args.fasta)
dataBlob = new BlobFilehandleWrapper(args.fasta)
else if (args.urlTemplate)
dataBlob = new BlobFilehandleWrapper(new XHRBlob(this.resolveUrl(args.urlTemplate), { expectRanges: true }))
else
dataBlob = new BlobFilehandleWrapper(new XHRBlob('data.fa', { expectRanges: true }))
let indexBlob
if (args.fai)
indexBlob = new BlobFilehandleWrapper(args.fai)
else if (args.faiUrlTemplate)
indexBlob = new BlobFilehandleWrapper(new XHRBlob(this.resolveUrl(args.faiUrlTemplate)))
else if (args.urlTemplate)
indexBlob = new BlobFilehandleWrapper(new XHRBlob(this.resolveUrl(args.urlTemplate+'.fai')))
else throw new Error('no index provided, must provide a FASTA index')
this.source = dataBlob.toString()
// LRU-cache the FASTA object so we don't have to re-download the
// index when we switch chromosomes
const cacheKey = `data: ${dataBlob}, index: ${indexBlob}`
this.fasta = fastaIndexedFilesCache.get(cacheKey)
if (!this.fasta) {
this.fasta = new IndexedFasta({
fasta: dataBlob,
fai: indexBlob
})
fastaIndexedFilesCache.set(cacheKey, this.fasta)
}
this.fasta.getSequenceList().then(
() => this._deferred.features.resolve({success:true}),
() => this._failAllDeferred()
)
},
_getFeatures: function( query, featCallback, endCallback, errorCallback ) {
if(query.start < 0) {
query.start = 0;
}
this.fasta.getResiduesByName( this.refSeq.name, query.start, query.end ).then((seq) => {
featCallback(new SimpleFeature({data: {seq, start: query.start, end: query.end}}))
endCallback()
},
errorCallback );
},
hasRefSeq: function( seqName, callback, errorCallback ) {
this.fasta.getSequenceSize(seqName)
.then(
size => {
callback(size !== undefined)
},
errorCallback,
)
},
getRefSeqs: function( callback, errorCallback ) {
this.fasta.getSequenceSizes()
.then(sizes => Object.entries(sizes).map(([name,length]) => {
return {
name,
length,
end: length,
start: 0,
}
}))
.then(callback, errorCallback)
},
saveStore: function() {
return {
urlTemplate: (this.config.file||this.config.blob).url,
faiUrlTemplate: this.config.fai.url
};
}
});
});