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,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;