genoverse 3.2.0 → 4.0.1

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 (217) 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 +174 -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 +125 -93
  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 +651 -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/change-width.test.js +71 -0
  144. package/test/create-and-destroy.test.js +2 -2
  145. package/test/track-ordering.test.js +3 -2
  146. package/test/track_config/config-settings.test.js +1 -1
  147. package/test/utils.js +4 -2
  148. package/webpack.config.js +103 -34
  149. package/css/font-awesome.css +0 -3
  150. package/expanded.html +0 -120
  151. package/fontawesome/css/fontawesome.min.css +0 -5
  152. package/fontawesome/css/regular.min.css +0 -5
  153. package/fontawesome/css/solid.min.css +0 -5
  154. package/fontawesome/webfonts/fa-brands-400.ttf +0 -0
  155. package/fontawesome/webfonts/fa-brands-400.woff +0 -0
  156. package/fontawesome/webfonts/fa-brands-400.woff2 +0 -0
  157. package/fontawesome/webfonts/fa-regular-400.ttf +0 -0
  158. package/fontawesome/webfonts/fa-regular-400.woff +0 -0
  159. package/fontawesome/webfonts/fa-regular-400.woff2 +0 -0
  160. package/fontawesome/webfonts/fa-solid-900.ttf +0 -0
  161. package/fontawesome/webfonts/fa-solid-900.woff +0 -0
  162. package/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
  163. package/help.pdf +0 -0
  164. package/index.js +0 -83
  165. package/js/Genoverse.js +0 -1681
  166. package/js/Track/Controller/Stranded.js +0 -73
  167. package/js/Track/Model/File/BAM.js +0 -44
  168. package/js/Track/Model/File/BED.js +0 -116
  169. package/js/Track/Model/File/GFF.js +0 -40
  170. package/js/Track/Model/File/VCF.js +0 -101
  171. package/js/Track/Model/File/WIG.js +0 -67
  172. package/js/Track/Model/File.js +0 -36
  173. package/js/Track/Model/Gene/Ensembl.js +0 -22
  174. package/js/Track/Model/Sequence/Ensembl.js +0 -4
  175. package/js/Track/Model/Transcript/Ensembl.js +0 -67
  176. package/js/Track/View/Gene.js +0 -6
  177. package/js/Track/View/Sequence/Variation.js +0 -115
  178. package/js/Track/View/Transcript/Ensembl.js +0 -12
  179. package/js/Track/View/Transcript.js +0 -28
  180. package/js/Track/library/File/BAM.js +0 -30
  181. package/js/Track/library/File/BED.js +0 -24
  182. package/js/Track/library/File/BIGBED.js +0 -47
  183. package/js/Track/library/File/BIGWIG.js +0 -52
  184. package/js/Track/library/File/GFF.js +0 -9
  185. package/js/Track/library/File/WIG.js +0 -5
  186. package/js/Track/library/Gene.js +0 -37
  187. package/js/Track/library/Graph/Bar.js +0 -235
  188. package/js/Track/library/Graph/Line.js +0 -296
  189. package/js/Track/library/Legend.js +0 -224
  190. package/js/Track/library/Static.js +0 -78
  191. package/js/Track.js +0 -632
  192. package/js/genoverse.min.js +0 -2
  193. package/js/genoverse.min.js.map +0 -1
  194. package/js/lib/BWReader.js +0 -578
  195. package/js/lib/Base.js +0 -145
  196. package/js/lib/VCFReader.js +0 -286
  197. package/js/lib/dalliance/js/bam.js +0 -494
  198. package/js/lib/dalliance/js/bin.js +0 -185
  199. package/js/lib/dalliance/js/das.js +0 -749
  200. package/js/lib/dalliance/js/utils.js +0 -370
  201. package/js/lib/dalliance-lib.js +0 -3594
  202. package/js/lib/dalliance-lib.min.js +0 -68
  203. package/js/lib/jDataView.js +0 -2
  204. package/js/lib/jParser.js +0 -192
  205. package/js/lib/jquery-ui.js +0 -8
  206. package/js/lib/jquery.js +0 -2
  207. package/js/lib/rtree.js +0 -1
  208. package/js/plugins/controlPanel.js +0 -395
  209. package/js/plugins/fileDrop.js +0 -62
  210. package/js/plugins/focusRegion.js +0 -12
  211. package/js/plugins/resizer.js +0 -45
  212. package/js/plugins/trackControls.js +0 -143
  213. package/utils/expandedTemplate.html +0 -46
  214. package/utils/git-hooks/post-commit +0 -9
  215. package/utils/git-hooks/pre-commit +0 -7
  216. package/utils/git-hooks/setup +0 -6
  217. 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
+ }