genoverse 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +197 -0
- package/.github/workflows/test.yml +24 -0
- package/LICENSE.TXT +24 -0
- package/README.md +11 -0
- package/css/controlPanel.css +200 -0
- package/css/fileDrop.css +22 -0
- package/css/font-awesome.css +3 -0
- package/css/fullscreen.css +19 -0
- package/css/genoverse.css +466 -0
- package/css/karyotype.css +85 -0
- package/css/resizer.css +36 -0
- package/css/tooltips.css +26 -0
- package/css/trackControls.css +111 -0
- package/expanded.html +120 -0
- package/fontawesome/css/fontawesome.min.css +5 -0
- package/fontawesome/css/regular.min.css +5 -0
- package/fontawesome/css/solid.min.css +5 -0
- package/fontawesome/webfonts/fa-brands-400.ttf +0 -0
- package/fontawesome/webfonts/fa-brands-400.woff +0 -0
- package/fontawesome/webfonts/fa-brands-400.woff2 +0 -0
- package/fontawesome/webfonts/fa-regular-400.ttf +0 -0
- package/fontawesome/webfonts/fa-regular-400.woff +0 -0
- package/fontawesome/webfonts/fa-regular-400.woff2 +0 -0
- package/fontawesome/webfonts/fa-solid-900.ttf +0 -0
- package/fontawesome/webfonts/fa-solid-900.woff +0 -0
- package/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
- package/help.pdf +0 -0
- package/i/sort_handle.png +0 -0
- package/index.html +68 -0
- package/index.js +83 -0
- package/jest.config.js +4 -0
- package/js/Genoverse.js +1681 -0
- package/js/Track/Controller/Sequence.js +17 -0
- package/js/Track/Controller/Stranded.js +73 -0
- package/js/Track/Controller.js +620 -0
- package/js/Track/Model/File/BAM.js +44 -0
- package/js/Track/Model/File/BED.js +116 -0
- package/js/Track/Model/File/GFF.js +40 -0
- package/js/Track/Model/File/VCF.js +101 -0
- package/js/Track/Model/File/WIG.js +67 -0
- package/js/Track/Model/File.js +36 -0
- package/js/Track/Model/Gene/Ensembl.js +22 -0
- package/js/Track/Model/Gene.js +5 -0
- package/js/Track/Model/Sequence/Ensembl.js +4 -0
- package/js/Track/Model/Sequence/Fasta.js +60 -0
- package/js/Track/Model/Sequence.js +50 -0
- package/js/Track/Model/SequenceVariation.js +41 -0
- package/js/Track/Model/Stranded.js +28 -0
- package/js/Track/Model/Transcript/Ensembl.js +67 -0
- package/js/Track/Model/Transcript.js +5 -0
- package/js/Track/Model.js +303 -0
- package/js/Track/View/Gene/Ensembl.js +46 -0
- package/js/Track/View/Gene.js +6 -0
- package/js/Track/View/Sequence/Variation.js +115 -0
- package/js/Track/View/Sequence.js +63 -0
- package/js/Track/View/Transcript/Ensembl.js +12 -0
- package/js/Track/View/Transcript.js +28 -0
- package/js/Track/View.js +566 -0
- package/js/Track/library/Chromosome.js +145 -0
- package/js/Track/library/File/BAM.js +30 -0
- package/js/Track/library/File/BED.js +24 -0
- package/js/Track/library/File/BIGBED.js +47 -0
- package/js/Track/library/File/BIGWIG.js +52 -0
- package/js/Track/library/File/GFF.js +9 -0
- package/js/Track/library/File/VCF.js +71 -0
- package/js/Track/library/File/WIG.js +5 -0
- package/js/Track/library/File.js +10 -0
- package/js/Track/library/Gene.js +37 -0
- package/js/Track/library/Graph/Bar.js +235 -0
- package/js/Track/library/Graph/Line.js +296 -0
- package/js/Track/library/Graph.js +355 -0
- package/js/Track/library/HighlightRegion.js +292 -0
- package/js/Track/library/Legend.js +224 -0
- package/js/Track/library/Scalebar.js +227 -0
- package/js/Track/library/Scaleline.js +91 -0
- package/js/Track/library/Static.js +78 -0
- package/js/Track/library/dbSNP.js +142 -0
- package/js/Track.js +632 -0
- package/js/genomes/grch37.js +990 -0
- package/js/genomes/grch38.js +990 -0
- package/js/genoverse.min.js +2 -0
- package/js/genoverse.min.js.map +1 -0
- package/js/lib/BWReader.js +578 -0
- package/js/lib/Base.js +145 -0
- package/js/lib/VCFReader.js +286 -0
- package/js/lib/dalliance/js/bam.js +494 -0
- package/js/lib/dalliance/js/bin.js +185 -0
- package/js/lib/dalliance/js/das.js +749 -0
- package/js/lib/dalliance/js/utils.js +370 -0
- package/js/lib/dalliance-lib.js +3594 -0
- package/js/lib/dalliance-lib.min.js +68 -0
- package/js/lib/jDataView.js +2 -0
- package/js/lib/jParser.js +192 -0
- package/js/lib/jquery-ui.js +8 -0
- package/js/lib/jquery.js +2 -0
- package/js/lib/jquery.mousehold.js +53 -0
- package/js/lib/jquery.mousewheel.js +84 -0
- package/js/lib/jquery.tipsy.js +258 -0
- package/js/lib/rtree.js +1 -0
- package/js/plugins/controlPanel.js +395 -0
- package/js/plugins/fileDrop.js +62 -0
- package/js/plugins/focusRegion.js +12 -0
- package/js/plugins/fullscreen.js +77 -0
- package/js/plugins/karyotype.js +210 -0
- package/js/plugins/resizer.js +45 -0
- package/js/plugins/tooltips.js +94 -0
- package/js/plugins/trackControls.js +143 -0
- package/package.json +43 -0
- package/test/View/__snapshots__/render-bar-graph.test.js.snap +111 -0
- package/test/View/__snapshots__/render-blocks.test.js.snap +105 -0
- package/test/View/__snapshots__/render-chromosome.test.js.snap +5 -0
- package/test/View/__snapshots__/render-highlights.test.js.snap +73 -0
- package/test/View/__snapshots__/render-insert-variants.test.js.snap +9 -0
- package/test/View/__snapshots__/render-labels.test.js.snap +241 -0
- package/test/View/__snapshots__/render-legends.test.js.snap +13 -0
- package/test/View/__snapshots__/render-line-graph.test.js.snap +349 -0
- package/test/View/__snapshots__/render-scalebar.test.js.snap +49 -0
- package/test/View/__snapshots__/render-scaleline.test.js.snap +31 -0
- package/test/View/__snapshots__/render-sequence.test.js.snap +23 -0
- package/test/View/__snapshots__/render-stranded.test.js.snap +5 -0
- package/test/View/__snapshots__/render-transcripts.test.js.snap +193 -0
- package/test/View/render-bar-graph.test.js +87 -0
- package/test/View/render-blocks.test.js +171 -0
- package/test/View/render-chromosome.test.js +40 -0
- package/test/View/render-highlights.test.js +67 -0
- package/test/View/render-insert-variants.test.js +11 -0
- package/test/View/render-labels.test.js +266 -0
- package/test/View/render-legends.test.js +31 -0
- package/test/View/render-line-graph.test.js +169 -0
- package/test/View/render-scalebar.test.js +36 -0
- package/test/View/render-scaleline.test.js +28 -0
- package/test/View/render-sequence.test.js +49 -0
- package/test/View/render-stranded.test.js +10 -0
- package/test/View/render-transcripts.test.js +165 -0
- package/test/create-and-destroy.test.js +63 -0
- package/test/track-ordering.test.js +514 -0
- package/test/track_config/__snapshots__/config-settings.test.js.snap +23 -0
- package/test/track_config/config-settings.test.js +321 -0
- package/test/track_config/zoom-level-settings.test.js +98 -0
- package/test/utils.js +80 -0
- package/utils/createGenome.js +52 -0
- package/utils/devServer.js +36 -0
- package/utils/expandedTemplate.html +46 -0
- package/utils/git-hooks/post-commit +9 -0
- package/utils/git-hooks/pre-commit +7 -0
- package/utils/git-hooks/setup +6 -0
- package/utils/makeExpanded.js +19 -0
- package/webpack.config.js +39 -0
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var BWReader = function (data, callback) {
|
|
3
|
+
// constants: bigwig/bigbed file header signatures (magic numbers) (32 bit) , can be swapped ( big-endian | BE )
|
|
4
|
+
var BIG_WIG_MAGIC = 0x888FFC26;
|
|
5
|
+
var BIG_WIG_MAGIC_BE = 0x26FC8F88;
|
|
6
|
+
|
|
7
|
+
var BIG_BED_MAGIC = 0x8789F2EB;
|
|
8
|
+
var BIG_BED_MAGIC_BE = 0xEBF28987;
|
|
9
|
+
|
|
10
|
+
var CIRTREE_MAGIC = 0x78ca8c91;
|
|
11
|
+
var IDXTREE_MAGIC = 0x2468ace0;
|
|
12
|
+
|
|
13
|
+
// type of file converted to bigwig bedgraph |variable step wiggle | fixed step wiggle
|
|
14
|
+
var BIG_WIG_TYPE_GRAPH = 1;
|
|
15
|
+
var BIG_WIG_TYPE_VSTEP = 2;
|
|
16
|
+
var BIG_WIG_TYPE_FSTEP = 3;
|
|
17
|
+
|
|
18
|
+
// bigbed data color regex
|
|
19
|
+
var BED_COLOR_REGEXP = new RegExp("^[0-9]+,[0-9]+,[0-9]+");
|
|
20
|
+
|
|
21
|
+
var M1 = 256;
|
|
22
|
+
var M2 = 256*256;
|
|
23
|
+
var M3 = 256*256*256;
|
|
24
|
+
var M4 = 256*256*256*256;
|
|
25
|
+
|
|
26
|
+
var bbi = {
|
|
27
|
+
fetchedData: new RTree()
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function init() {
|
|
31
|
+
checkSignature();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function getData(start, length, cb) {
|
|
35
|
+
var end = start + length;
|
|
36
|
+
var fetched = bbi.fetchedData.search({ x: start, w: length, y: 0, h: 1 }).filter(function (d) { return d[0] <= start && d[1] >= end; });
|
|
37
|
+
|
|
38
|
+
if (fetched.length == 1) {
|
|
39
|
+
cb(fetched[0][2].slice(start - fetched[0][0], start + length));
|
|
40
|
+
} else {
|
|
41
|
+
data.slice(start, length).fetch(function (d) {
|
|
42
|
+
bbi.fetchedData.insert({ x: start, w: length, y: 0, h: 1 }, [ start, start + length, d ]);
|
|
43
|
+
cb(d);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function checkSignature() {
|
|
49
|
+
getData(0, 512, function (header) {
|
|
50
|
+
var ba = new Uint8Array(header);
|
|
51
|
+
var sa = new Uint16Array(header);
|
|
52
|
+
var la = new Uint32Array(header);
|
|
53
|
+
var magic = la[0];
|
|
54
|
+
var error, reduction, dataOffset, indexOffset;
|
|
55
|
+
|
|
56
|
+
if (magic === BIG_WIG_MAGIC) {
|
|
57
|
+
bbi.type = 'bigwig';
|
|
58
|
+
} else if (magic === BIG_BED_MAGIC) {
|
|
59
|
+
bbi.type = 'bigbed';
|
|
60
|
+
} else if (magic === BIG_WIG_MAGIC_BE || magic === BIG_BED_MAGIC_BE) {
|
|
61
|
+
error = 'big-endian files not supported yet!';
|
|
62
|
+
} else{
|
|
63
|
+
error = 'unsupported file format';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (error) {
|
|
67
|
+
callback(null, error);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
bbi.version = sa[2];
|
|
71
|
+
bbi.numZoomLevels = sa[3];
|
|
72
|
+
bbi.chromTreeOffset = read64Bit(ba, 8);
|
|
73
|
+
bbi.unzoomedDataOffset = read64Bit(ba, 16);
|
|
74
|
+
bbi.unzoomedIndexOffset = read64Bit(ba, 24);
|
|
75
|
+
bbi.fieldCount = sa[16];
|
|
76
|
+
bbi.definedFieldCount = sa[17];
|
|
77
|
+
bbi.asOffset = read64Bit(ba, 36);
|
|
78
|
+
bbi.totalSummaryOffset = read64Bit(ba, 44);
|
|
79
|
+
bbi.uncompressBufSize = la[13];
|
|
80
|
+
bbi.extHeaderOffset = read64Bit(ba, 56);
|
|
81
|
+
bbi.compressed = bbi.uncompressBufSize > 0;
|
|
82
|
+
bbi.summary = bbi.totalSummaryOffset > 0;
|
|
83
|
+
bbi.extHeader = bbi.extHeaderOffset > 0;
|
|
84
|
+
bbi.zoomHeaders = [];
|
|
85
|
+
|
|
86
|
+
for (var i = 0; i < bbi.numZoomLevels; i++) {
|
|
87
|
+
reduction = la[16 + 6*i];
|
|
88
|
+
dataOffset = read64Bit(ba, 72 + 24*i);
|
|
89
|
+
indexOffset = read64Bit(ba, 80 + 24*i);
|
|
90
|
+
|
|
91
|
+
bbi.zoomHeaders.push({
|
|
92
|
+
reductionLevel : reduction,
|
|
93
|
+
dataOffset : dataOffset,
|
|
94
|
+
indexOffset : indexOffset
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
readAutoSQL(readChromTree); // reading autoSQL passing next task as callback
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// autoSQL could be present in some bigbed files
|
|
103
|
+
function readAutoSQL(cb) {
|
|
104
|
+
if (bbi.asOffset === 0) {
|
|
105
|
+
cb(); // no autoSQL present
|
|
106
|
+
} else {
|
|
107
|
+
// autoSQL present, need to parse
|
|
108
|
+
getData(bbi.asOffset, 2048, function (d) {
|
|
109
|
+
var ba = new Uint8Array(d);
|
|
110
|
+
var s = '';
|
|
111
|
+
|
|
112
|
+
for (var i = 0; i < ba.length; i++) {
|
|
113
|
+
if (ba[i] === 0) {
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
s += String.fromCharCode(ba[i]);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
var header_re = /(\w+)\s+(\w+)\s+("([^"]+)")?\s*\(\s*/;
|
|
121
|
+
var field_re = /([\w\[\]]+)\s+(\w+)\s*;\s*("([^"]+)")?\s*/g;
|
|
122
|
+
var headerMatch = header_re.exec(s);
|
|
123
|
+
|
|
124
|
+
if (headerMatch) {
|
|
125
|
+
var as = {
|
|
126
|
+
declType : headerMatch[1],
|
|
127
|
+
name : headerMatch[2],
|
|
128
|
+
comment : headerMatch[4],
|
|
129
|
+
fields : []
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
s = s.substring(headerMatch[0]);
|
|
133
|
+
|
|
134
|
+
for (var m = field_re.exec(s); m !== null; m = field_re.exec(s)) {
|
|
135
|
+
as.fields.push({
|
|
136
|
+
type : m[1],
|
|
137
|
+
name : m[2],
|
|
138
|
+
comment : m[4]
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
bbi.schema = as;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
cb();
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// reading B+ tree which maps chrom names to ids used in R-tree
|
|
151
|
+
function readChromTree() {
|
|
152
|
+
var len = bbi.unzoomedDataOffset - bbi.chromTreeOffset;
|
|
153
|
+
len = len + (4 - len%4);
|
|
154
|
+
|
|
155
|
+
getData(bbi.chromTreeOffset, len, function (d) {
|
|
156
|
+
var ba = new Uint8Array(d);
|
|
157
|
+
var sa = new Uint16Array(d);
|
|
158
|
+
var la = new Uint32Array(d);
|
|
159
|
+
var magic = la[0];
|
|
160
|
+
var error;
|
|
161
|
+
|
|
162
|
+
function readChromTreeLeaf(nodeOffset) {
|
|
163
|
+
// padding 8 byte
|
|
164
|
+
var children = sa[(nodeOffset/2) + 1];
|
|
165
|
+
var offset = nodeOffset + 4;
|
|
166
|
+
var chrom, i, c, idx, len;
|
|
167
|
+
|
|
168
|
+
while (children > 0) {
|
|
169
|
+
children--;
|
|
170
|
+
chrom = '';
|
|
171
|
+
|
|
172
|
+
for (i = 0; i < bbi.bpTree.keySize; i++) {
|
|
173
|
+
c = ba[offset + i];
|
|
174
|
+
|
|
175
|
+
if (c !== 0) {
|
|
176
|
+
chrom += String.fromCharCode(c);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
offset += bbi.bpTree.keySize;
|
|
181
|
+
|
|
182
|
+
idx = (ba[offset + 3] << 24) | (ba[offset + 2] << 16) | (ba[offset + 1] << 8) | (ba[offset + 0]);
|
|
183
|
+
len = (ba[offset + 7] << 24) | (ba[offset + 6] << 16) | (ba[offset + 5] << 8) | (ba[offset + 4]);
|
|
184
|
+
|
|
185
|
+
offset += 8;
|
|
186
|
+
|
|
187
|
+
bbi.chroms[idx] = chrom;
|
|
188
|
+
bbi.lengths[idx] = len;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (magic === CIRTREE_MAGIC) {
|
|
193
|
+
bbi.bpTree = {
|
|
194
|
+
itemsPerBlock : la[1],
|
|
195
|
+
keySize : la[2],
|
|
196
|
+
valueSize : la[3],
|
|
197
|
+
itemCount : read64Bit(ba, 16)
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
bbi.chroms = new Array(bbi.bpTree.itemCount);
|
|
201
|
+
bbi.lengths = new Array(bbi.bpTree.itemCount);
|
|
202
|
+
} else {
|
|
203
|
+
error = 'chromosome id B+ tree not found!';
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (error) {
|
|
207
|
+
callback(null, error);
|
|
208
|
+
} else {
|
|
209
|
+
readChromTreeLeaf(32);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
readRTreeIndex();
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function readRTreeIndex() {
|
|
217
|
+
getData(bbi.unzoomedIndexOffset, 48, function (d) {
|
|
218
|
+
var ba = new Uint8Array(d);
|
|
219
|
+
var la = new Uint32Array(d);
|
|
220
|
+
var magic = la[0];
|
|
221
|
+
|
|
222
|
+
if (magic === IDXTREE_MAGIC) {
|
|
223
|
+
bbi.Rheader = {
|
|
224
|
+
blockSize : la[1],
|
|
225
|
+
nItems : read64Bit(ba, 8),
|
|
226
|
+
chrIdxStart : la[4],
|
|
227
|
+
baseStart : la[5],
|
|
228
|
+
chrIdxEnd : la[6],
|
|
229
|
+
baseEnd : la[7],
|
|
230
|
+
endFileOffset : read64Bit(ba, 32),
|
|
231
|
+
nItemsPerSlot : la[10]
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
bbi.rootOffset = bbi.unzoomedIndexOffset + 48;
|
|
235
|
+
bbi.getValues = getValues;
|
|
236
|
+
|
|
237
|
+
callback(bbi);
|
|
238
|
+
} else {
|
|
239
|
+
callback(null, 'R-tree not found!');
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function getRTreeNode(treedata, offset) {
|
|
245
|
+
var ba = new Uint8Array(treedata);
|
|
246
|
+
var sa = new Uint16Array(treedata);
|
|
247
|
+
var la = new Uint32Array(treedata);
|
|
248
|
+
var children = sa[offset/2 + 1];
|
|
249
|
+
var lo, i;
|
|
250
|
+
|
|
251
|
+
var node = {
|
|
252
|
+
isLeaf : ba[offset],
|
|
253
|
+
children : children,
|
|
254
|
+
chrIdxStart : new Array(children),
|
|
255
|
+
baseStart : new Array(children),
|
|
256
|
+
chrIdxEnd : new Array(children),
|
|
257
|
+
baseEnd : new Array(children),
|
|
258
|
+
dataOffset : new Array(children),
|
|
259
|
+
x : {}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
if (node.isLeaf) {
|
|
263
|
+
node.x.size = new Array(children);
|
|
264
|
+
} else {
|
|
265
|
+
node.x.child = new Array(children);
|
|
266
|
+
|
|
267
|
+
for (i = 0; i < children; i++) {
|
|
268
|
+
node.x.child[i] = -1;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
offset += 4;
|
|
273
|
+
|
|
274
|
+
for (i = 0; i < children; i++) {
|
|
275
|
+
lo = offset / 4;
|
|
276
|
+
|
|
277
|
+
node.chrIdxStart[i] = la[lo];
|
|
278
|
+
node.baseStart[i] = la[lo + 1];
|
|
279
|
+
node.chrIdxEnd[i] = la[lo + 2];
|
|
280
|
+
node.baseEnd[i] = la[lo + 3];
|
|
281
|
+
node.dataOffset[i] = read64Bit(ba, offset + 16);
|
|
282
|
+
|
|
283
|
+
offset += 24;
|
|
284
|
+
|
|
285
|
+
if (node.isLeaf) {
|
|
286
|
+
node.x.size[i] = read64Bit(ba, offset);
|
|
287
|
+
offset += 8;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return node;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function getValues(chrom, start, end, cb) {
|
|
295
|
+
var vals = [];
|
|
296
|
+
var chromid = bbi.chroms.indexOf(chrom);
|
|
297
|
+
|
|
298
|
+
if (chromid == -1) {
|
|
299
|
+
chromid = bbi.chroms.indexOf('chr' + chrom);
|
|
300
|
+
|
|
301
|
+
if (chromid == -1) {
|
|
302
|
+
return cb([], 'chrom not found');
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
var query = {
|
|
307
|
+
chrom : chromid,
|
|
308
|
+
start : start,
|
|
309
|
+
end : end
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
function traverseRTree() {
|
|
313
|
+
var outstanding = 0;
|
|
314
|
+
|
|
315
|
+
function fetchRTreeKids(offset, level) {
|
|
316
|
+
outstanding += offset.length;
|
|
317
|
+
|
|
318
|
+
var min = offset[0];
|
|
319
|
+
var maxNodeSize = 4 + bbi.Rheader.blockSize*32;
|
|
320
|
+
var max = offset[offset.length - 1] + maxNodeSize;
|
|
321
|
+
|
|
322
|
+
getData(min, max - min, function (treedata) {
|
|
323
|
+
// traverse kids
|
|
324
|
+
for (var i = 0; i < offset.length; i++) {
|
|
325
|
+
traverseRTreeKids(treedata, offset[i] - min, level);
|
|
326
|
+
|
|
327
|
+
if (--outstanding === 0) {
|
|
328
|
+
fetchBlocks();
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function traverseRTreeKids(treedata, offset, level) {
|
|
335
|
+
var node = getRTreeNode(treedata, offset);
|
|
336
|
+
var overlaps = findOverlaps(node);
|
|
337
|
+
var i;
|
|
338
|
+
|
|
339
|
+
if (node.isLeaf) {
|
|
340
|
+
for (i = 0; i < overlaps.length; i++){
|
|
341
|
+
vals.push({
|
|
342
|
+
offset : node.dataOffset[overlaps[i]],
|
|
343
|
+
size : node.x.size[overlaps[i]]
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return [];
|
|
348
|
+
} else {
|
|
349
|
+
fetchRTreeKids(overlaps.map(function (o) { return node.dataOffset[o]; }), level + 1);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function findOverlaps(node) {
|
|
354
|
+
var children = node.children;
|
|
355
|
+
var overlaps = [];
|
|
356
|
+
|
|
357
|
+
for (var i = 0; i < children; i++) {
|
|
358
|
+
var startChrom = node.chrIdxStart[i];
|
|
359
|
+
var startBase = node.baseStart[i];
|
|
360
|
+
var endChrom = node.chrIdxEnd[i];
|
|
361
|
+
var endBase = node.baseEnd[i];
|
|
362
|
+
|
|
363
|
+
if (
|
|
364
|
+
((startChrom < query.chrom) || (startChrom == query.chrom && startBase <= query.end)) &&
|
|
365
|
+
((endChrom > query.chrom) || (endChrom == query.chrom && endBase >= query.start))
|
|
366
|
+
) {
|
|
367
|
+
overlaps.push(i);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return overlaps;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
fetchRTreeKids([bbi.rootOffset], 1);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function fetchBlocks() {
|
|
378
|
+
vals.sort(function (b0, b1) {
|
|
379
|
+
return (b0.offset | 0) - (b1.offset | 0);
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
if (vals.length === 0) {
|
|
383
|
+
return getBlocks();
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
var totalSize = 0;
|
|
387
|
+
var base = vals[0].offset;
|
|
388
|
+
|
|
389
|
+
for (var i = 0; i < vals.length; i++) {
|
|
390
|
+
totalSize += vals[i].size;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
getData(base, totalSize, function (buffer) {
|
|
394
|
+
var ioffset = 0;
|
|
395
|
+
var bi = 0;
|
|
396
|
+
var fb, blockData;
|
|
397
|
+
|
|
398
|
+
while (ioffset < totalSize) {
|
|
399
|
+
fb = vals[bi];
|
|
400
|
+
|
|
401
|
+
if (bbi.uncompressBufSize > 0) {
|
|
402
|
+
blockData = dallianceLib.inflateBuffer(buffer, ioffset + 2, fb.size - 2);
|
|
403
|
+
} else {
|
|
404
|
+
blockData = buffer.slice(ioffset, ioffset + fb.size);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
vals[bi].data = blockData;
|
|
408
|
+
ioffset += fb.size;
|
|
409
|
+
bi++;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
getBlocks();
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function getBlocks() {
|
|
417
|
+
var parser = bbi.type == 'bigwig' ? WiggleParser : bbi.type == 'bigbed' ? BEDParser : false;
|
|
418
|
+
var result = [];
|
|
419
|
+
|
|
420
|
+
if (parser && vals.length) {
|
|
421
|
+
for (var i = 0; i < vals.length; i++) {
|
|
422
|
+
result = result.concat(parser(vals[i].data, query));
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
cb(result);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
traverseRTree();
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function WiggleParser(data, query) {
|
|
433
|
+
var arr = [];
|
|
434
|
+
var ba = new Uint8Array(data);
|
|
435
|
+
var sa = new Int16Array(data);
|
|
436
|
+
var la = new Int32Array(data);
|
|
437
|
+
var fa = new Float32Array(data);
|
|
438
|
+
var chromId = la[0];
|
|
439
|
+
var chr = parseInt(bbi.chroms[chromId].replace('chr', ''), 10);
|
|
440
|
+
var blockStart = la[1] + 1;
|
|
441
|
+
var itemStep = la[3];
|
|
442
|
+
var itemSpan = la[4];
|
|
443
|
+
var blockType = ba[20];
|
|
444
|
+
var itemCount = sa[11];
|
|
445
|
+
var i, start, end, score;
|
|
446
|
+
|
|
447
|
+
if (blockType === BIG_WIG_TYPE_FSTEP) { // fixedStep wiggle
|
|
448
|
+
for (i = 0; i < itemCount; i++) {
|
|
449
|
+
start = blockStart + i*itemStep;
|
|
450
|
+
end = start + itemSpan - 1;
|
|
451
|
+
score = fa[i + 6];
|
|
452
|
+
|
|
453
|
+
if (chromId == query.chrom) {
|
|
454
|
+
arr.push({
|
|
455
|
+
chr : chr,
|
|
456
|
+
start : start,
|
|
457
|
+
end : end,
|
|
458
|
+
height : score
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
} else if (blockType === BIG_WIG_TYPE_VSTEP) { // variable step wiggle
|
|
463
|
+
for (i = 0; i < itemCount; i++) {
|
|
464
|
+
start = la[i*2 + 6] + 1;
|
|
465
|
+
end = start + itemSpan - 1;
|
|
466
|
+
score = fa[i*2 + 7];
|
|
467
|
+
|
|
468
|
+
if (chromId == query.chrom) {
|
|
469
|
+
arr.push({
|
|
470
|
+
chr : chr,
|
|
471
|
+
start : start,
|
|
472
|
+
end : end,
|
|
473
|
+
height : score
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
} else if (blockType === BIG_WIG_TYPE_GRAPH) { // bedGraph
|
|
478
|
+
for (i = 0; i < itemCount; i++) {
|
|
479
|
+
start = la[i*3 + 6] + 1;
|
|
480
|
+
end = la[i*3 + 7];
|
|
481
|
+
score = fa[i*3 + 8];
|
|
482
|
+
|
|
483
|
+
if (start > end) {
|
|
484
|
+
start = end;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (chromId == query.chrom) {
|
|
488
|
+
arr.push({
|
|
489
|
+
chr : chr,
|
|
490
|
+
start : start,
|
|
491
|
+
end : end,
|
|
492
|
+
height : score
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return arr;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
function BEDParser(data, query) {
|
|
502
|
+
var arr = [];
|
|
503
|
+
var ba = new Uint8Array(data);
|
|
504
|
+
var la = new Int32Array(data);
|
|
505
|
+
var offset = 0;
|
|
506
|
+
var bbRecord, ch, rest;
|
|
507
|
+
|
|
508
|
+
while (offset < la.length) {
|
|
509
|
+
bbRecord = {
|
|
510
|
+
chromid : la[offset],
|
|
511
|
+
chr : bbi.chroms[la[offset]],
|
|
512
|
+
start : la[offset + 1],
|
|
513
|
+
end : la[offset + 2]
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
offset += 12;
|
|
517
|
+
|
|
518
|
+
while (true) {
|
|
519
|
+
ch = ba[offset++];
|
|
520
|
+
|
|
521
|
+
if (ch !== 0) {
|
|
522
|
+
rest += String.fromCharCode(ch);
|
|
523
|
+
} else {
|
|
524
|
+
break;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if (bbRecord.chromid === query.chrom) {
|
|
529
|
+
arr.push([ bbRecord.chr, bbRecord.start, bbRecord.end, rest ].join('\t'));
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
return arr;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// reads 8 bytes from data
|
|
537
|
+
function read64Bit(ba, o) {
|
|
538
|
+
var val = ba[o] + ba[o+1]*M1 + ba[o+2]*M2 + ba[o+3]*M3 + ba[o+4]*M4;
|
|
539
|
+
return val;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
function readFloat(ba, o) {
|
|
543
|
+
var a = new Uint8Array([ ba[o], ba[o+1], ba[o+2], ba[o+3] ]);
|
|
544
|
+
var b = a.buffer;
|
|
545
|
+
var c = new Float32Array(b);
|
|
546
|
+
return c[0];
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// reads 4 bytes from data
|
|
550
|
+
function read32Bit(ba, o) {
|
|
551
|
+
var a = ba[o];
|
|
552
|
+
var b = ba[o+1];
|
|
553
|
+
var c = ba[o+2];
|
|
554
|
+
var d = ba[o+3];
|
|
555
|
+
var r = (a | ((b << 8) >>> 0) | ((c << 16) >>> 0) | ((d << 24) >>> 0)) >>> 0;
|
|
556
|
+
return r;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// reads 2 bytes from data
|
|
560
|
+
function read16Bit(ba, o) {
|
|
561
|
+
var r = ba[o] | (ba[o+1] << 8);
|
|
562
|
+
return r;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// reads 1 byte from data
|
|
566
|
+
function read8Bit(ba, o) {
|
|
567
|
+
return ba[o];
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
init();
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
window.BWReader = BWReader;
|
|
574
|
+
|
|
575
|
+
if (typeof module === 'object' && typeof module.exports === 'object') {
|
|
576
|
+
module.exports = BWReader;
|
|
577
|
+
}
|
|
578
|
+
})();
|
package/js/lib/Base.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Based on Base.js 1.1a (c) 2006-2010, Dean Edwards
|
|
3
|
+
Updated to pass JSHint and converted into a module by Kenneth Powers
|
|
4
|
+
License: http://www.opensource.org/licenses/mit-license.php
|
|
5
|
+
*/
|
|
6
|
+
/*global define:true module:true*/
|
|
7
|
+
/*jshint eqeqeq:true*/
|
|
8
|
+
(function (name, global, definition) {
|
|
9
|
+
if (typeof module !== 'undefined') {
|
|
10
|
+
module.exports = definition();
|
|
11
|
+
} else if (typeof define !== 'undefined' && typeof define.amd === 'object') {
|
|
12
|
+
define(definition);
|
|
13
|
+
} else {
|
|
14
|
+
global[name] = definition();
|
|
15
|
+
}
|
|
16
|
+
})('Base', this, function () {
|
|
17
|
+
// Base Object
|
|
18
|
+
var Base = function () {};
|
|
19
|
+
|
|
20
|
+
// Implementation
|
|
21
|
+
Base.extend = function (_instance, _static) { // subclass
|
|
22
|
+
var extend = Base.prototype.extend;
|
|
23
|
+
// build the prototype
|
|
24
|
+
Base._prototyping = true;
|
|
25
|
+
var proto = new this();
|
|
26
|
+
extend.call(proto, _instance);
|
|
27
|
+
proto.base = function () {
|
|
28
|
+
// call this method from any other method to invoke that method's ancestor
|
|
29
|
+
};
|
|
30
|
+
delete Base._prototyping;
|
|
31
|
+
// create the wrapper for the constructor function
|
|
32
|
+
//var constructor = proto.constructor.valueOf(); //-dean
|
|
33
|
+
var constructor = proto.constructor;
|
|
34
|
+
var klass = proto.constructor = function () {
|
|
35
|
+
if (!Base._prototyping) {
|
|
36
|
+
if (this._constructing || this.constructor === klass) { // instantiation
|
|
37
|
+
this._constructing = true;
|
|
38
|
+
constructor.apply(this, arguments);
|
|
39
|
+
delete this._constructing;
|
|
40
|
+
} else if (arguments[0] !== null) { // casting
|
|
41
|
+
return (arguments[0].extend || extend).call(arguments[0], proto);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
// build the class interface
|
|
46
|
+
klass.ancestor = this;
|
|
47
|
+
klass.extend = this.extend;
|
|
48
|
+
klass.forEach = this.forEach;
|
|
49
|
+
klass.implement = this.implement;
|
|
50
|
+
klass.prototype = proto;
|
|
51
|
+
klass.toString = this.toString;
|
|
52
|
+
klass.valueOf = function (type) {
|
|
53
|
+
return (type === 'object') ? klass : constructor.valueOf();
|
|
54
|
+
};
|
|
55
|
+
extend.call(klass, _static);
|
|
56
|
+
// class initialization
|
|
57
|
+
if (typeof klass.init === 'function') klass.init();
|
|
58
|
+
return klass;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
Base.prototype = {
|
|
62
|
+
extend: function (source, value) {
|
|
63
|
+
if (arguments.length > 1) { // extending with a name/value pair
|
|
64
|
+
var ancestor = this[source];
|
|
65
|
+
if (ancestor && (typeof value === 'function') && // overriding a method?
|
|
66
|
+
// the valueOf() comparison is to avoid circular references
|
|
67
|
+
(!ancestor.valueOf || ancestor.valueOf() !== value.valueOf()) && /\bbase\b/.test(value)) {
|
|
68
|
+
// get the underlying method
|
|
69
|
+
var method = value.valueOf();
|
|
70
|
+
// override
|
|
71
|
+
value = function () {
|
|
72
|
+
var previous = this.base || Base.prototype.base;
|
|
73
|
+
this.base = ancestor;
|
|
74
|
+
var returnValue = method.apply(this, arguments);
|
|
75
|
+
this.base = previous;
|
|
76
|
+
return returnValue;
|
|
77
|
+
};
|
|
78
|
+
// point to the underlying method
|
|
79
|
+
value.valueOf = function (type) {
|
|
80
|
+
return (type === 'object') ? value : method;
|
|
81
|
+
};
|
|
82
|
+
value.toString = Base.toString;
|
|
83
|
+
}
|
|
84
|
+
this[source] = value;
|
|
85
|
+
} else if (source) { // extending with an object literal
|
|
86
|
+
var extend = Base.prototype.extend;
|
|
87
|
+
// if this object has a customized extend method then use it
|
|
88
|
+
if (!Base._prototyping && typeof this !== 'function') {
|
|
89
|
+
extend = this.extend || extend;
|
|
90
|
+
}
|
|
91
|
+
var proto = {
|
|
92
|
+
toSource: null
|
|
93
|
+
};
|
|
94
|
+
// do the "toString" and other methods manually
|
|
95
|
+
var hidden = ['constructor', 'toString', 'valueOf'];
|
|
96
|
+
// if we are prototyping then include the constructor
|
|
97
|
+
for (var i = Base._prototyping ? 0 : 1; i < hidden.length; i++) {
|
|
98
|
+
var h = hidden[i];
|
|
99
|
+
if (source[h] !== proto[h])
|
|
100
|
+
extend.call(this, h, source[h]);
|
|
101
|
+
}
|
|
102
|
+
// copy each of the source object's properties to this object
|
|
103
|
+
for (var key in source) {
|
|
104
|
+
if (!proto[key]) extend.call(this, key, source[key]);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// initialize
|
|
112
|
+
Base = Base.extend({
|
|
113
|
+
constructor: function () {
|
|
114
|
+
this.extend(arguments[0]);
|
|
115
|
+
}
|
|
116
|
+
}, {
|
|
117
|
+
ancestor: Object,
|
|
118
|
+
version: '1.1',
|
|
119
|
+
forEach: function (object, block, context) {
|
|
120
|
+
for (var key in object) {
|
|
121
|
+
if (this.prototype[key] === undefined) {
|
|
122
|
+
block.call(context, object[key], key, object);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
implement: function () {
|
|
127
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
128
|
+
if (typeof arguments[i] === 'function') {
|
|
129
|
+
// if it's a function, call it
|
|
130
|
+
arguments[i](this.prototype);
|
|
131
|
+
} else {
|
|
132
|
+
// add the interface using the extend method
|
|
133
|
+
this.prototype.extend(arguments[i]);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return this;
|
|
137
|
+
},
|
|
138
|
+
toString: function () {
|
|
139
|
+
return String(this.valueOf());
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Return Base implementation
|
|
144
|
+
return Base;
|
|
145
|
+
});
|