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,517 @@
1
+ // Adapted from https://github.com/dasmoth/dalliance/blob/master/js/bam.js
2
+
3
+ /* -*- mode: javascript; c-basic-offset: 4; indent-tabs-mode: nil -*- */
4
+
5
+ //
6
+ // Dalliance Genome Explorer
7
+ // (c) Thomas Down 2006-2011
8
+ //
9
+ // bam.js: indexed binary alignments
10
+ //
11
+
12
+ import { readInt, readShort, readByte, readFloat } from './bin';
13
+ import { unbgzf, readVob, reg2bins, Chunk } from './lh3utils';
14
+
15
+ var BAM_MAGIC = 0x14d4142;
16
+ var BAI_MAGIC = 0x1494142;
17
+
18
+ var BamFlags = {
19
+ MULTIPLE_SEGMENTS: 0x1,
20
+ ALL_SEGMENTS_ALIGN: 0x2,
21
+ SEGMENT_UNMAPPED: 0x4,
22
+ NEXT_SEGMENT_UNMAPPED: 0x8,
23
+ REVERSE_COMPLEMENT: 0x10,
24
+ NEXT_REVERSE_COMPLEMENT: 0x20,
25
+ FIRST_SEGMENT: 0x40,
26
+ LAST_SEGMENT: 0x80,
27
+ SECONDARY_ALIGNMENT: 0x100,
28
+ QC_FAIL: 0x200,
29
+ DUPLICATE: 0x400,
30
+ SUPPLEMENTARY: 0x800
31
+ };
32
+
33
+ function BamFile() {
34
+ }
35
+
36
+
37
+ // Calculate the length (in bytes) of the BAI ref starting at offset.
38
+ // Returns {nbin, length, minBlockIndex}
39
+ function _getBaiRefLength(uncba, offset) {
40
+ var p = offset;
41
+ var nbin = readInt(uncba, p); p += 4;
42
+ for (var b = 0; b < nbin; ++b) {
43
+ var bin = readInt(uncba, p);
44
+ var nchnk = readInt(uncba, p+4);
45
+ p += 8 + (nchnk * 16);
46
+ }
47
+ var nintv = readInt(uncba, p); p += 4;
48
+
49
+ var minBlockIndex = 1000000000;
50
+ var q = p;
51
+ for (var i = 0; i < nintv; ++i) {
52
+ var v = readVob(uncba, q); q += 8;
53
+ if (v) {
54
+ var bi = v.block;
55
+ if (v.offset > 0)
56
+ bi += 65536;
57
+
58
+ if (bi < minBlockIndex)
59
+ minBlockIndex = bi;
60
+ break;
61
+ }
62
+ }
63
+ p += (nintv * 8);
64
+
65
+ return {
66
+ minBlockIndex: minBlockIndex,
67
+ nbin: nbin,
68
+ length: p - offset
69
+ };
70
+ }
71
+
72
+
73
+ function makeBam(data, bai, indexChunks, callback, attempted) {
74
+ // Do an initial probe on the BAM file to catch any mixed-content errors.
75
+ data.slice(0, 10).fetch(function(header) {
76
+ if (header) {
77
+ return makeBam2(data, bai, indexChunks, callback, attempted);
78
+ } else {
79
+ return callback(null, "Couldn't access BAM.");
80
+ }
81
+ }, {timeout: 5000});
82
+ }
83
+
84
+ function makeBam2(data, bai, indexChunks, callback, attempted) {
85
+ var bam = new BamFile();
86
+ bam.data = data;
87
+ bam.bai = bai;
88
+ bam.indexChunks = indexChunks;
89
+
90
+ var minBlockIndex = bam.indexChunks ? bam.indexChunks.minBlockIndex : 1000000000;
91
+
92
+ // Fills out bam.chrToIndex and bam.indexToChr based on the first few bytes of the BAM.
93
+ function parseBamHeader(r) {
94
+ if (!r) {
95
+ return callback(null, "Couldn't access BAM");
96
+ }
97
+
98
+ var unc = unbgzf(r, r.byteLength);
99
+ var uncba = new Uint8Array(unc);
100
+
101
+ var magic = readInt(uncba, 0);
102
+ if (magic != BAM_MAGIC) {
103
+ return callback(null, "Not a BAM file, magic=0x" + magic.toString(16));
104
+ }
105
+ var headLen = readInt(uncba, 4);
106
+ var header = '';
107
+ for (var i = 0; i < headLen; ++i) {
108
+ header += String.fromCharCode(uncba[i + 8]);
109
+ }
110
+
111
+ var nRef = readInt(uncba, headLen + 8);
112
+ var p = headLen + 12;
113
+
114
+ bam.chrToIndex = {};
115
+ bam.indexToChr = [];
116
+ for (var i = 0; i < nRef; ++i) {
117
+ var lName = readInt(uncba, p);
118
+ var name = '';
119
+ for (var j = 0; j < lName-1; ++j) {
120
+ name += String.fromCharCode(uncba[p + 4 + j]);
121
+ }
122
+ var lRef = readInt(uncba, p + lName + 4);
123
+ bam.chrToIndex[name] = i;
124
+ if (name.indexOf('chr') == 0) {
125
+ bam.chrToIndex[name.substring(3)] = i;
126
+ } else {
127
+ bam.chrToIndex['chr' + name] = i;
128
+ }
129
+ bam.indexToChr.push(name);
130
+
131
+ p = p + 8 + lName;
132
+ }
133
+
134
+ if (bam.indices) {
135
+ return callback(bam);
136
+ }
137
+ }
138
+
139
+ function parseBai(header) {
140
+ if (!header) {
141
+ return "Couldn't access BAI";
142
+ }
143
+
144
+ var uncba = new Uint8Array(header);
145
+ var baiMagic = readInt(uncba, 0);
146
+ if (baiMagic != BAI_MAGIC) {
147
+ return callback(null, 'Not a BAI file, magic=0x' + baiMagic.toString(16));
148
+ }
149
+
150
+ var nref = readInt(uncba, 4);
151
+
152
+ bam.indices = [];
153
+
154
+ var p = 8;
155
+ for (var ref = 0; ref < nref; ++ref) {
156
+ var blockStart = p;
157
+ var o = _getBaiRefLength(uncba, blockStart);
158
+ p += o.length;
159
+
160
+ minBlockIndex = Math.min(o.minBlockIndex, minBlockIndex);
161
+
162
+ var nbin = o.nbin;
163
+
164
+ if (nbin > 0) {
165
+ bam.indices[ref] = new Uint8Array(header, blockStart, p - blockStart);
166
+ }
167
+ }
168
+
169
+ return true;
170
+ }
171
+
172
+ if (!bam.indexChunks) {
173
+ bam.bai.fetch(function(header) { // Do we really need to fetch the whole thing? :-(
174
+ var result = parseBai(header);
175
+ if (result !== true) {
176
+ if (bam.bai.url && typeof(attempted) === "undefined") {
177
+ // Already attempted x.bam.bai not there so now trying x.bai
178
+ bam.bai.url = bam.data.url.replace(new RegExp('.bam$'), '.bai');
179
+
180
+ // True lets us know we are making a second attempt
181
+ makeBam2(data, bam.bai, indexChunks, callback, true);
182
+ }
183
+ else {
184
+ // We've attempted x.bam.bai & x.bai and nothing worked
185
+ callback(null, result);
186
+ }
187
+ } else {
188
+ bam.data.slice(0, minBlockIndex).fetch(parseBamHeader);
189
+ }
190
+ }); // Timeout on first request to catch Chrome mixed-content error.
191
+ } else {
192
+ var chunks = bam.indexChunks.chunks;
193
+ bam.indices = []
194
+ for (var i = 0; i < chunks.length; i++) {
195
+ bam.indices[i] = null; // To be filled out lazily as needed
196
+ }
197
+ bam.data.slice(0, minBlockIndex).fetch(parseBamHeader);
198
+ }
199
+ }
200
+
201
+
202
+
203
+ BamFile.prototype.blocksForRange = function(refId, min, max) {
204
+ var index = this.indices[refId];
205
+ if (!index) {
206
+ return [];
207
+ }
208
+
209
+ var intBinsL = reg2bins(min, max);
210
+ var intBins = [];
211
+ for (var i = 0; i < intBinsL.length; ++i) {
212
+ intBins[intBinsL[i]] = true;
213
+ }
214
+ var leafChunks = [], otherChunks = [];
215
+
216
+ var nbin = readInt(index, 0);
217
+ var p = 4;
218
+ for (var b = 0; b < nbin; ++b) {
219
+ var bin = readInt(index, p);
220
+ var nchnk = readInt(index, p+4);
221
+ // dlog('bin=' + bin + '; nchnk=' + nchnk);
222
+ p += 8;
223
+ if (intBins[bin]) {
224
+ for (var c = 0; c < nchnk; ++c) {
225
+ var cs = readVob(index, p);
226
+ var ce = readVob(index, p + 8);
227
+ (bin < 4681 ? otherChunks : leafChunks).push(new Chunk(cs, ce));
228
+ p += 16;
229
+ }
230
+ } else {
231
+ p += (nchnk * 16);
232
+ }
233
+ }
234
+ // console.log('leafChunks = ' + JSON.stringify(leafChunks));
235
+ // console.log('otherChunks = ' + JSON.stringify(otherChunks));
236
+
237
+ var nintv = readInt(index, p);
238
+ // console.log('nintv=' + nintv);
239
+ var lowest = null;
240
+ var minLin = Math.min(min>>14, nintv - 1), maxLin = Math.min(max>>14, nintv - 1);
241
+ for (var i = minLin; i <= maxLin; ++i) {
242
+ var lb = readVob(index, p + 4 + (i * 8));
243
+ if (!lb) {
244
+ continue;
245
+ }
246
+ if (!lowest || lb.block < lowest.block || (lb.block == lowest.block && lb.offset < lowest.offset)) {
247
+ lowest = lb;
248
+ }
249
+ }
250
+ // console.log('Lowest LB = ' + lowest);
251
+
252
+ var prunedOtherChunks = [];
253
+ if (lowest != null) {
254
+ for (var i = 0; i < otherChunks.length; ++i) {
255
+ var chnk = otherChunks[i];
256
+ if (chnk.maxv.block > lowest.block || (chnk.maxv.block == lowest.block && chnk.maxv.offset >= lowest.offset)) {
257
+ prunedOtherChunks.push(chnk);
258
+ }
259
+ }
260
+ }
261
+ // console.log('prunedOtherChunks = ' + JSON.stringify(prunedOtherChunks));
262
+ otherChunks = prunedOtherChunks;
263
+
264
+ var intChunks = [];
265
+ for (var i = 0; i < otherChunks.length; ++i) {
266
+ intChunks.push(otherChunks[i]);
267
+ }
268
+ for (var i = 0; i < leafChunks.length; ++i) {
269
+ intChunks.push(leafChunks[i]);
270
+ }
271
+
272
+ intChunks.sort(function(c0, c1) {
273
+ var dif = c0.minv.block - c1.minv.block;
274
+ if (dif != 0) {
275
+ return dif;
276
+ } else {
277
+ return c0.minv.offset - c1.minv.offset;
278
+ }
279
+ });
280
+ var mergedChunks = [];
281
+ if (intChunks.length > 0) {
282
+ var cur = intChunks[0];
283
+ for (var i = 1; i < intChunks.length; ++i) {
284
+ var nc = intChunks[i];
285
+ if (nc.minv.block == cur.maxv.block /* && nc.minv.offset == cur.maxv.offset */) { // no point splitting mid-block
286
+ cur = new Chunk(cur.minv, nc.maxv);
287
+ } else {
288
+ mergedChunks.push(cur);
289
+ cur = nc;
290
+ }
291
+ }
292
+ mergedChunks.push(cur);
293
+ }
294
+ // console.log('mergedChunks = ' + JSON.stringify(mergedChunks));
295
+
296
+ return mergedChunks;
297
+ }
298
+
299
+ BamFile.prototype.fetch = function(chr, min, max, callback, opts) {
300
+ var thisB = this;
301
+ opts = opts || {};
302
+
303
+ var chrId = this.chrToIndex[chr];
304
+ var chunks;
305
+ if (chrId === undefined) {
306
+ chunks = [];
307
+ } else {
308
+ // Fetch this portion of the BAI if it hasn't been loaded yet.
309
+ if (this.indices[chrId] === null && this.indexChunks.chunks[chrId]) {
310
+ var start_stop = this.indexChunks.chunks[chrId];
311
+ return this.bai.slice(start_stop[0], start_stop[1]).fetch(function(data) {
312
+ var buffer = new Uint8Array(data);
313
+ this.indices[chrId] = buffer;
314
+ return this.fetch(chr, min, max, callback, opts);
315
+ }.bind(this));
316
+ }
317
+
318
+ chunks = this.blocksForRange(chrId, min, max);
319
+ if (!chunks) {
320
+ callback(null, 'Error in index fetch');
321
+ }
322
+ }
323
+
324
+ var records = [];
325
+ var index = 0;
326
+ var data;
327
+
328
+ function tramp() {
329
+ if (index >= chunks.length) {
330
+ return callback(records);
331
+ } else if (!data) {
332
+ var c = chunks[index];
333
+ var fetchMin = c.minv.block;
334
+ var fetchMax = c.maxv.block + (1<<16); // *sigh*
335
+ // console.log('fetching ' + fetchMin + ':' + fetchMax);
336
+ thisB.data.slice(fetchMin, fetchMax - fetchMin).fetch(function(r) {
337
+ data = unbgzf(r, c.maxv.block - c.minv.block + 1);
338
+ return tramp();
339
+ });
340
+ } else {
341
+ var ba = new Uint8Array(data);
342
+ var finished = thisB.readBamRecords(ba, chunks[index].minv.offset, records, min, max, chrId, opts);
343
+ data = null;
344
+ ++index;
345
+ if (finished)
346
+ return callback(records);
347
+ else
348
+ return tramp();
349
+ }
350
+ }
351
+ tramp();
352
+ }
353
+
354
+ var SEQRET_DECODER = ['=', 'A', 'C', 'x', 'G', 'x', 'x', 'x', 'T', 'x', 'x', 'x', 'x', 'x', 'x', 'N'];
355
+ var CIGAR_DECODER = ['M', 'I', 'D', 'N', 'S', 'H', 'P', '=', 'X', '?', '?', '?', '?', '?', '?', '?'];
356
+
357
+ function BamRecord() {
358
+ }
359
+
360
+ BamFile.prototype.readBamRecords = function(ba, offset, sink, min, max, chrId, opts) {
361
+ while (true) {
362
+ var blockSize = readInt(ba, offset);
363
+ var blockEnd = offset + blockSize + 4;
364
+ if (blockEnd > ba.length) {
365
+ return false;
366
+ }
367
+
368
+ var record = new BamRecord();
369
+
370
+ var refID = readInt(ba, offset + 4);
371
+ var pos = readInt(ba, offset + 8);
372
+
373
+ var bmn = readInt(ba, offset + 12);
374
+ var bin = (bmn & 0xffff0000) >> 16;
375
+ var mq = (bmn & 0xff00) >> 8;
376
+ var nl = bmn & 0xff;
377
+
378
+ var flag_nc = readInt(ba, offset + 16);
379
+ var flag = (flag_nc & 0xffff0000) >> 16;
380
+ var nc = flag_nc & 0xffff;
381
+
382
+ var lseq = readInt(ba, offset + 20);
383
+
384
+ var nextRef = readInt(ba, offset + 24);
385
+ var nextPos = readInt(ba, offset + 28);
386
+
387
+ var tlen = readInt(ba, offset + 32);
388
+
389
+ record.segment = this.indexToChr[refID];
390
+ record.flag = flag;
391
+ record.pos = pos;
392
+ record.mq = mq;
393
+ if (opts.light)
394
+ record.seqLength = lseq;
395
+
396
+ if (!opts.light || opts.includeName) {
397
+ var readName = '';
398
+ for (var j = 0; j < nl-1; ++j) {
399
+ readName += String.fromCharCode(ba[offset + 36 + j]);
400
+ }
401
+ record.readName = readName;
402
+ }
403
+
404
+ if (!opts.light) {
405
+ if (nextRef >= 0) {
406
+ record.nextSegment = this.indexToChr[nextRef];
407
+ record.nextPos = nextPos;
408
+ }
409
+
410
+ var p = offset + 36 + nl;
411
+
412
+ var cigar = '';
413
+ for (var c = 0; c < nc; ++c) {
414
+ var cigop = readInt(ba, p);
415
+ cigar = cigar + (cigop>>4) + CIGAR_DECODER[cigop & 0xf];
416
+ p += 4;
417
+ }
418
+ record.cigar = cigar;
419
+
420
+ var seq = '';
421
+ var seqBytes = (lseq + 1) >> 1;
422
+ for (var j = 0; j < seqBytes; ++j) {
423
+ var sb = ba[p + j];
424
+ seq += SEQRET_DECODER[(sb & 0xf0) >> 4];
425
+ if (seq.length < lseq)
426
+ seq += SEQRET_DECODER[(sb & 0x0f)];
427
+ }
428
+ p += seqBytes;
429
+ record.seq = seq;
430
+
431
+ var qseq = '';
432
+ for (var j = 0; j < lseq; ++j) {
433
+ qseq += String.fromCharCode(ba[p + j] + 33);
434
+ }
435
+ p += lseq;
436
+ record.quals = qseq;
437
+
438
+ while (p < blockEnd) {
439
+ var tag = String.fromCharCode(ba[p], ba[p + 1]);
440
+ var type = String.fromCharCode(ba[p + 2]);
441
+ var value;
442
+
443
+ if (type == 'A') {
444
+ value = String.fromCharCode(ba[p + 3]);
445
+ p += 4;
446
+ } else if (type == 'i' || type == 'I') {
447
+ value = readInt(ba, p + 3);
448
+ p += 7;
449
+ } else if (type == 'c' || type == 'C') {
450
+ value = ba[p + 3];
451
+ p += 4;
452
+ } else if (type == 's' || type == 'S') {
453
+ value = readShort(ba, p + 3);
454
+ p += 5;
455
+ } else if (type == 'f') {
456
+ value = readFloat(ba, p + 3);
457
+ p += 7;
458
+ } else if (type == 'Z' || type == 'H') {
459
+ p += 3;
460
+ value = '';
461
+ for (;;) {
462
+ var cc = ba[p++];
463
+ if (cc == 0) {
464
+ break;
465
+ } else {
466
+ value += String.fromCharCode(cc);
467
+ }
468
+ }
469
+ } else if (type == 'B') {
470
+ var atype = String.fromCharCode(ba[p + 3]);
471
+ var alen = readInt(ba, p + 4);
472
+ var elen;
473
+ var reader;
474
+ if (atype == 'i' || atype == 'I' || atype == 'f') {
475
+ elen = 4;
476
+ if (atype == 'f')
477
+ reader = readFloat;
478
+ else
479
+ reader = readInt;
480
+ } else if (atype == 's' || atype == 'S') {
481
+ elen = 2;
482
+ reader = readShort;
483
+ } else if (atype == 'c' || atype == 'C') {
484
+ elen = 1;
485
+ reader = readByte;
486
+ } else {
487
+ throw 'Unknown array type ' + atype;
488
+ }
489
+
490
+ p += 8;
491
+ value = [];
492
+ for (var i = 0; i < alen; ++i) {
493
+ value.push(reader(ba, p));
494
+ p += elen;
495
+ }
496
+ } else {
497
+ throw 'Unknown type '+ type;
498
+ }
499
+ record[tag] = value;
500
+ }
501
+ }
502
+
503
+ if (!min || record.pos <= max && record.pos + lseq >= min) {
504
+ if (chrId === undefined || refID == chrId) {
505
+ sink.push(record);
506
+ }
507
+ }
508
+ if (record.pos > max) {
509
+ return true;
510
+ }
511
+ offset = blockEnd;
512
+ }
513
+
514
+ // Exits via top of loop.
515
+ };
516
+
517
+ export default makeBam;