igv 2.13.6 → 2.13.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/dist/igv.esm.js +474 -229
- package/dist/igv.esm.min.js +8 -8
- package/dist/igv.esm.min.js.map +1 -1
- package/dist/igv.js +478 -222
- package/dist/igv.min.js +6 -6
- package/dist/igv.min.js.map +1 -1
- package/package.json +1 -1
package/dist/igv.esm.js
CHANGED
|
@@ -8482,8 +8482,8 @@ function encode(objectName) {
|
|
|
8482
8482
|
|
|
8483
8483
|
let result = '';
|
|
8484
8484
|
objectName.split('').forEach(function(letter) {
|
|
8485
|
-
if(encodings$
|
|
8486
|
-
result += encodings$
|
|
8485
|
+
if(encodings$2.has(letter)) {
|
|
8486
|
+
result += encodings$2.get(letter);
|
|
8487
8487
|
} else {
|
|
8488
8488
|
result += letter;
|
|
8489
8489
|
}
|
|
@@ -8492,27 +8492,27 @@ function encode(objectName) {
|
|
|
8492
8492
|
}
|
|
8493
8493
|
|
|
8494
8494
|
// %23 %24 %25 %26 %27 %28 %29 %2A %2B %2C %2F %3A %3B %3D %3F %40 %5B %5D
|
|
8495
|
-
const encodings$
|
|
8496
|
-
encodings$
|
|
8497
|
-
encodings$
|
|
8498
|
-
encodings$
|
|
8499
|
-
encodings$
|
|
8500
|
-
encodings$
|
|
8501
|
-
encodings$
|
|
8502
|
-
encodings$
|
|
8503
|
-
encodings$
|
|
8504
|
-
encodings$
|
|
8505
|
-
encodings$
|
|
8506
|
-
encodings$
|
|
8507
|
-
encodings$
|
|
8508
|
-
encodings$
|
|
8509
|
-
encodings$
|
|
8510
|
-
encodings$
|
|
8511
|
-
encodings$
|
|
8512
|
-
encodings$
|
|
8513
|
-
encodings$
|
|
8514
|
-
encodings$
|
|
8515
|
-
encodings$
|
|
8495
|
+
const encodings$2 = new Map();
|
|
8496
|
+
encodings$2.set("!", "%21");
|
|
8497
|
+
encodings$2.set("#", "%23");
|
|
8498
|
+
encodings$2.set("$", "%24");
|
|
8499
|
+
encodings$2.set("%", "%25");
|
|
8500
|
+
encodings$2.set("&", "%26");
|
|
8501
|
+
encodings$2.set("'", "%27");
|
|
8502
|
+
encodings$2.set("(", "%28");
|
|
8503
|
+
encodings$2.set(")", "%29");
|
|
8504
|
+
encodings$2.set("*", "%2A");
|
|
8505
|
+
encodings$2.set("+", "%2B");
|
|
8506
|
+
encodings$2.set(",", "%2C");
|
|
8507
|
+
encodings$2.set("/", "%2F");
|
|
8508
|
+
encodings$2.set(":", "%3A");
|
|
8509
|
+
encodings$2.set(";", "%3B");
|
|
8510
|
+
encodings$2.set("=", "%3D");
|
|
8511
|
+
encodings$2.set("?", "%3F");
|
|
8512
|
+
encodings$2.set("@", "%40");
|
|
8513
|
+
encodings$2.set("[", "%5B");
|
|
8514
|
+
encodings$2.set("]", "%5D");
|
|
8515
|
+
encodings$2.set(" ", "%20");
|
|
8516
8516
|
|
|
8517
8517
|
// Convenience functions for the gapi oAuth library.
|
|
8518
8518
|
|
|
@@ -15473,7 +15473,7 @@ function download(filename, data) {
|
|
|
15473
15473
|
|
|
15474
15474
|
const { Deflate, deflate, deflateRaw, gzip } = deflate_1$1;
|
|
15475
15475
|
|
|
15476
|
-
const { Inflate, inflate: inflate$3, inflateRaw, ungzip: ungzip$2 } = inflate_1$1;
|
|
15476
|
+
const { Inflate, inflate: inflate$3, inflateRaw: inflateRaw$2, ungzip: ungzip$2 } = inflate_1$1;
|
|
15477
15477
|
|
|
15478
15478
|
|
|
15479
15479
|
|
|
@@ -15483,7 +15483,7 @@ function download(filename, data) {
|
|
|
15483
15483
|
var gzip_1 = gzip;
|
|
15484
15484
|
var Inflate_1 = Inflate;
|
|
15485
15485
|
var inflate_1 = inflate$3;
|
|
15486
|
-
var inflateRaw_1 = inflateRaw;
|
|
15486
|
+
var inflateRaw_1 = inflateRaw$2;
|
|
15487
15487
|
var ungzip_1 = ungzip$2;
|
|
15488
15488
|
var constants_1 = constants$2;
|
|
15489
15489
|
|
|
@@ -15517,7 +15517,7 @@ function download(filename, data) {
|
|
|
15517
15517
|
|
|
15518
15518
|
pako.deflateRaw;
|
|
15519
15519
|
pako.deflate;
|
|
15520
|
-
pako.inflateRaw;
|
|
15520
|
+
const inflateRaw = pako.inflateRaw;
|
|
15521
15521
|
const inflate = pako.inflate;
|
|
15522
15522
|
pako.gzip;
|
|
15523
15523
|
|
|
@@ -15595,7 +15595,7 @@ function unbgzf(data, lim) {
|
|
|
15595
15595
|
}
|
|
15596
15596
|
}
|
|
15597
15597
|
|
|
15598
|
-
function bgzBlockSize(data) {
|
|
15598
|
+
function bgzBlockSize$1(data) {
|
|
15599
15599
|
const ba = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
|
|
15600
15600
|
const bsize = (ba[17] << 8 | ba[16]) + 1;
|
|
15601
15601
|
return bsize;
|
|
@@ -19700,27 +19700,27 @@ function createMenuElements$1(itemList, popover) {
|
|
|
19700
19700
|
}
|
|
19701
19701
|
|
|
19702
19702
|
// %23 %24 %25 %26 %27 %28 %29 %2A %2B %2C %2F %3A %3B %3D %3F %40 %5B %5D
|
|
19703
|
-
const encodings = new Map();
|
|
19704
|
-
encodings.set("!", "%21");
|
|
19705
|
-
encodings.set("#", "%23");
|
|
19706
|
-
encodings.set("$", "%24");
|
|
19707
|
-
encodings.set("%", "%25");
|
|
19708
|
-
encodings.set("&", "%26");
|
|
19709
|
-
encodings.set("'", "%27");
|
|
19710
|
-
encodings.set("(", "%28");
|
|
19711
|
-
encodings.set(")", "%29");
|
|
19712
|
-
encodings.set("*", "%2A");
|
|
19713
|
-
encodings.set("+", "%2B");
|
|
19714
|
-
encodings.set(",", "%2C");
|
|
19715
|
-
encodings.set("/", "%2F");
|
|
19716
|
-
encodings.set(":", "%3A");
|
|
19717
|
-
encodings.set(";", "%3B");
|
|
19718
|
-
encodings.set("=", "%3D");
|
|
19719
|
-
encodings.set("?", "%3F");
|
|
19720
|
-
encodings.set("@", "%40");
|
|
19721
|
-
encodings.set("[", "%5B");
|
|
19722
|
-
encodings.set("]", "%5D");
|
|
19723
|
-
encodings.set(" ", "%20");
|
|
19703
|
+
const encodings$1 = new Map();
|
|
19704
|
+
encodings$1.set("!", "%21");
|
|
19705
|
+
encodings$1.set("#", "%23");
|
|
19706
|
+
encodings$1.set("$", "%24");
|
|
19707
|
+
encodings$1.set("%", "%25");
|
|
19708
|
+
encodings$1.set("&", "%26");
|
|
19709
|
+
encodings$1.set("'", "%27");
|
|
19710
|
+
encodings$1.set("(", "%28");
|
|
19711
|
+
encodings$1.set(")", "%29");
|
|
19712
|
+
encodings$1.set("*", "%2A");
|
|
19713
|
+
encodings$1.set("+", "%2B");
|
|
19714
|
+
encodings$1.set(",", "%2C");
|
|
19715
|
+
encodings$1.set("/", "%2F");
|
|
19716
|
+
encodings$1.set(":", "%3A");
|
|
19717
|
+
encodings$1.set(";", "%3B");
|
|
19718
|
+
encodings$1.set("=", "%3D");
|
|
19719
|
+
encodings$1.set("?", "%3F");
|
|
19720
|
+
encodings$1.set("@", "%40");
|
|
19721
|
+
encodings$1.set("[", "%5B");
|
|
19722
|
+
encodings$1.set("]", "%5D");
|
|
19723
|
+
encodings$1.set(" ", "%20");
|
|
19724
19724
|
|
|
19725
19725
|
if (typeof process === 'object' && typeof window === 'undefined') {
|
|
19726
19726
|
global.atob = function (str) {
|
|
@@ -20792,7 +20792,7 @@ function buildOptions(config, options) {
|
|
|
20792
20792
|
const doAutoscale = function (features) {
|
|
20793
20793
|
var min, max;
|
|
20794
20794
|
|
|
20795
|
-
if (features.length > 0) {
|
|
20795
|
+
if (features && features.length > 0) {
|
|
20796
20796
|
min = Number.MAX_VALUE;
|
|
20797
20797
|
max = -Number.MAX_VALUE;
|
|
20798
20798
|
|
|
@@ -24215,7 +24215,7 @@ const Cytoband = function (start, end, name, typestain) {
|
|
|
24215
24215
|
}
|
|
24216
24216
|
};
|
|
24217
24217
|
|
|
24218
|
-
const _version = "2.13.
|
|
24218
|
+
const _version = "2.13.8";
|
|
24219
24219
|
function version() {
|
|
24220
24220
|
return _version
|
|
24221
24221
|
}
|
|
@@ -25949,7 +25949,7 @@ function decode(tokens, header) {
|
|
|
25949
25949
|
|
|
25950
25950
|
const delim = ('gff3' === format) ? '=' : ' ';
|
|
25951
25951
|
return new GFFFeature({
|
|
25952
|
-
source: tokens[1],
|
|
25952
|
+
source: decodeGFFAttribute(tokens[1]),
|
|
25953
25953
|
type: tokens[2],
|
|
25954
25954
|
chr: tokens[0],
|
|
25955
25955
|
start: parseInt(tokens[3]) - 1,
|
|
@@ -26060,7 +26060,7 @@ function parseAttributeString(attributeString, keyValueDelim) {
|
|
|
26060
26060
|
const idx = kv.indexOf(keyValueDelim);
|
|
26061
26061
|
if (idx > 0 && idx < kv.length - 1) {
|
|
26062
26062
|
const key = kv.substring(0, idx);
|
|
26063
|
-
let value = stripQuotes(
|
|
26063
|
+
let value = stripQuotes(decodeGFFAttribute(kv.substring(idx + 1).trim()));
|
|
26064
26064
|
attributes.push([key, value]);
|
|
26065
26065
|
}
|
|
26066
26066
|
}
|
|
@@ -26074,6 +26074,55 @@ function stripQuotes(value) {
|
|
|
26074
26074
|
return value
|
|
26075
26075
|
}
|
|
26076
26076
|
|
|
26077
|
+
// GFF3 attributes have specific percent encoding rules, the list below are required, all others are forbidden
|
|
26078
|
+
/*
|
|
26079
|
+
tab (%09)
|
|
26080
|
+
newline (%0A)
|
|
26081
|
+
carriage return (%0D)
|
|
26082
|
+
% percent (%25)
|
|
26083
|
+
control characters (%00 through %1F, %7F)
|
|
26084
|
+
In addition, the following characters have reserved meanings in column 9 and must be escaped when used in other contexts:
|
|
26085
|
+
; semicolon (%3B)
|
|
26086
|
+
= equals (%3D)
|
|
26087
|
+
& ampersand (%26)
|
|
26088
|
+
, comma (%2C)
|
|
26089
|
+
*/
|
|
26090
|
+
|
|
26091
|
+
const encodings = new Map([
|
|
26092
|
+
["%09", "\t"],
|
|
26093
|
+
["%0A", "\n"],
|
|
26094
|
+
["%0D", "\r"],
|
|
26095
|
+
["%25", "%"],
|
|
26096
|
+
["%3B", ";"],
|
|
26097
|
+
["%3D", "="],
|
|
26098
|
+
["%26", "&"],
|
|
26099
|
+
["%2C", ","]
|
|
26100
|
+
]);
|
|
26101
|
+
|
|
26102
|
+
function decodeGFFAttribute(str) {
|
|
26103
|
+
|
|
26104
|
+
if (!str.includes("%")) {
|
|
26105
|
+
return str
|
|
26106
|
+
}
|
|
26107
|
+
let decoded = "";
|
|
26108
|
+
for (let i = 0; i < str.length; i++) {
|
|
26109
|
+
|
|
26110
|
+
if (str.charCodeAt(i) === 37 && i < str.length - 2) {
|
|
26111
|
+
const key = str.substring(i, i + 3);
|
|
26112
|
+
if (encodings.has(key)) {
|
|
26113
|
+
decoded += encodings.get(key);
|
|
26114
|
+
} else {
|
|
26115
|
+
decoded += key;
|
|
26116
|
+
}
|
|
26117
|
+
i += 2;
|
|
26118
|
+
} else {
|
|
26119
|
+
decoded += str.charAt(i);
|
|
26120
|
+
}
|
|
26121
|
+
}
|
|
26122
|
+
return decoded
|
|
26123
|
+
|
|
26124
|
+
}
|
|
26125
|
+
|
|
26077
26126
|
/**
|
|
26078
26127
|
* Wrapper class to record a decoding error.
|
|
26079
26128
|
*/
|
|
@@ -29184,12 +29233,88 @@ class VPointer {
|
|
|
29184
29233
|
(this.block === vp.block && this.offset > vp.offset)
|
|
29185
29234
|
}
|
|
29186
29235
|
|
|
29236
|
+
isEqualTo(vp) {
|
|
29237
|
+
return this.block === vp.block && this.offset === vp.offset
|
|
29238
|
+
}
|
|
29239
|
+
|
|
29187
29240
|
print() {
|
|
29188
29241
|
return "" + this.block + ":" + this.offset
|
|
29189
29242
|
}
|
|
29190
29243
|
}
|
|
29191
29244
|
|
|
29192
|
-
|
|
29245
|
+
function optimizeChunks(chunks, lowest) {
|
|
29246
|
+
|
|
29247
|
+
if (chunks.length === 0) return chunks
|
|
29248
|
+
|
|
29249
|
+
chunks.sort(function (c0, c1) {
|
|
29250
|
+
|
|
29251
|
+
const dif = c0.minv.block - c1.minv.block;
|
|
29252
|
+
if (dif !== 0) {
|
|
29253
|
+
return dif
|
|
29254
|
+
} else {
|
|
29255
|
+
return c0.minv.offset - c1.minv.offset
|
|
29256
|
+
}
|
|
29257
|
+
});
|
|
29258
|
+
|
|
29259
|
+
if(chunks.length <= 1) {
|
|
29260
|
+
return chunks
|
|
29261
|
+
}
|
|
29262
|
+
|
|
29263
|
+
// console.log("Before trimming " + chunks.length)
|
|
29264
|
+
// for (let c of chunks) {
|
|
29265
|
+
// console.log(`${c.minv.block} ${c.minv.offset} - ${c.maxv.block} ${c.maxv.offset}`)
|
|
29266
|
+
// }
|
|
29267
|
+
|
|
29268
|
+
if (lowest) {
|
|
29269
|
+
chunks = chunks.filter(c => c.maxv.isGreaterThan(lowest));
|
|
29270
|
+
}
|
|
29271
|
+
|
|
29272
|
+
// console.log("Before merging " + chunks.length)
|
|
29273
|
+
// for (let c of chunks) {
|
|
29274
|
+
// console.log(`${c.minv.block} ${c.minv.offset} - ${c.maxv.block} ${c.maxv.offset}`)
|
|
29275
|
+
// }
|
|
29276
|
+
|
|
29277
|
+
const mergedChunks = [];
|
|
29278
|
+
let lastChunk;
|
|
29279
|
+
for (let chunk of chunks) {
|
|
29280
|
+
|
|
29281
|
+
if (!lastChunk) {
|
|
29282
|
+
mergedChunks.push(chunk);
|
|
29283
|
+
lastChunk = chunk;
|
|
29284
|
+
} else {
|
|
29285
|
+
if (canMerge(lastChunk, chunk)) {
|
|
29286
|
+
if (chunk.maxv.isGreaterThan(lastChunk.maxv)) {
|
|
29287
|
+
lastChunk.maxv = chunk.maxv;
|
|
29288
|
+
}
|
|
29289
|
+
} else {
|
|
29290
|
+
mergedChunks.push(chunk);
|
|
29291
|
+
lastChunk = chunk;
|
|
29292
|
+
}
|
|
29293
|
+
}
|
|
29294
|
+
}
|
|
29295
|
+
|
|
29296
|
+
// console.log("After merging " + mergedChunks.length)
|
|
29297
|
+
// for (let c of mergedChunks) {
|
|
29298
|
+
// console.log(`${c.minv.block} ${c.minv.offset} - ${c.maxv.block} ${c.maxv.offset}`)
|
|
29299
|
+
// }
|
|
29300
|
+
|
|
29301
|
+
return mergedChunks
|
|
29302
|
+
}
|
|
29303
|
+
|
|
29304
|
+
|
|
29305
|
+
/**
|
|
29306
|
+
* Merge 2 blocks if the file position gap between them is < 16 kb, and the total size is < ~5 mb
|
|
29307
|
+
* @param chunk1
|
|
29308
|
+
* @param chunk2
|
|
29309
|
+
* @returns {boolean|boolean}
|
|
29310
|
+
*/
|
|
29311
|
+
function canMerge(chunk1, chunk2) {
|
|
29312
|
+
const gap = chunk2.minv.block - chunk1.maxv.block;
|
|
29313
|
+
const sizeEstimate = chunk1.maxv.block - chunk1.minv.block;
|
|
29314
|
+
return gap < 65000 && sizeEstimate < 5000000
|
|
29315
|
+
}
|
|
29316
|
+
|
|
29317
|
+
// Represents a CSI Bam or Tabix index
|
|
29193
29318
|
|
|
29194
29319
|
const CSI1_MAGIC$1 = 21582659; // CSI\1
|
|
29195
29320
|
const CSI2_MAGIC$1 = 38359875; // CSI\2
|
|
@@ -29316,7 +29441,7 @@ class CSIIndex {
|
|
|
29316
29441
|
* @param max genomic end position
|
|
29317
29442
|
* @param return an array of {minv: {filePointer, offset}, {maxv: {filePointer, offset}}
|
|
29318
29443
|
*/
|
|
29319
|
-
|
|
29444
|
+
chunksForRange(refId, min, max) {
|
|
29320
29445
|
|
|
29321
29446
|
const ba = this.indices[refId];
|
|
29322
29447
|
if (!ba) {
|
|
@@ -29342,7 +29467,7 @@ class CSIIndex {
|
|
|
29342
29467
|
|
|
29343
29468
|
const lowestOffset = ba.loffset[overlappingBins[0]];
|
|
29344
29469
|
|
|
29345
|
-
return optimizeChunks
|
|
29470
|
+
return optimizeChunks(chunks, lowestOffset)
|
|
29346
29471
|
}
|
|
29347
29472
|
|
|
29348
29473
|
}
|
|
@@ -29379,58 +29504,11 @@ class CSIIndex {
|
|
|
29379
29504
|
|
|
29380
29505
|
}
|
|
29381
29506
|
|
|
29382
|
-
|
|
29383
|
-
|
|
29384
|
-
const mergedChunks = [];
|
|
29385
|
-
let lastChunk = null;
|
|
29386
|
-
|
|
29387
|
-
if (chunks.length === 0) return chunks
|
|
29388
|
-
|
|
29389
|
-
chunks.sort(function (c0, c1) {
|
|
29390
|
-
const dif = c0.minv.block - c1.minv.block;
|
|
29391
|
-
if (dif !== 0) {
|
|
29392
|
-
return dif
|
|
29393
|
-
} else {
|
|
29394
|
-
return c0.minv.offset - c1.minv.offset
|
|
29395
|
-
}
|
|
29396
|
-
});
|
|
29397
|
-
|
|
29398
|
-
chunks.forEach(function (chunk) {
|
|
29399
|
-
|
|
29400
|
-
if (!lowest || chunk.maxv.isGreaterThan(lowest)) {
|
|
29401
|
-
if (lastChunk === null) {
|
|
29402
|
-
mergedChunks.push(chunk);
|
|
29403
|
-
lastChunk = chunk;
|
|
29404
|
-
} else {
|
|
29405
|
-
if (canMerge$1(lastChunk, chunk)) {
|
|
29406
|
-
if (chunk.maxv.isGreaterThan(lastChunk.maxv)) {
|
|
29407
|
-
lastChunk.maxv = chunk.maxv;
|
|
29408
|
-
}
|
|
29409
|
-
} else {
|
|
29410
|
-
mergedChunks.push(chunk);
|
|
29411
|
-
lastChunk = chunk;
|
|
29412
|
-
}
|
|
29413
|
-
}
|
|
29414
|
-
}
|
|
29415
|
-
});
|
|
29416
|
-
|
|
29417
|
-
return mergedChunks
|
|
29418
|
-
}
|
|
29419
|
-
|
|
29420
|
-
function canMerge$1(chunk1, chunk2) {
|
|
29421
|
-
return (chunk2.minv.block - chunk1.maxv.block) < 65000 &&
|
|
29422
|
-
(chunk2.maxv.block - chunk1.minv.block) < 5000000
|
|
29423
|
-
// lastChunk.minv.block === lastChunk.maxv.block &&
|
|
29424
|
-
// lastChunk.maxv.block === chunk.minv.block &&
|
|
29425
|
-
// chunk.minv.block === chunk.maxv.block
|
|
29426
|
-
|
|
29427
|
-
}
|
|
29428
|
-
|
|
29429
|
-
// Represents a BAM index.
|
|
29507
|
+
// Represents a BAM or Tabix index.
|
|
29430
29508
|
|
|
29431
29509
|
const BAI_MAGIC$1 = 21578050;
|
|
29432
29510
|
const TABIX_MAGIC$1 = 21578324;
|
|
29433
|
-
|
|
29511
|
+
|
|
29434
29512
|
|
|
29435
29513
|
async function parseBamIndex(arrayBuffer, genome) {
|
|
29436
29514
|
const index = new BamIndex();
|
|
@@ -29552,14 +29630,14 @@ class BamIndex {
|
|
|
29552
29630
|
}
|
|
29553
29631
|
|
|
29554
29632
|
/**
|
|
29555
|
-
* Fetch
|
|
29633
|
+
* Fetch chunks for a particular genomic range. This method is public so it can be unit-tested.
|
|
29556
29634
|
*
|
|
29557
29635
|
* @param refId the sequence dictionary index of the chromosome
|
|
29558
29636
|
* @param min genomic start position
|
|
29559
29637
|
* @param max genomic end position
|
|
29560
|
-
* @param return an array of {minv: {
|
|
29638
|
+
* @param return an array of objects representing chunks (file spans) {minv: {block, offset}, {maxv: {block, offset}}
|
|
29561
29639
|
*/
|
|
29562
|
-
|
|
29640
|
+
chunksForRange(refId, min, max) {
|
|
29563
29641
|
|
|
29564
29642
|
const bam = this;
|
|
29565
29643
|
const ba = bam.indices[refId];
|
|
@@ -29568,8 +29646,13 @@ class BamIndex {
|
|
|
29568
29646
|
return []
|
|
29569
29647
|
} else {
|
|
29570
29648
|
const overlappingBins = reg2bins(min, max); // List of bin #s that overlap min, max
|
|
29571
|
-
const chunks = [];
|
|
29572
29649
|
|
|
29650
|
+
//console.log("bin ranges")
|
|
29651
|
+
//for(let b of overlappingBins) {
|
|
29652
|
+
// console.log(`${b[0]} - ${b[1]}`)
|
|
29653
|
+
//}
|
|
29654
|
+
|
|
29655
|
+
const chunks = [];
|
|
29573
29656
|
// Find chunks in overlapping bins. Leaf bins (< 4681) are not pruned
|
|
29574
29657
|
for (let binRange of overlappingBins) {
|
|
29575
29658
|
for (let bin = binRange[0]; bin <= binRange[1]; bin++) {
|
|
@@ -29578,7 +29661,7 @@ class BamIndex {
|
|
|
29578
29661
|
for (let c of binChunks) {
|
|
29579
29662
|
const cs = c[0];
|
|
29580
29663
|
const ce = c[1];
|
|
29581
|
-
chunks.push({minv: cs, maxv: ce
|
|
29664
|
+
chunks.push({minv: cs, maxv: ce});
|
|
29582
29665
|
}
|
|
29583
29666
|
}
|
|
29584
29667
|
}
|
|
@@ -29586,16 +29669,15 @@ class BamIndex {
|
|
|
29586
29669
|
|
|
29587
29670
|
// Use the linear index to find minimum file position of chunks that could contain alignments in the region
|
|
29588
29671
|
const nintv = ba.linearIndex.length;
|
|
29589
|
-
|
|
29590
|
-
|
|
29672
|
+
|
|
29673
|
+
let lowest;
|
|
29674
|
+
const minLin = Math.min(min >> 14, nintv - 1); // i.e. min / 16384
|
|
29591
29675
|
const maxLin = Math.min(max >> 14, nintv - 1);
|
|
29592
|
-
for (let i = minLin; i
|
|
29676
|
+
for (let i = minLin; i <= maxLin; i++) {
|
|
29593
29677
|
const vp = ba.linearIndex[i];
|
|
29594
29678
|
if (vp) {
|
|
29595
|
-
|
|
29596
|
-
|
|
29597
|
-
lowest = vp;
|
|
29598
|
-
}
|
|
29679
|
+
lowest = vp; // lowest file offset that contains alignments overlapping (min, max)
|
|
29680
|
+
break
|
|
29599
29681
|
}
|
|
29600
29682
|
}
|
|
29601
29683
|
|
|
@@ -29604,56 +29686,7 @@ class BamIndex {
|
|
|
29604
29686
|
}
|
|
29605
29687
|
}
|
|
29606
29688
|
|
|
29607
|
-
function optimizeChunks(chunks, lowest) {
|
|
29608
|
-
|
|
29609
|
-
const mergedChunks = [];
|
|
29610
|
-
let lastChunk = null;
|
|
29611
|
-
|
|
29612
|
-
if (chunks.length === 0) return chunks
|
|
29613
|
-
|
|
29614
|
-
chunks.sort(function (c0, c1) {
|
|
29615
|
-
const dif = c0.minv.block - c1.minv.block;
|
|
29616
|
-
if (dif !== 0) {
|
|
29617
|
-
return dif
|
|
29618
|
-
} else {
|
|
29619
|
-
return c0.minv.offset - c1.minv.offset
|
|
29620
|
-
}
|
|
29621
|
-
});
|
|
29622
|
-
|
|
29623
|
-
chunks.forEach(function (chunk) {
|
|
29624
|
-
|
|
29625
|
-
if (!lowest || chunk.maxv.isGreaterThan(lowest)) {
|
|
29626
|
-
if (lastChunk === null) {
|
|
29627
|
-
mergedChunks.push(chunk);
|
|
29628
|
-
lastChunk = chunk;
|
|
29629
|
-
} else {
|
|
29630
|
-
if (canMerge(lastChunk, chunk)) {
|
|
29631
|
-
if (chunk.maxv.isGreaterThan(lastChunk.maxv)) {
|
|
29632
|
-
lastChunk.maxv = chunk.maxv;
|
|
29633
|
-
}
|
|
29634
|
-
} else {
|
|
29635
|
-
mergedChunks.push(chunk);
|
|
29636
|
-
lastChunk = chunk;
|
|
29637
|
-
}
|
|
29638
|
-
}
|
|
29639
|
-
}
|
|
29640
|
-
});
|
|
29641
|
-
|
|
29642
|
-
return mergedChunks
|
|
29643
|
-
}
|
|
29644
|
-
|
|
29645
29689
|
|
|
29646
|
-
/**
|
|
29647
|
-
* Merge 2 blocks if the gap between them is < 1kb and the total resulting size < 100mb
|
|
29648
|
-
* @param chunk1
|
|
29649
|
-
* @param chunk2
|
|
29650
|
-
* @returns {boolean|boolean}
|
|
29651
|
-
*/
|
|
29652
|
-
function canMerge(chunk1, chunk2) {
|
|
29653
|
-
const gap = chunk2.minv.block - chunk1.maxv.block;
|
|
29654
|
-
const total = chunk2.maxv.block - chunk1.minv.block;
|
|
29655
|
-
return gap < 30000 && total < 10 * MB
|
|
29656
|
-
}
|
|
29657
29690
|
|
|
29658
29691
|
/**
|
|
29659
29692
|
* Calculate the list of bins that overlap with region [beg, end]
|
|
@@ -29791,7 +29824,7 @@ class TribbleIndex {
|
|
|
29791
29824
|
* @param min genomic start position
|
|
29792
29825
|
* @param max genomic end position
|
|
29793
29826
|
*/
|
|
29794
|
-
|
|
29827
|
+
chunksForRange(queryChr, min, max) { //function (refId, min, max) {
|
|
29795
29828
|
const chrIdx = this.chrIndex[queryChr];
|
|
29796
29829
|
|
|
29797
29830
|
if (chrIdx) {
|
|
@@ -29958,7 +29991,12 @@ class ByteArrayDataWrapper {
|
|
|
29958
29991
|
|
|
29959
29992
|
}
|
|
29960
29993
|
|
|
29961
|
-
|
|
29994
|
+
/**
|
|
29995
|
+
* Class to iterate line-by-line over a BGZipped text file. This class is useful for iterating from the start of
|
|
29996
|
+
* the file. Not useful for indexed queries.
|
|
29997
|
+
*/
|
|
29998
|
+
|
|
29999
|
+
class BGZLineReader {
|
|
29962
30000
|
|
|
29963
30001
|
constructor(config) {
|
|
29964
30002
|
this.config = config;
|
|
@@ -30004,7 +30042,7 @@ class BGZipLineReader {
|
|
|
30004
30042
|
}
|
|
30005
30043
|
});
|
|
30006
30044
|
const abuffer = await igvxhr.loadArrayBuffer(this.config.url, bsizeOptions);
|
|
30007
|
-
const bufferSize = bgzBlockSize(abuffer);
|
|
30045
|
+
const bufferSize = bgzBlockSize$1(abuffer);
|
|
30008
30046
|
//console.log(`next block ${this.filePtr} ${bufferSize}`);
|
|
30009
30047
|
|
|
30010
30048
|
if (bufferSize === 0) {
|
|
@@ -30025,6 +30063,250 @@ class BGZipLineReader {
|
|
|
30025
30063
|
|
|
30026
30064
|
}
|
|
30027
30065
|
|
|
30066
|
+
function concatenateArrayBuffers(arrayBuffers) {
|
|
30067
|
+
|
|
30068
|
+
if (arrayBuffers.length === 1) {
|
|
30069
|
+
return arrayBuffers[0]
|
|
30070
|
+
}
|
|
30071
|
+
|
|
30072
|
+
let len = 0;
|
|
30073
|
+
for (const b of arrayBuffers) {
|
|
30074
|
+
len += b.byteLength;
|
|
30075
|
+
}
|
|
30076
|
+
const c = new Uint8Array(len);
|
|
30077
|
+
let offset = 0;
|
|
30078
|
+
for (const b of arrayBuffers) {
|
|
30079
|
+
c.set(new Uint8Array(b), offset);
|
|
30080
|
+
offset += b.byteLength;
|
|
30081
|
+
}
|
|
30082
|
+
return c.buffer
|
|
30083
|
+
}
|
|
30084
|
+
|
|
30085
|
+
/**
|
|
30086
|
+
* Return the block size for the data buffer.
|
|
30087
|
+
* @param data
|
|
30088
|
+
* @returns {number}
|
|
30089
|
+
*/
|
|
30090
|
+
const bgzBlockSize = (data) => {
|
|
30091
|
+
const ba = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
|
|
30092
|
+
const bsize = (ba[17] << 8 | ba[16]) + 1;
|
|
30093
|
+
return bsize
|
|
30094
|
+
};
|
|
30095
|
+
|
|
30096
|
+
class BGZBlockLoader {
|
|
30097
|
+
|
|
30098
|
+
constructor(config) {
|
|
30099
|
+
this.config = config;
|
|
30100
|
+
this.cacheBlocks = false != config.cacheBlocks; // Default to true
|
|
30101
|
+
this.cache = undefined;
|
|
30102
|
+
}
|
|
30103
|
+
|
|
30104
|
+
/**
|
|
30105
|
+
* Return inflated data from startBlock through endBlock as an UInt8Array
|
|
30106
|
+
*
|
|
30107
|
+
* @param startBlock
|
|
30108
|
+
* @param endBlock
|
|
30109
|
+
* @returns {Promise<Uint8Array>}
|
|
30110
|
+
*/
|
|
30111
|
+
async getData(startBlock, endBlock) {
|
|
30112
|
+
|
|
30113
|
+
const blocks = await this.getInflatedBlocks(startBlock, endBlock);
|
|
30114
|
+
if (blocks.length === 1) {
|
|
30115
|
+
return blocks[0]
|
|
30116
|
+
}
|
|
30117
|
+
|
|
30118
|
+
let len = 0;
|
|
30119
|
+
for (const b of blocks) {
|
|
30120
|
+
len += b.byteLength;
|
|
30121
|
+
}
|
|
30122
|
+
const c = new Uint8Array(len);
|
|
30123
|
+
let offset = 0;
|
|
30124
|
+
for (const b of blocks) {
|
|
30125
|
+
c.set(b, offset);
|
|
30126
|
+
offset += b.byteLength;
|
|
30127
|
+
}
|
|
30128
|
+
return c
|
|
30129
|
+
}
|
|
30130
|
+
|
|
30131
|
+
/**
|
|
30132
|
+
* Return the inflated data for the specified blocks as an array of Uint8Arrays. This method is public so
|
|
30133
|
+
* it can be unit tested. *
|
|
30134
|
+
* @param startBlock
|
|
30135
|
+
* @param endBlock
|
|
30136
|
+
* @returns {Promise<*[Uint8Array]>}
|
|
30137
|
+
*/
|
|
30138
|
+
async getInflatedBlocks(startBlock, endBlock) {
|
|
30139
|
+
|
|
30140
|
+
if (!this.cacheBlocks) {
|
|
30141
|
+
const buffer = await this.loadBLockData(startBlock, endBlock);
|
|
30142
|
+
return inflateBlocks(buffer)
|
|
30143
|
+
} else {
|
|
30144
|
+
|
|
30145
|
+
const c = this.cache;
|
|
30146
|
+
if (c && (c.startBlock <= startBlock && c.endBlock >= endBlock)) {
|
|
30147
|
+
//console.log("Complete overlap")
|
|
30148
|
+
const startOffset = startBlock - c.startBlock;
|
|
30149
|
+
const endOffset = endBlock - c.startBlock;
|
|
30150
|
+
return inflateBlocks(c.buffer, startOffset, endOffset)
|
|
30151
|
+
// Don't update cache, still valid
|
|
30152
|
+
} else {
|
|
30153
|
+
|
|
30154
|
+
let buffer;
|
|
30155
|
+
if (!c || (c.startBlock > endBlock || c.endBlock < startBlock)) {
|
|
30156
|
+
// no overlap with cache
|
|
30157
|
+
buffer = await this.loadBLockData(startBlock, endBlock);
|
|
30158
|
+
} else {
|
|
30159
|
+
|
|
30160
|
+
//console.log("Some overlap")
|
|
30161
|
+
const arrayBuffers = [];
|
|
30162
|
+
|
|
30163
|
+
// Load blocks preceding cache start, if any
|
|
30164
|
+
if (startBlock < c.startBlock) {
|
|
30165
|
+
// load first blocks
|
|
30166
|
+
const startBuffer = await this.loadBLockData(startBlock, c.startBlock, {skipEnd: true});
|
|
30167
|
+
arrayBuffers.push(startBuffer);
|
|
30168
|
+
}
|
|
30169
|
+
|
|
30170
|
+
// Slice cached buffer as needed
|
|
30171
|
+
let cachedBuffer;
|
|
30172
|
+
if (startBlock <= c.startBlock && endBlock >= c.endBlock) {
|
|
30173
|
+
cachedBuffer = c.buffer;
|
|
30174
|
+
} else {
|
|
30175
|
+
const start = Math.max(0, startBlock - c.startBlock);
|
|
30176
|
+
let end;
|
|
30177
|
+
if (endBlock >= c.endBlock) {
|
|
30178
|
+
end = c.buffer.byteLength;
|
|
30179
|
+
} else {
|
|
30180
|
+
// We need to find the byte position of the end of "endBlock"
|
|
30181
|
+
const boundaries = findBlockBoundaries(c.buffer);
|
|
30182
|
+
for (let i = 0; i < boundaries.length - 1; i++) {
|
|
30183
|
+
if (c.startBlock + boundaries[i] === endBlock) {
|
|
30184
|
+
end = boundaries[i + 1];
|
|
30185
|
+
break
|
|
30186
|
+
}
|
|
30187
|
+
}
|
|
30188
|
+
// Do something if end not found
|
|
30189
|
+
}
|
|
30190
|
+
cachedBuffer = c.buffer.slice(start, end);
|
|
30191
|
+
}
|
|
30192
|
+
arrayBuffers.push(cachedBuffer);
|
|
30193
|
+
|
|
30194
|
+
// Load end blocks, if any
|
|
30195
|
+
if (endBlock > c.endBlock) {
|
|
30196
|
+
const endBuffer = await this.loadBLockData(c.endBlock, endBlock, {skipStart: true});
|
|
30197
|
+
arrayBuffers.push(endBuffer);
|
|
30198
|
+
}
|
|
30199
|
+
|
|
30200
|
+
buffer = concatenateArrayBuffers(arrayBuffers);
|
|
30201
|
+
}
|
|
30202
|
+
|
|
30203
|
+
this.cache = {startBlock, endBlock, buffer};
|
|
30204
|
+
return inflateBlocks(buffer)
|
|
30205
|
+
}
|
|
30206
|
+
}
|
|
30207
|
+
}
|
|
30208
|
+
|
|
30209
|
+
async loadBLockData(startBlock, endBlock, options) {
|
|
30210
|
+
|
|
30211
|
+
const config = this.config;
|
|
30212
|
+
const skipStart = options && options.skipStart;
|
|
30213
|
+
const skipEnd = options && options.skipEnd;
|
|
30214
|
+
|
|
30215
|
+
// Get size of last block if not skipped
|
|
30216
|
+
let lastBlockSize = 0;
|
|
30217
|
+
if (!skipEnd) {
|
|
30218
|
+
const bsizeOptions = buildOptions(config, {range: {start: endBlock, size: 26}});
|
|
30219
|
+
const abuffer = await igvxhr.loadArrayBuffer(config.url, bsizeOptions);
|
|
30220
|
+
lastBlockSize = bgzBlockSize(abuffer);
|
|
30221
|
+
}
|
|
30222
|
+
|
|
30223
|
+
if (skipStart) {
|
|
30224
|
+
const bsizeOptions = buildOptions(config, {range: {start: startBlock, size: 26}});
|
|
30225
|
+
const abuffer = await igvxhr.loadArrayBuffer(config.url, bsizeOptions);
|
|
30226
|
+
startBlock += bgzBlockSize(abuffer);
|
|
30227
|
+
}
|
|
30228
|
+
|
|
30229
|
+
// Load data for all blocks
|
|
30230
|
+
const loadOptions = buildOptions(config, {
|
|
30231
|
+
range: {
|
|
30232
|
+
start: startBlock,
|
|
30233
|
+
size: endBlock + lastBlockSize - startBlock
|
|
30234
|
+
}
|
|
30235
|
+
});
|
|
30236
|
+
|
|
30237
|
+
//console.log(`${this.config.name} Loaded ${startBlock} - ${endBlock + lastBlockSize} (${(endBlock + lastBlockSize - startBlock) / 1000} kb)`)
|
|
30238
|
+
|
|
30239
|
+
return igvxhr.loadArrayBuffer(config.url, loadOptions)
|
|
30240
|
+
}
|
|
30241
|
+
}
|
|
30242
|
+
|
|
30243
|
+
function findBlockBoundaries(arrayBuffer) {
|
|
30244
|
+
|
|
30245
|
+
const byteLengh = arrayBuffer.byteLength;
|
|
30246
|
+
let offset = 0;
|
|
30247
|
+
const blockBoundaries = [0];
|
|
30248
|
+
while (offset < byteLengh) {
|
|
30249
|
+
//console.log("Cache block " + offset)
|
|
30250
|
+
const ba = new Uint8Array(arrayBuffer, offset);
|
|
30251
|
+
const bsize = (ba[17] << 8 | ba[16]) + 1;
|
|
30252
|
+
offset += bsize;
|
|
30253
|
+
if (offset < byteLengh) {
|
|
30254
|
+
blockBoundaries.push(offset);
|
|
30255
|
+
}
|
|
30256
|
+
}
|
|
30257
|
+
return blockBoundaries
|
|
30258
|
+
}
|
|
30259
|
+
|
|
30260
|
+
|
|
30261
|
+
/**
|
|
30262
|
+
* Inflate compressed blocks within the data buffer*
|
|
30263
|
+
* @param data
|
|
30264
|
+
* @param startBlock - optional file location for start block. Default == 0
|
|
30265
|
+
* @param endBlock - optional file location for last block to decompress.
|
|
30266
|
+
* @returns {*[]}
|
|
30267
|
+
*/
|
|
30268
|
+
function inflateBlocks(data, startBlock, endBlock) {
|
|
30269
|
+
|
|
30270
|
+
startBlock = startBlock || 0;
|
|
30271
|
+
|
|
30272
|
+
const oBlockList = [];
|
|
30273
|
+
let ptr = startBlock;
|
|
30274
|
+
|
|
30275
|
+
const lim = data.byteLength - 18;
|
|
30276
|
+
while (ptr < lim) {
|
|
30277
|
+
try {
|
|
30278
|
+
//console.log(113873 + ptr)
|
|
30279
|
+
const header = new Uint8Array(data, ptr, 18);
|
|
30280
|
+
const xlen = (header[11] << 8) | (header[10]);
|
|
30281
|
+
const bsize = ((header[17] << 8) | (header[16])); // Total block size, including header, minus 1
|
|
30282
|
+
const start = 12 + xlen + ptr; // Start of CDATA
|
|
30283
|
+
const bytesLeft = data.byteLength - start;
|
|
30284
|
+
const cDataSize = bsize - xlen - 18;
|
|
30285
|
+
|
|
30286
|
+
if (bytesLeft < cDataSize || cDataSize <= 0) {
|
|
30287
|
+
// This is unexpected. Throw error?
|
|
30288
|
+
break
|
|
30289
|
+
}
|
|
30290
|
+
|
|
30291
|
+
const cdata = new Uint8Array(data, start, cDataSize);
|
|
30292
|
+
const unc = inflateRaw(cdata);
|
|
30293
|
+
oBlockList.push(unc);
|
|
30294
|
+
|
|
30295
|
+
if (endBlock === ptr) {
|
|
30296
|
+
break
|
|
30297
|
+
} else {
|
|
30298
|
+
// Advance to next block
|
|
30299
|
+
ptr += bsize + 1;
|
|
30300
|
+
}
|
|
30301
|
+
|
|
30302
|
+
} catch (e) {
|
|
30303
|
+
console.error(e);
|
|
30304
|
+
break
|
|
30305
|
+
}
|
|
30306
|
+
}
|
|
30307
|
+
return oBlockList
|
|
30308
|
+
}
|
|
30309
|
+
|
|
30028
30310
|
/*
|
|
30029
30311
|
* The MIT License (MIT)
|
|
30030
30312
|
*
|
|
@@ -30082,6 +30364,7 @@ class FeatureFileReader {
|
|
|
30082
30364
|
if (this.config.format === "vcf" && !this.config.indexURL) {
|
|
30083
30365
|
console.warn("Warning: index file not specified. The entire vcf file will be loaded.");
|
|
30084
30366
|
}
|
|
30367
|
+
|
|
30085
30368
|
}
|
|
30086
30369
|
|
|
30087
30370
|
async defaultVisibilityWindow() {
|
|
@@ -30139,7 +30422,8 @@ class FeatureFileReader {
|
|
|
30139
30422
|
|
|
30140
30423
|
let dataWrapper;
|
|
30141
30424
|
if (index.tabix) {
|
|
30142
|
-
|
|
30425
|
+
this._blockLoader = new BGZBlockLoader(this.config);
|
|
30426
|
+
dataWrapper = new BGZLineReader(this.config);
|
|
30143
30427
|
} else {
|
|
30144
30428
|
// Tribble
|
|
30145
30429
|
const maxSize = Object.values(index.chrIndex)
|
|
@@ -30225,51 +30509,27 @@ class FeatureFileReader {
|
|
|
30225
30509
|
}
|
|
30226
30510
|
|
|
30227
30511
|
const genome = this.genome;
|
|
30228
|
-
const
|
|
30229
|
-
if (!
|
|
30512
|
+
const chunks = this.index.chunksForRange(refId, start, end);
|
|
30513
|
+
if (!chunks || chunks.length === 0) {
|
|
30230
30514
|
return []
|
|
30231
30515
|
} else {
|
|
30232
30516
|
const allFeatures = [];
|
|
30233
|
-
for (let
|
|
30234
|
-
|
|
30235
|
-
const startPos = block.minv.block;
|
|
30236
|
-
const startOffset = block.minv.offset;
|
|
30237
|
-
const endOffset = block.maxv.offset;
|
|
30238
|
-
let endPos;
|
|
30239
|
-
|
|
30240
|
-
if (tabix) {
|
|
30241
|
-
let lastBlockSize = 0;
|
|
30242
|
-
if (endOffset > 0) {
|
|
30243
|
-
const bsizeOptions = buildOptions(config, {
|
|
30244
|
-
range: {
|
|
30245
|
-
start: block.maxv.block,
|
|
30246
|
-
size: 26
|
|
30247
|
-
}
|
|
30248
|
-
});
|
|
30249
|
-
const abuffer = await igvxhr.loadArrayBuffer(config.url, bsizeOptions);
|
|
30250
|
-
lastBlockSize = bgzBlockSize(abuffer);
|
|
30251
|
-
}
|
|
30252
|
-
endPos = block.maxv.block + lastBlockSize;
|
|
30253
|
-
} else {
|
|
30254
|
-
endPos = block.maxv.block;
|
|
30255
|
-
}
|
|
30256
|
-
|
|
30257
|
-
const options = buildOptions(config, {
|
|
30258
|
-
range: {
|
|
30259
|
-
start: startPos,
|
|
30260
|
-
size: endPos - startPos + 1
|
|
30261
|
-
}
|
|
30262
|
-
});
|
|
30517
|
+
for (let chunk of chunks) {
|
|
30263
30518
|
|
|
30264
30519
|
let inflated;
|
|
30265
30520
|
if (tabix) {
|
|
30266
|
-
|
|
30267
|
-
inflated = unbgzf(data);
|
|
30521
|
+
inflated = await this._blockLoader.getData(chunk.minv.block, chunk.maxv.block);
|
|
30268
30522
|
} else {
|
|
30523
|
+
const options = buildOptions(config, {
|
|
30524
|
+
range: {
|
|
30525
|
+
start: chunk.minv.block,
|
|
30526
|
+
size: chunk.maxv.block - chunk.minv.block + 1
|
|
30527
|
+
}
|
|
30528
|
+
});
|
|
30269
30529
|
inflated = await igvxhr.loadString(config.url, options);
|
|
30270
30530
|
}
|
|
30271
30531
|
|
|
30272
|
-
const slicedData =
|
|
30532
|
+
const slicedData = chunk.minv.offset ? inflated.slice(chunk.minv.offset) : inflated;
|
|
30273
30533
|
const dataWrapper = getDataWrapper(slicedData);
|
|
30274
30534
|
let slicedFeatures = await parser.parseFeatures(dataWrapper);
|
|
30275
30535
|
|
|
@@ -36371,6 +36631,8 @@ class BamReader {
|
|
|
36371
36631
|
this.bamPath = config.url;
|
|
36372
36632
|
this.baiPath = config.indexURL;
|
|
36373
36633
|
BamUtils.setReaderDefaults(this, config);
|
|
36634
|
+
|
|
36635
|
+
this._blockLoader = new BGZBlockLoader(config);
|
|
36374
36636
|
}
|
|
36375
36637
|
|
|
36376
36638
|
async readAlignments(chr, bpStart, bpEnd) {
|
|
@@ -36386,32 +36648,16 @@ class BamReader {
|
|
|
36386
36648
|
} else {
|
|
36387
36649
|
|
|
36388
36650
|
const bamIndex = await this.getIndex();
|
|
36389
|
-
const chunks = bamIndex.
|
|
36651
|
+
const chunks = bamIndex.chunksForRange(chrId, bpStart, bpEnd);
|
|
36390
36652
|
|
|
36391
36653
|
if (!chunks || chunks.length === 0) {
|
|
36392
36654
|
return alignmentContainer
|
|
36393
36655
|
}
|
|
36394
|
-
for (let c of chunks) {
|
|
36395
|
-
|
|
36396
|
-
let lastBlockSize;
|
|
36397
|
-
if (c.maxv.offset === 0) {
|
|
36398
|
-
lastBlockSize = 0; // Don't need to read the last block.
|
|
36399
|
-
} else {
|
|
36400
|
-
const bsizeOptions = buildOptions(this.config, {range: {start: c.maxv.block, size: 26}});
|
|
36401
|
-
const abuffer = await igvxhr.loadArrayBuffer(this.bamPath, bsizeOptions);
|
|
36402
|
-
lastBlockSize = bgzBlockSize(abuffer);
|
|
36403
|
-
}
|
|
36404
|
-
const fetchMin = c.minv.block;
|
|
36405
|
-
const fetchMax = c.maxv.block + lastBlockSize;
|
|
36406
|
-
const range = {start: fetchMin, size: fetchMax - fetchMin + 1};
|
|
36407
|
-
|
|
36408
|
-
const compressed = await igvxhr.loadArrayBuffer(this.bamPath, buildOptions(this.config, {range: range}));
|
|
36409
36656
|
|
|
36410
|
-
|
|
36657
|
+
for (let c of chunks) {
|
|
36658
|
+
const ba = await this._blockLoader.getData(c.minv.block, c.maxv.block);
|
|
36411
36659
|
const done = BamUtils.decodeBamRecords(ba, c.minv.offset, alignmentContainer, this.indexToChr, chrId, bpStart, bpEnd, this.filter);
|
|
36412
|
-
|
|
36413
36660
|
if (done) {
|
|
36414
|
-
// console.log(`Loaded ${counter} chunks out of ${chunks.length}`);
|
|
36415
36661
|
break
|
|
36416
36662
|
}
|
|
36417
36663
|
}
|
|
@@ -36428,7 +36674,7 @@ class BamReader {
|
|
|
36428
36674
|
if (index.firstBlockPosition) {
|
|
36429
36675
|
const bsizeOptions = buildOptions(this.config, {range: {start: index.firstBlockPosition, size: 26}});
|
|
36430
36676
|
const abuffer = await igvxhr.loadArrayBuffer(this.bamPath, bsizeOptions);
|
|
36431
|
-
const bsize = bgzBlockSize(abuffer);
|
|
36677
|
+
const bsize = bgzBlockSize$1(abuffer);
|
|
36432
36678
|
len = index.firstBlockPosition + bsize; // Insure we get the complete compressed block containing the header
|
|
36433
36679
|
} else {
|
|
36434
36680
|
len = 64000;
|
|
@@ -40103,7 +40349,9 @@ class BAMTrack extends TrackBase {
|
|
|
40103
40349
|
hoverText(clickState) {
|
|
40104
40350
|
if (true === this.showCoverage && clickState.y >= this.coverageTrack.top && clickState.y < this.coverageTrack.height) {
|
|
40105
40351
|
const clickedObject = this.coverageTrack.getClickedObject(clickState);
|
|
40106
|
-
|
|
40352
|
+
if(clickedObject) {
|
|
40353
|
+
return clickedObject.hoverText()
|
|
40354
|
+
}
|
|
40107
40355
|
}
|
|
40108
40356
|
|
|
40109
40357
|
}
|
|
@@ -54209,10 +54457,7 @@ var index = {
|
|
|
54209
54457
|
setOauthToken,
|
|
54210
54458
|
oauth,
|
|
54211
54459
|
version,
|
|
54212
|
-
setApiKey
|
|
54213
|
-
doAutoscale,
|
|
54214
|
-
TrackView,
|
|
54215
|
-
GenomeUtils
|
|
54460
|
+
setApiKey
|
|
54216
54461
|
};
|
|
54217
54462
|
|
|
54218
54463
|
export { index as default };
|