genoverse 3.2.0 → 4.0.0-beta1

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.
Files changed (216) hide show
  1. package/.eslintrc.js +93 -162
  2. package/.github/workflows/test.yml +9 -10
  3. package/.github/workflows/update-gh-pages.yml +33 -0
  4. package/LICENSE.TXT +2 -2
  5. package/README.md +176 -3
  6. package/{i → assets}/sort_handle.png +0 -0
  7. package/babel.config.js +19 -0
  8. package/dist/129.css +334 -0
  9. package/dist/129.css.map +1 -0
  10. package/dist/129.genoverse.js +2 -0
  11. package/dist/129.genoverse.js.map +1 -0
  12. package/dist/15d98c18221c8bcb2334.ttf +0 -0
  13. package/dist/166.css +2 -0
  14. package/dist/166.genoverse.js +1 -0
  15. package/dist/216.css +20 -0
  16. package/dist/216.css.map +1 -0
  17. package/dist/232.css +114 -0
  18. package/dist/232.css.map +1 -0
  19. package/dist/232.genoverse.js +2 -0
  20. package/dist/232.genoverse.js.map +1 -0
  21. package/dist/2e659e443f3e98569e9f.png +0 -0
  22. package/dist/394.css +114 -0
  23. package/dist/394.css.map +1 -0
  24. package/dist/394.genoverse.js +2 -0
  25. package/dist/394.genoverse.js.map +1 -0
  26. package/dist/469.css +24 -0
  27. package/dist/469.css.map +1 -0
  28. package/dist/469.genoverse.js +2 -0
  29. package/dist/469.genoverse.js.map +1 -0
  30. package/dist/4896d4b04430cc3dfb06.woff2 +0 -0
  31. package/dist/530.css +39 -0
  32. package/dist/530.css.map +1 -0
  33. package/dist/530.genoverse.js +2 -0
  34. package/dist/530.genoverse.js.map +1 -0
  35. package/dist/547.css +469 -0
  36. package/dist/547.css.map +1 -0
  37. package/dist/547.genoverse.js +1 -0
  38. package/dist/729.css +315 -0
  39. package/dist/729.css.map +1 -0
  40. package/dist/79da213423ac0def2058.ttf +0 -0
  41. package/dist/804.genoverse.js +2 -0
  42. package/dist/804.genoverse.js.map +1 -0
  43. package/dist/842.genoverse.js +2 -0
  44. package/dist/842.genoverse.js.map +1 -0
  45. package/dist/893.genoverse.js +2 -0
  46. package/dist/893.genoverse.js.map +1 -0
  47. package/dist/949.css +315 -0
  48. package/dist/949.css.map +1 -0
  49. package/dist/949.genoverse.js +2 -0
  50. package/dist/949.genoverse.js.map +1 -0
  51. package/dist/952.css +315 -0
  52. package/dist/952.css.map +1 -0
  53. package/dist/952.genoverse.js +2 -0
  54. package/dist/952.genoverse.js.map +1 -0
  55. package/dist/d79c2ec96ab9ff1161a2.woff2 +0 -0
  56. package/dist/genoverse.js +2 -0
  57. package/dist/genoverse.js.map +1 -0
  58. package/index.html +13 -14
  59. package/jest.config.js +5 -0
  60. package/jest.setup.js +13 -0
  61. package/package.json +29 -12
  62. package/{css → src/css}/controlPanel.css +0 -0
  63. package/{css → src/css}/fileDrop.css +0 -0
  64. package/src/css/fontawesome.css +3 -0
  65. package/{css → src/css}/fullscreen.css +0 -0
  66. package/{css → src/css}/genoverse.css +1 -1
  67. package/{css → src/css}/karyotype.css +2 -0
  68. package/{css → src/css}/resizer.css +0 -0
  69. package/{css → src/css}/tooltips.css +0 -0
  70. package/{css → src/css}/trackControls.css +0 -0
  71. package/src/js/Genoverse.js +1747 -0
  72. package/{js → src/js}/Track/Controller/Sequence.js +6 -4
  73. package/src/js/Track/Controller/Stranded.js +83 -0
  74. package/{js → src/js}/Track/Controller.js +201 -160
  75. package/src/js/Track/Model/File/BAM.js +47 -0
  76. package/src/js/Track/Model/File/BED.js +122 -0
  77. package/src/js/Track/Model/File/GFF.js +42 -0
  78. package/src/js/Track/Model/File/VCF.js +109 -0
  79. package/src/js/Track/Model/File/WIG.js +82 -0
  80. package/src/js/Track/Model/File.js +36 -0
  81. package/src/js/Track/Model/Gene/Ensembl.js +24 -0
  82. package/{js → src/js}/Track/Model/Gene.js +3 -1
  83. package/src/js/Track/Model/Sequence/Ensembl.js +6 -0
  84. package/{js → src/js}/Track/Model/Sequence/Fasta.js +24 -17
  85. package/{js → src/js}/Track/Model/Sequence.js +10 -7
  86. package/{js → src/js}/Track/Model/SequenceVariation.js +17 -11
  87. package/{js → src/js}/Track/Model/Stranded.js +11 -8
  88. package/src/js/Track/Model/Transcript/Ensembl.js +73 -0
  89. package/{js → src/js}/Track/Model/Transcript.js +3 -1
  90. package/{js → src/js}/Track/Model.js +128 -97
  91. package/{js → src/js}/Track/View/Gene/Ensembl.js +6 -4
  92. package/src/js/Track/View/Gene.js +8 -0
  93. package/{js → src/js}/Track/View/Sequence.js +18 -22
  94. package/src/js/Track/View/SequenceVariation.js +117 -0
  95. package/src/js/Track/View/Transcript/Ensembl.js +17 -0
  96. package/src/js/Track/View/Transcript.js +32 -0
  97. package/{js → src/js}/Track/View.js +200 -159
  98. package/{js → src/js}/Track/library/Chromosome.js +18 -13
  99. package/src/js/Track/library/File/BAM.js +34 -0
  100. package/src/js/Track/library/File/BED.js +27 -0
  101. package/src/js/Track/library/File/BIGBED.js +51 -0
  102. package/src/js/Track/library/File/BIGWIG.js +54 -0
  103. package/src/js/Track/library/File/GFF.js +10 -0
  104. package/{js → src/js}/Track/library/File/VCF.js +29 -22
  105. package/src/js/Track/library/File/WIG.js +8 -0
  106. package/{js → src/js}/Track/library/File.js +4 -2
  107. package/src/js/Track/library/Gene.js +44 -0
  108. package/src/js/Track/library/Graph/Bar.js +263 -0
  109. package/src/js/Track/library/Graph/Line.js +335 -0
  110. package/{js → src/js}/Track/library/Graph.js +137 -114
  111. package/{js → src/js}/Track/library/HighlightRegion.js +118 -93
  112. package/src/js/Track/library/Legend.js +258 -0
  113. package/{js → src/js}/Track/library/Scalebar.js +69 -49
  114. package/{js → src/js}/Track/library/Scaleline.js +29 -27
  115. package/src/js/Track/library/Static.js +82 -0
  116. package/{js → src/js}/Track/library/dbSNP.js +47 -50
  117. package/src/js/Track.js +649 -0
  118. package/{js → src/js}/genomes/grch37.js +52 -52
  119. package/{js → src/js}/genomes/grch38.js +52 -52
  120. package/src/js/lib/BWReader.js +562 -0
  121. package/src/js/lib/VCFReader.js +296 -0
  122. package/src/js/lib/dalliance/bam.js +517 -0
  123. package/src/js/lib/dalliance/bin.js +317 -0
  124. package/src/js/lib/dalliance/jszlib-inflate.js +2159 -0
  125. package/src/js/lib/dalliance/lh3utils.js +105 -0
  126. package/src/js/lib/dalliance/sha1.js +334 -0
  127. package/src/js/lib/import-tracks.js +42 -0
  128. package/{js/lib → src/js/lib/jquery-plugins}/jquery.mousehold.js +0 -0
  129. package/{js/lib → src/js/lib/jquery-plugins}/jquery.mousewheel.js +0 -0
  130. package/{js/lib → src/js/lib/jquery-plugins}/jquery.tipsy.js +0 -0
  131. package/src/js/lib/jquery.js +26 -0
  132. package/src/js/lib/polyfills.js +11 -0
  133. package/src/js/lib/wrap-functions.js +88 -0
  134. package/src/js/plugins/controlPanel.js +388 -0
  135. package/src/js/plugins/fileDrop.js +81 -0
  136. package/src/js/plugins/focusRegion.js +13 -0
  137. package/{js → src/js}/plugins/fullscreen.js +18 -14
  138. package/{js → src/js}/plugins/karyotype.js +51 -45
  139. package/src/js/plugins/resizer.js +52 -0
  140. package/{js → src/js}/plugins/tooltips.js +31 -29
  141. package/src/js/plugins/trackControls.js +159 -0
  142. package/test/View/render-legends.test.js +1 -1
  143. package/test/create-and-destroy.test.js +2 -2
  144. package/test/track-ordering.test.js +3 -2
  145. package/test/track_config/config-settings.test.js +1 -1
  146. package/test/utils.js +4 -2
  147. package/webpack.config.js +103 -34
  148. package/css/font-awesome.css +0 -3
  149. package/expanded.html +0 -120
  150. package/fontawesome/css/fontawesome.min.css +0 -5
  151. package/fontawesome/css/regular.min.css +0 -5
  152. package/fontawesome/css/solid.min.css +0 -5
  153. package/fontawesome/webfonts/fa-brands-400.ttf +0 -0
  154. package/fontawesome/webfonts/fa-brands-400.woff +0 -0
  155. package/fontawesome/webfonts/fa-brands-400.woff2 +0 -0
  156. package/fontawesome/webfonts/fa-regular-400.ttf +0 -0
  157. package/fontawesome/webfonts/fa-regular-400.woff +0 -0
  158. package/fontawesome/webfonts/fa-regular-400.woff2 +0 -0
  159. package/fontawesome/webfonts/fa-solid-900.ttf +0 -0
  160. package/fontawesome/webfonts/fa-solid-900.woff +0 -0
  161. package/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
  162. package/help.pdf +0 -0
  163. package/index.js +0 -83
  164. package/js/Genoverse.js +0 -1681
  165. package/js/Track/Controller/Stranded.js +0 -73
  166. package/js/Track/Model/File/BAM.js +0 -44
  167. package/js/Track/Model/File/BED.js +0 -116
  168. package/js/Track/Model/File/GFF.js +0 -40
  169. package/js/Track/Model/File/VCF.js +0 -101
  170. package/js/Track/Model/File/WIG.js +0 -67
  171. package/js/Track/Model/File.js +0 -36
  172. package/js/Track/Model/Gene/Ensembl.js +0 -22
  173. package/js/Track/Model/Sequence/Ensembl.js +0 -4
  174. package/js/Track/Model/Transcript/Ensembl.js +0 -67
  175. package/js/Track/View/Gene.js +0 -6
  176. package/js/Track/View/Sequence/Variation.js +0 -115
  177. package/js/Track/View/Transcript/Ensembl.js +0 -12
  178. package/js/Track/View/Transcript.js +0 -28
  179. package/js/Track/library/File/BAM.js +0 -30
  180. package/js/Track/library/File/BED.js +0 -24
  181. package/js/Track/library/File/BIGBED.js +0 -47
  182. package/js/Track/library/File/BIGWIG.js +0 -52
  183. package/js/Track/library/File/GFF.js +0 -9
  184. package/js/Track/library/File/WIG.js +0 -5
  185. package/js/Track/library/Gene.js +0 -37
  186. package/js/Track/library/Graph/Bar.js +0 -235
  187. package/js/Track/library/Graph/Line.js +0 -296
  188. package/js/Track/library/Legend.js +0 -224
  189. package/js/Track/library/Static.js +0 -78
  190. package/js/Track.js +0 -632
  191. package/js/genoverse.min.js +0 -2
  192. package/js/genoverse.min.js.map +0 -1
  193. package/js/lib/BWReader.js +0 -578
  194. package/js/lib/Base.js +0 -145
  195. package/js/lib/VCFReader.js +0 -286
  196. package/js/lib/dalliance/js/bam.js +0 -494
  197. package/js/lib/dalliance/js/bin.js +0 -185
  198. package/js/lib/dalliance/js/das.js +0 -749
  199. package/js/lib/dalliance/js/utils.js +0 -370
  200. package/js/lib/dalliance-lib.js +0 -3594
  201. package/js/lib/dalliance-lib.min.js +0 -68
  202. package/js/lib/jDataView.js +0 -2
  203. package/js/lib/jParser.js +0 -192
  204. package/js/lib/jquery-ui.js +0 -8
  205. package/js/lib/jquery.js +0 -2
  206. package/js/lib/rtree.js +0 -1
  207. package/js/plugins/controlPanel.js +0 -395
  208. package/js/plugins/fileDrop.js +0 -62
  209. package/js/plugins/focusRegion.js +0 -12
  210. package/js/plugins/resizer.js +0 -45
  211. package/js/plugins/trackControls.js +0 -143
  212. package/utils/expandedTemplate.html +0 -46
  213. package/utils/git-hooks/post-commit +0 -9
  214. package/utils/git-hooks/pre-commit +0 -7
  215. package/utils/git-hooks/setup +0 -6
  216. package/utils/makeExpanded.js +0 -19
@@ -0,0 +1,562 @@
1
+ import RTree from 'rtree';
2
+ import inflateBuffer from './dalliance/jszlib-inflate';
3
+
4
+ export default function (fileData, callback) {
5
+ const bbi = {
6
+ fetchedData: new RTree(),
7
+ };
8
+
9
+ // constants: bigwig/bigbed file header signatures (magic numbers) (32 bit) , can be swapped ( big-endian | BE )
10
+ const BIG_WIG_MAGIC = 0x888FFC26;
11
+ const BIG_WIG_MAGIC_BE = 0x26FC8F88;
12
+
13
+ const BIG_BED_MAGIC = 0x8789F2EB;
14
+ const BIG_BED_MAGIC_BE = 0xEBF28987;
15
+
16
+ const CIRTREE_MAGIC = 0x78ca8c91;
17
+ const IDXTREE_MAGIC = 0x2468ace0;
18
+
19
+ // type of file converted to bigwig bedgraph |variable step wiggle | fixed step wiggle
20
+ const BIG_WIG_TYPE_GRAPH = 1;
21
+ const BIG_WIG_TYPE_VSTEP = 2;
22
+ const BIG_WIG_TYPE_FSTEP = 3;
23
+
24
+ const M1 = 256;
25
+ const M2 = 256 * 256;
26
+ const M3 = 256 * 256 * 256;
27
+ const M4 = 256 * 256 * 256 * 256;
28
+
29
+ // reads 8 bytes from data
30
+ const read64Bit = (ba, o) => {
31
+ const val = ba[o] + ba[o + 1] * M1 + ba[o + 2] * M2 + ba[o + 3] * M3 + ba[o + 4] * M4;
32
+
33
+ return val;
34
+ };
35
+
36
+ const WiggleParser = (data, query) => {
37
+ const arr = [];
38
+ const ba = new Uint8Array(data);
39
+ const sa = new Int16Array(data);
40
+ const la = new Int32Array(data);
41
+ const fa = new Float32Array(data);
42
+ const chromId = la[0];
43
+ const chr = parseInt(bbi.chroms[chromId].replace('chr', ''), 10);
44
+ const blockStart = la[1] + 1;
45
+ const itemStep = la[3];
46
+ const itemSpan = la[4];
47
+ const blockType = ba[20];
48
+ const itemCount = sa[11];
49
+
50
+ let i;
51
+ let start;
52
+ let end;
53
+ let score;
54
+
55
+ if (blockType === BIG_WIG_TYPE_FSTEP) { // fixedStep wiggle
56
+ for (i = 0; i < itemCount; i++) {
57
+ start = blockStart + i * itemStep;
58
+ end = start + itemSpan - 1;
59
+ score = fa[i + 6];
60
+
61
+ if (chromId == query.chrom) { // eslint-disable-line eqeqeq
62
+ arr.push({
63
+ chr : chr,
64
+ start : start,
65
+ end : end,
66
+ height : score,
67
+ });
68
+ }
69
+ }
70
+ } else if (blockType === BIG_WIG_TYPE_VSTEP) { // variable step wiggle
71
+ for (i = 0; i < itemCount; i++) {
72
+ start = la[i * 2 + 6] + 1;
73
+ end = start + itemSpan - 1;
74
+ score = fa[i * 2 + 7];
75
+
76
+ if (chromId == query.chrom) { // eslint-disable-line eqeqeq
77
+ arr.push({
78
+ chr : chr,
79
+ start : start,
80
+ end : end,
81
+ height : score,
82
+ });
83
+ }
84
+ }
85
+ } else if (blockType === BIG_WIG_TYPE_GRAPH) { // bedGraph
86
+ for (i = 0; i < itemCount; i++) {
87
+ start = la[i * 3 + 6] + 1;
88
+ end = la[i * 3 + 7];
89
+ score = fa[i * 3 + 8];
90
+
91
+ if (start > end) {
92
+ start = end;
93
+ }
94
+
95
+ if (chromId == query.chrom) { // eslint-disable-line eqeqeq
96
+ arr.push({
97
+ chr : chr,
98
+ start : start,
99
+ end : end,
100
+ height : score,
101
+ });
102
+ }
103
+ }
104
+ }
105
+
106
+ return arr;
107
+ };
108
+
109
+ const BEDParser = (data, query) => {
110
+ const arr = [];
111
+ const ba = new Uint8Array(data);
112
+ const la = new Int32Array(data);
113
+
114
+ let offset = 0;
115
+ let bbRecord;
116
+ let ch;
117
+ let rest;
118
+
119
+ while (offset < la.length) {
120
+ bbRecord = {
121
+ chromid : la[offset],
122
+ chr : bbi.chroms[la[offset]],
123
+ start : la[offset + 1],
124
+ end : la[offset + 2],
125
+ };
126
+
127
+ offset += 12;
128
+
129
+ while (true) { // eslint-disable-line no-constant-condition
130
+ ch = ba[offset++];
131
+
132
+ if (ch !== 0) {
133
+ rest += String.fromCharCode(ch);
134
+ } else {
135
+ break;
136
+ }
137
+ }
138
+
139
+ if (bbRecord.chromid === query.chrom) {
140
+ arr.push([ bbRecord.chr, bbRecord.start, bbRecord.end, rest ].join('\t'));
141
+ }
142
+ }
143
+
144
+ return arr;
145
+ };
146
+
147
+ const getData = (start, length, cb) => {
148
+ const end = start + length;
149
+ const fetched = bbi.fetchedData.search({ x: start, w: length, y: 0, h: 1 }).filter(d => d[0] <= start && d[1] >= end);
150
+
151
+ if (fetched.length === 1) {
152
+ cb(fetched[0][2].slice(start - fetched[0][0], start + length));
153
+ } else {
154
+ fileData.slice(start, length).fetch((d) => {
155
+ bbi.fetchedData.insert({ x: start, w: length, y: 0, h: 1 }, [ start, start + length, d ]);
156
+ cb(d);
157
+ });
158
+ }
159
+ };
160
+
161
+ const getRTreeNode = (treedata, offset) => {
162
+ const ba = new Uint8Array(treedata);
163
+ const sa = new Uint16Array(treedata);
164
+ const la = new Uint32Array(treedata);
165
+ const children = sa[offset / 2 + 1];
166
+
167
+ let lo;
168
+ let i;
169
+
170
+ const node = {
171
+ isLeaf : ba[offset],
172
+ children : children,
173
+ chrIdxStart : new Array(children),
174
+ baseStart : new Array(children),
175
+ chrIdxEnd : new Array(children),
176
+ baseEnd : new Array(children),
177
+ dataOffset : new Array(children),
178
+ x : {},
179
+ };
180
+
181
+ if (node.isLeaf) {
182
+ node.x.size = new Array(children);
183
+ } else {
184
+ node.x.child = new Array(children);
185
+
186
+ for (i = 0; i < children; i++) {
187
+ node.x.child[i] = -1;
188
+ }
189
+ }
190
+
191
+ offset += 4;
192
+
193
+ for (i = 0; i < children; i++) {
194
+ lo = offset / 4;
195
+
196
+ node.chrIdxStart[i] = la[lo];
197
+ node.baseStart[i] = la[lo + 1];
198
+ node.chrIdxEnd[i] = la[lo + 2];
199
+ node.baseEnd[i] = la[lo + 3];
200
+ node.dataOffset[i] = read64Bit(ba, offset + 16);
201
+
202
+ offset += 24;
203
+
204
+ if (node.isLeaf) {
205
+ node.x.size[i] = read64Bit(ba, offset);
206
+ offset += 8;
207
+ }
208
+ }
209
+
210
+ return node;
211
+ };
212
+
213
+ const getValues = (chrom, start, end, cb) => {
214
+ const vals = [];
215
+
216
+ let chromid = bbi.chroms.indexOf(chrom);
217
+
218
+ if (chromid === -1) {
219
+ chromid = bbi.chroms.indexOf(`chr${chrom}`);
220
+
221
+ if (chromid === -1) {
222
+ return cb([], 'chrom not found');
223
+ }
224
+ }
225
+
226
+ const query = {
227
+ chrom : chromid,
228
+ start : start,
229
+ end : end,
230
+ };
231
+
232
+ const findOverlaps = (node) => {
233
+ const children = node.children;
234
+ const overlaps = [];
235
+
236
+ for (let i = 0; i < children; i++) {
237
+ const startChrom = node.chrIdxStart[i];
238
+ const startBase = node.baseStart[i];
239
+ const endChrom = node.chrIdxEnd[i];
240
+ const endBase = node.baseEnd[i];
241
+
242
+ if (
243
+ ((startChrom < query.chrom) || (startChrom == query.chrom && startBase <= query.end)) && // eslint-disable-line eqeqeq
244
+ ((endChrom > query.chrom) || (endChrom == query.chrom && endBase >= query.start)) // eslint-disable-line eqeqeq
245
+ ) {
246
+ overlaps.push(i);
247
+ }
248
+ }
249
+
250
+ return overlaps;
251
+ };
252
+
253
+ function traverseRTree() {
254
+ let outstanding = 0;
255
+
256
+ const getBlocks = () => {
257
+ const parser = bbi.type === 'bigwig' ? WiggleParser : bbi.type === 'bigbed' ? BEDParser : false;
258
+
259
+ let result = [];
260
+
261
+ if (parser && vals.length) {
262
+ for (let i = 0; i < vals.length; i++) {
263
+ result = result.concat(parser(vals[i].data, query));
264
+ }
265
+ }
266
+
267
+ cb(result);
268
+ };
269
+
270
+ const fetchBlocks = () => {
271
+ vals.sort((b0, b1) => (b0.offset | 0) - (b1.offset | 0));
272
+
273
+ if (vals.length === 0) {
274
+ return getBlocks();
275
+ }
276
+
277
+ let totalSize = 0;
278
+
279
+ const base = vals[0].offset;
280
+
281
+ for (let i = 0; i < vals.length; i++) {
282
+ totalSize += vals[i].size;
283
+ }
284
+
285
+ getData(base, totalSize, (buffer) => {
286
+ let ioffset = 0;
287
+ let bi = 0;
288
+ let fb;
289
+
290
+ let
291
+ blockData;
292
+
293
+ while (ioffset < totalSize) {
294
+ fb = vals[bi];
295
+
296
+ if (bbi.uncompressBufSize > 0) {
297
+ blockData = inflateBuffer(buffer, ioffset + 2, fb.size - 2);
298
+ } else {
299
+ blockData = buffer.slice(ioffset, ioffset + fb.size);
300
+ }
301
+
302
+ vals[bi].data = blockData;
303
+ ioffset += fb.size;
304
+ bi++;
305
+ }
306
+
307
+ getBlocks();
308
+ });
309
+ };
310
+
311
+ const traverseRTreeChildren = (treedata, offset, level, fetchChildren) => {
312
+ const node = getRTreeNode(treedata, offset);
313
+ const overlaps = findOverlaps(node);
314
+
315
+ let i;
316
+
317
+ if (node.isLeaf) {
318
+ for (i = 0; i < overlaps.length; i++) {
319
+ vals.push({
320
+ offset : node.dataOffset[overlaps[i]],
321
+ size : node.x.size[overlaps[i]],
322
+ });
323
+ }
324
+
325
+ return [];
326
+ }
327
+
328
+ fetchChildren(overlaps.map(o => node.dataOffset[o]), level + 1);
329
+ };
330
+
331
+ const fetchRTreeChildren = (offset, level) => {
332
+ outstanding += offset.length;
333
+
334
+ const min = offset[0];
335
+ const maxNodeSize = 4 + bbi.Rheader.blockSize * 32;
336
+ const max = offset[offset.length - 1] + maxNodeSize;
337
+
338
+ getData(min, max - min, (treedata) => {
339
+ // traverse children
340
+ for (let i = 0; i < offset.length; i++) {
341
+ traverseRTreeChildren(treedata, offset[i] - min, level, fetchRTreeChildren);
342
+
343
+ if (--outstanding === 0) {
344
+ fetchBlocks();
345
+ }
346
+ }
347
+ });
348
+ };
349
+
350
+ fetchRTreeChildren([ bbi.rootOffset ], 1);
351
+ }
352
+
353
+ traverseRTree();
354
+ };
355
+
356
+ // autoSQL could be present in some bigbed files
357
+ const readAutoSQL = (cb) => {
358
+ if (bbi.asOffset === 0) {
359
+ cb(); // no autoSQL present
360
+ } else {
361
+ // autoSQL present, need to parse
362
+ getData(bbi.asOffset, 2048, (d) => {
363
+ const ba = new Uint8Array(d);
364
+
365
+ let s = '';
366
+
367
+ for (let i = 0; i < ba.length; i++) {
368
+ if (ba[i] === 0) {
369
+ break;
370
+ }
371
+
372
+ s += String.fromCharCode(ba[i]);
373
+ }
374
+
375
+ const headerRe = /(\w+)\s+(\w+)\s+("([^"]+)")?\s*\(\s*/;
376
+ const fieldRe = /([\w[]]+)\s+(\w+)\s*;\s*("([^"]+)")?\s*/g;
377
+ const headerMatch = headerRe.exec(s);
378
+
379
+ if (headerMatch) {
380
+ const as = {
381
+ declType : headerMatch[1],
382
+ name : headerMatch[2],
383
+ comment : headerMatch[4],
384
+ fields : [],
385
+ };
386
+
387
+ s = s.substring(headerMatch[0]);
388
+
389
+ for (let m = fieldRe.exec(s); m !== null; m = fieldRe.exec(s)) {
390
+ as.fields.push({
391
+ type : m[1],
392
+ name : m[2],
393
+ comment : m[4],
394
+ });
395
+ }
396
+
397
+ bbi.schema = as;
398
+ }
399
+
400
+ cb();
401
+ });
402
+ }
403
+ };
404
+
405
+ const readRTreeIndex = () => {
406
+ getData(bbi.unzoomedIndexOffset, 48, (d) => {
407
+ const ba = new Uint8Array(d);
408
+ const la = new Uint32Array(d);
409
+ const magic = la[0];
410
+
411
+ if (magic === IDXTREE_MAGIC) {
412
+ bbi.Rheader = {
413
+ blockSize : la[1],
414
+ nItems : read64Bit(ba, 8),
415
+ chrIdxStart : la[4],
416
+ baseStart : la[5],
417
+ chrIdxEnd : la[6],
418
+ baseEnd : la[7],
419
+ endFileOffset : read64Bit(ba, 32),
420
+ nItemsPerSlot : la[10],
421
+ };
422
+
423
+ bbi.rootOffset = bbi.unzoomedIndexOffset + 48;
424
+ bbi.getValues = getValues;
425
+
426
+ callback(bbi);
427
+ } else {
428
+ callback(null, 'R-tree not found!');
429
+ }
430
+ });
431
+ };
432
+
433
+ // reading B+ tree which maps chrom names to ids used in R-tree
434
+ const readChromTree = () => {
435
+ const length = bbi.unzoomedDataOffset - bbi.chromTreeOffset;
436
+
437
+ getData(bbi.chromTreeOffset, length + 4 - (length % 4), (d) => {
438
+ const ba = new Uint8Array(d);
439
+ const sa = new Uint16Array(d);
440
+ const la = new Uint32Array(d);
441
+ const magic = la[0];
442
+
443
+ let error;
444
+
445
+ const readChromTreeLeaf = (nodeOffset) => {
446
+ // padding 8 byte
447
+ let children = sa[(nodeOffset / 2) + 1];
448
+ let offset = nodeOffset + 4;
449
+ let chrom;
450
+ let i;
451
+ let c;
452
+ let idx;
453
+ let len;
454
+
455
+ while (children > 0) {
456
+ children--;
457
+ chrom = '';
458
+
459
+ for (i = 0; i < bbi.bpTree.keySize; i++) {
460
+ c = ba[offset + i];
461
+
462
+ if (c !== 0) {
463
+ chrom += String.fromCharCode(c);
464
+ }
465
+ }
466
+
467
+ offset += bbi.bpTree.keySize;
468
+
469
+ idx = (ba[offset + 3] << 24) | (ba[offset + 2] << 16) | (ba[offset + 1] << 8) | (ba[offset + 0]);
470
+ len = (ba[offset + 7] << 24) | (ba[offset + 6] << 16) | (ba[offset + 5] << 8) | (ba[offset + 4]);
471
+
472
+ offset += 8;
473
+
474
+ bbi.chroms[idx] = chrom;
475
+ bbi.lengths[idx] = len;
476
+ }
477
+ };
478
+
479
+ if (magic === CIRTREE_MAGIC) {
480
+ bbi.bpTree = {
481
+ itemsPerBlock : la[1],
482
+ keySize : la[2],
483
+ valueSize : la[3],
484
+ itemCount : read64Bit(ba, 16),
485
+ };
486
+
487
+ bbi.chroms = new Array(bbi.bpTree.itemCount);
488
+ bbi.lengths = new Array(bbi.bpTree.itemCount);
489
+ } else {
490
+ error = 'chromosome id B+ tree not found!';
491
+ }
492
+
493
+ if (error) {
494
+ callback(null, error);
495
+ } else {
496
+ readChromTreeLeaf(32);
497
+ }
498
+
499
+ readRTreeIndex();
500
+ });
501
+ };
502
+
503
+ const checkSignature = () => {
504
+ getData(0, 512, (header) => {
505
+ const ba = new Uint8Array(header);
506
+ const sa = new Uint16Array(header);
507
+ const la = new Uint32Array(header);
508
+ const magic = la[0];
509
+
510
+ let error;
511
+ let reduction;
512
+ let dataOffset;
513
+ let indexOffset;
514
+
515
+ if (magic === BIG_WIG_MAGIC) {
516
+ bbi.type = 'bigwig';
517
+ } else if (magic === BIG_BED_MAGIC) {
518
+ bbi.type = 'bigbed';
519
+ } else if (magic === BIG_WIG_MAGIC_BE || magic === BIG_BED_MAGIC_BE) {
520
+ error = 'big-endian files not supported yet!';
521
+ } else {
522
+ error = 'unsupported file format';
523
+ }
524
+
525
+ if (error) {
526
+ callback(null, error);
527
+ }
528
+
529
+ bbi.version = sa[2];
530
+ bbi.numZoomLevels = sa[3];
531
+ bbi.chromTreeOffset = read64Bit(ba, 8);
532
+ bbi.unzoomedDataOffset = read64Bit(ba, 16);
533
+ bbi.unzoomedIndexOffset = read64Bit(ba, 24);
534
+ bbi.fieldCount = sa[16];
535
+ bbi.definedFieldCount = sa[17];
536
+ bbi.asOffset = read64Bit(ba, 36);
537
+ bbi.totalSummaryOffset = read64Bit(ba, 44);
538
+ bbi.uncompressBufSize = la[13];
539
+ bbi.extHeaderOffset = read64Bit(ba, 56);
540
+ bbi.compressed = bbi.uncompressBufSize > 0;
541
+ bbi.summary = bbi.totalSummaryOffset > 0;
542
+ bbi.extHeader = bbi.extHeaderOffset > 0;
543
+ bbi.zoomHeaders = [];
544
+
545
+ for (let i = 0; i < bbi.numZoomLevels; i++) {
546
+ reduction = la[16 + 6 * i];
547
+ dataOffset = read64Bit(ba, 72 + 24 * i);
548
+ indexOffset = read64Bit(ba, 80 + 24 * i);
549
+
550
+ bbi.zoomHeaders.push({
551
+ reductionLevel : reduction,
552
+ dataOffset : dataOffset,
553
+ indexOffset : indexOffset,
554
+ });
555
+ }
556
+
557
+ readAutoSQL(readChromTree); // reading autoSQL passing next task as callback
558
+ });
559
+ };
560
+
561
+ checkSignature();
562
+ }