igv 2.13.7 → 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/dist/igv.js CHANGED
@@ -13966,7 +13966,7 @@
13966
13966
  const {
13967
13967
  Inflate,
13968
13968
  inflate: inflate$3,
13969
- inflateRaw,
13969
+ inflateRaw: inflateRaw$2,
13970
13970
  ungzip: ungzip$2
13971
13971
  } = inflate_1$1;
13972
13972
  var Deflate_1 = Deflate;
@@ -13975,7 +13975,7 @@
13975
13975
  var gzip_1 = gzip;
13976
13976
  var Inflate_1 = Inflate;
13977
13977
  var inflate_1 = inflate$3;
13978
- var inflateRaw_1 = inflateRaw;
13978
+ var inflateRaw_1 = inflateRaw$2;
13979
13979
  var ungzip_1 = ungzip$2;
13980
13980
  var constants_1 = constants$2;
13981
13981
  var pako = {
@@ -14008,7 +14008,7 @@
14008
14008
 
14009
14009
  pako.deflateRaw;
14010
14010
  pako.deflate;
14011
- pako.inflateRaw;
14011
+ const inflateRaw = pako.inflateRaw;
14012
14012
  const inflate = pako.inflate;
14013
14013
  pako.gzip;
14014
14014
  const FEXTRA = 4; // gzip spec F.EXTRA flag
@@ -14080,7 +14080,7 @@
14080
14080
  return out;
14081
14081
  }
14082
14082
  }
14083
- function bgzBlockSize(data) {
14083
+ function bgzBlockSize$1(data) {
14084
14084
  const ba = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
14085
14085
  const bsize = (ba[17] << 8 | ba[16]) + 1;
14086
14086
  return bsize;
@@ -18865,7 +18865,7 @@
18865
18865
 
18866
18866
  const doAutoscale = function (features) {
18867
18867
  var min, max;
18868
- if (features.length > 0) {
18868
+ if (features && features.length > 0) {
18869
18869
  min = Number.MAX_VALUE;
18870
18870
  max = -Number.MAX_VALUE;
18871
18871
  features.forEach(function (f) {
@@ -21939,7 +21939,7 @@
21939
21939
  }
21940
21940
  };
21941
21941
 
21942
- const _version = "2.13.7";
21942
+ const _version = "2.13.8";
21943
21943
  function version$1() {
21944
21944
  return _version;
21945
21945
  }
@@ -26462,12 +26462,81 @@
26462
26462
  isGreaterThan(vp) {
26463
26463
  return this.block > vp.block || this.block === vp.block && this.offset > vp.offset;
26464
26464
  }
26465
+ isEqualTo(vp) {
26466
+ return this.block === vp.block && this.offset === vp.offset;
26467
+ }
26465
26468
  print() {
26466
26469
  return "" + this.block + ":" + this.offset;
26467
26470
  }
26468
26471
  }
26469
26472
 
26470
- // Represents a BAM index.
26473
+ function optimizeChunks(chunks, lowest) {
26474
+ if (chunks.length === 0) return chunks;
26475
+ chunks.sort(function (c0, c1) {
26476
+ const dif = c0.minv.block - c1.minv.block;
26477
+ if (dif !== 0) {
26478
+ return dif;
26479
+ } else {
26480
+ return c0.minv.offset - c1.minv.offset;
26481
+ }
26482
+ });
26483
+ if (chunks.length <= 1) {
26484
+ return chunks;
26485
+ }
26486
+
26487
+ // console.log("Before trimming " + chunks.length)
26488
+ // for (let c of chunks) {
26489
+ // console.log(`${c.minv.block} ${c.minv.offset} - ${c.maxv.block} ${c.maxv.offset}`)
26490
+ // }
26491
+
26492
+ if (lowest) {
26493
+ chunks = chunks.filter(c => c.maxv.isGreaterThan(lowest));
26494
+ }
26495
+
26496
+ // console.log("Before merging " + chunks.length)
26497
+ // for (let c of chunks) {
26498
+ // console.log(`${c.minv.block} ${c.minv.offset} - ${c.maxv.block} ${c.maxv.offset}`)
26499
+ // }
26500
+
26501
+ const mergedChunks = [];
26502
+ let lastChunk;
26503
+ for (let chunk of chunks) {
26504
+ if (!lastChunk) {
26505
+ mergedChunks.push(chunk);
26506
+ lastChunk = chunk;
26507
+ } else {
26508
+ if (canMerge(lastChunk, chunk)) {
26509
+ if (chunk.maxv.isGreaterThan(lastChunk.maxv)) {
26510
+ lastChunk.maxv = chunk.maxv;
26511
+ }
26512
+ } else {
26513
+ mergedChunks.push(chunk);
26514
+ lastChunk = chunk;
26515
+ }
26516
+ }
26517
+ }
26518
+
26519
+ // console.log("After merging " + mergedChunks.length)
26520
+ // for (let c of mergedChunks) {
26521
+ // console.log(`${c.minv.block} ${c.minv.offset} - ${c.maxv.block} ${c.maxv.offset}`)
26522
+ // }
26523
+
26524
+ return mergedChunks;
26525
+ }
26526
+
26527
+ /**
26528
+ * Merge 2 blocks if the file position gap between them is < 16 kb, and the total size is < ~5 mb
26529
+ * @param chunk1
26530
+ * @param chunk2
26531
+ * @returns {boolean|boolean}
26532
+ */
26533
+ function canMerge(chunk1, chunk2) {
26534
+ const gap = chunk2.minv.block - chunk1.maxv.block;
26535
+ const sizeEstimate = chunk1.maxv.block - chunk1.minv.block;
26536
+ return gap < 65000 && sizeEstimate < 5000000;
26537
+ }
26538
+
26539
+ // Represents a CSI Bam or Tabix index
26471
26540
  const CSI1_MAGIC$1 = 21582659; // CSI\1
26472
26541
  const CSI2_MAGIC$1 = 38359875; // CSI\2
26473
26542
 
@@ -26579,7 +26648,7 @@
26579
26648
  * @param max genomic end position
26580
26649
  * @param return an array of {minv: {filePointer, offset}, {maxv: {filePointer, offset}}
26581
26650
  */
26582
- blocksForRange(refId, min, max) {
26651
+ chunksForRange(refId, min, max) {
26583
26652
  const ba = this.indices[refId];
26584
26653
  if (!ba) {
26585
26654
  return [];
@@ -26605,7 +26674,7 @@
26605
26674
  }
26606
26675
  }
26607
26676
  const lowestOffset = ba.loffset[overlappingBins[0]];
26608
- return optimizeChunks$1(chunks, lowestOffset);
26677
+ return optimizeChunks(chunks, lowestOffset);
26609
26678
  }
26610
26679
  }
26611
26680
 
@@ -26637,48 +26706,10 @@
26637
26706
  return ((1 << (this.depth + 1) * 3) - 1) / 7;
26638
26707
  }
26639
26708
  }
26640
- function optimizeChunks$1(chunks, lowest) {
26641
- const mergedChunks = [];
26642
- let lastChunk = null;
26643
- if (chunks.length === 0) return chunks;
26644
- chunks.sort(function (c0, c1) {
26645
- const dif = c0.minv.block - c1.minv.block;
26646
- if (dif !== 0) {
26647
- return dif;
26648
- } else {
26649
- return c0.minv.offset - c1.minv.offset;
26650
- }
26651
- });
26652
- chunks.forEach(function (chunk) {
26653
- if (!lowest || chunk.maxv.isGreaterThan(lowest)) {
26654
- if (lastChunk === null) {
26655
- mergedChunks.push(chunk);
26656
- lastChunk = chunk;
26657
- } else {
26658
- if (canMerge$1(lastChunk, chunk)) {
26659
- if (chunk.maxv.isGreaterThan(lastChunk.maxv)) {
26660
- lastChunk.maxv = chunk.maxv;
26661
- }
26662
- } else {
26663
- mergedChunks.push(chunk);
26664
- lastChunk = chunk;
26665
- }
26666
- }
26667
- }
26668
- });
26669
- return mergedChunks;
26670
- }
26671
- function canMerge$1(chunk1, chunk2) {
26672
- return chunk2.minv.block - chunk1.maxv.block < 65000 && chunk2.maxv.block - chunk1.minv.block < 5000000;
26673
- // lastChunk.minv.block === lastChunk.maxv.block &&
26674
- // lastChunk.maxv.block === chunk.minv.block &&
26675
- // chunk.minv.block === chunk.maxv.block
26676
- }
26677
26709
 
26678
- // Represents a BAM index.
26710
+ // Represents a BAM or Tabix index.
26679
26711
  const BAI_MAGIC$1 = 21578050;
26680
26712
  const TABIX_MAGIC$1 = 21578324;
26681
- const MB = 1000000;
26682
26713
  async function parseBamIndex(arrayBuffer, genome) {
26683
26714
  const index = new BamIndex();
26684
26715
  await index.parse(arrayBuffer, false, genome);
@@ -26780,22 +26811,27 @@
26780
26811
  }
26781
26812
 
26782
26813
  /**
26783
- * Fetch blocks for a particular genomic range. This method is public so it can be unit-tested.
26814
+ * Fetch chunks for a particular genomic range. This method is public so it can be unit-tested.
26784
26815
  *
26785
26816
  * @param refId the sequence dictionary index of the chromosome
26786
26817
  * @param min genomic start position
26787
26818
  * @param max genomic end position
26788
- * @param return an array of {minv: {filePointer, offset}, {maxv: {filePointer, offset}}
26819
+ * @param return an array of objects representing chunks (file spans) {minv: {block, offset}, {maxv: {block, offset}}
26789
26820
  */
26790
- blocksForRange(refId, min, max) {
26821
+ chunksForRange(refId, min, max) {
26791
26822
  const bam = this;
26792
26823
  const ba = bam.indices[refId];
26793
26824
  if (!ba) {
26794
26825
  return [];
26795
26826
  } else {
26796
26827
  const overlappingBins = reg2bins(min, max); // List of bin #s that overlap min, max
26797
- const chunks = [];
26798
26828
 
26829
+ //console.log("bin ranges")
26830
+ //for(let b of overlappingBins) {
26831
+ // console.log(`${b[0]} - ${b[1]}`)
26832
+ //}
26833
+
26834
+ const chunks = [];
26799
26835
  // Find chunks in overlapping bins. Leaf bins (< 4681) are not pruned
26800
26836
  for (let binRange of overlappingBins) {
26801
26837
  for (let bin = binRange[0]; bin <= binRange[1]; bin++) {
@@ -26806,8 +26842,7 @@
26806
26842
  const ce = c[1];
26807
26843
  chunks.push({
26808
26844
  minv: cs,
26809
- maxv: ce,
26810
- bin: bin
26845
+ maxv: ce
26811
26846
  });
26812
26847
  }
26813
26848
  }
@@ -26816,65 +26851,20 @@
26816
26851
 
26817
26852
  // Use the linear index to find minimum file position of chunks that could contain alignments in the region
26818
26853
  const nintv = ba.linearIndex.length;
26819
- let lowest = null;
26820
- const minLin = Math.min(min >> 14, nintv - 1);
26854
+ let lowest;
26855
+ const minLin = Math.min(min >> 14, nintv - 1); // i.e. min / 16384
26821
26856
  const maxLin = Math.min(max >> 14, nintv - 1);
26822
- for (let i = minLin; i < maxLin; i++) {
26857
+ for (let i = minLin; i <= maxLin; i++) {
26823
26858
  const vp = ba.linearIndex[i];
26824
26859
  if (vp) {
26825
- // todo -- I think, but am not sure, that the values in the linear index have to be in increasing order. So the first non-null should be minimum
26826
- if (!lowest || vp.isLessThan(lowest)) {
26827
- lowest = vp;
26828
- }
26860
+ lowest = vp; // lowest file offset that contains alignments overlapping (min, max)
26861
+ break;
26829
26862
  }
26830
26863
  }
26831
26864
  return optimizeChunks(chunks, lowest);
26832
26865
  }
26833
26866
  }
26834
26867
  }
26835
- function optimizeChunks(chunks, lowest) {
26836
- const mergedChunks = [];
26837
- let lastChunk = null;
26838
- if (chunks.length === 0) return chunks;
26839
- chunks.sort(function (c0, c1) {
26840
- const dif = c0.minv.block - c1.minv.block;
26841
- if (dif !== 0) {
26842
- return dif;
26843
- } else {
26844
- return c0.minv.offset - c1.minv.offset;
26845
- }
26846
- });
26847
- chunks.forEach(function (chunk) {
26848
- if (!lowest || chunk.maxv.isGreaterThan(lowest)) {
26849
- if (lastChunk === null) {
26850
- mergedChunks.push(chunk);
26851
- lastChunk = chunk;
26852
- } else {
26853
- if (canMerge(lastChunk, chunk)) {
26854
- if (chunk.maxv.isGreaterThan(lastChunk.maxv)) {
26855
- lastChunk.maxv = chunk.maxv;
26856
- }
26857
- } else {
26858
- mergedChunks.push(chunk);
26859
- lastChunk = chunk;
26860
- }
26861
- }
26862
- }
26863
- });
26864
- return mergedChunks;
26865
- }
26866
-
26867
- /**
26868
- * Merge 2 blocks if the gap between them is < 1kb and the total resulting size < 100mb
26869
- * @param chunk1
26870
- * @param chunk2
26871
- * @returns {boolean|boolean}
26872
- */
26873
- function canMerge(chunk1, chunk2) {
26874
- const gap = chunk2.minv.block - chunk1.maxv.block;
26875
- const total = chunk2.maxv.block - chunk1.minv.block;
26876
- return gap < 30000 && total < 10 * MB;
26877
- }
26878
26868
 
26879
26869
  /**
26880
26870
  * Calculate the list of bins that overlap with region [beg, end]
@@ -27006,7 +26996,7 @@
27006
26996
  * @param min genomic start position
27007
26997
  * @param max genomic end position
27008
26998
  */
27009
- blocksForRange(queryChr, min, max) {
26999
+ chunksForRange(queryChr, min, max) {
27010
27000
  const chrIdx = this.chrIndex[queryChr];
27011
27001
  if (chrIdx) {
27012
27002
  const blocks = chrIdx.blocks;
@@ -27166,7 +27156,12 @@
27166
27156
  }
27167
27157
  }
27168
27158
 
27169
- class BGZipLineReader {
27159
+ /**
27160
+ * Class to iterate line-by-line over a BGZipped text file. This class is useful for iterating from the start of
27161
+ * the file. Not useful for indexed queries.
27162
+ */
27163
+
27164
+ class BGZLineReader {
27170
27165
  constructor(config) {
27171
27166
  this.config = config;
27172
27167
  this.filePtr = 0;
@@ -27206,7 +27201,7 @@
27206
27201
  }
27207
27202
  });
27208
27203
  const abuffer = await igvxhr.loadArrayBuffer(this.config.url, bsizeOptions);
27209
- const bufferSize = bgzBlockSize(abuffer);
27204
+ const bufferSize = bgzBlockSize$1(abuffer);
27210
27205
  //console.log(`next block ${this.filePtr} ${bufferSize}`);
27211
27206
 
27212
27207
  if (bufferSize === 0) {
@@ -27231,6 +27226,244 @@
27231
27226
  }
27232
27227
  }
27233
27228
 
27229
+ function concatenateArrayBuffers(arrayBuffers) {
27230
+ if (arrayBuffers.length === 1) {
27231
+ return arrayBuffers[0];
27232
+ }
27233
+ let len = 0;
27234
+ for (const b of arrayBuffers) {
27235
+ len += b.byteLength;
27236
+ }
27237
+ const c = new Uint8Array(len);
27238
+ let offset = 0;
27239
+ for (const b of arrayBuffers) {
27240
+ c.set(new Uint8Array(b), offset);
27241
+ offset += b.byteLength;
27242
+ }
27243
+ return c.buffer;
27244
+ }
27245
+
27246
+ /**
27247
+ * Return the block size for the data buffer.
27248
+ * @param data
27249
+ * @returns {number}
27250
+ */
27251
+ const bgzBlockSize = data => {
27252
+ const ba = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
27253
+ const bsize = (ba[17] << 8 | ba[16]) + 1;
27254
+ return bsize;
27255
+ };
27256
+ class BGZBlockLoader {
27257
+ constructor(config) {
27258
+ this.config = config;
27259
+ this.cacheBlocks = false != config.cacheBlocks; // Default to true
27260
+ this.cache = undefined;
27261
+ }
27262
+
27263
+ /**
27264
+ * Return inflated data from startBlock through endBlock as an UInt8Array
27265
+ *
27266
+ * @param startBlock
27267
+ * @param endBlock
27268
+ * @returns {Promise<Uint8Array>}
27269
+ */
27270
+ async getData(startBlock, endBlock) {
27271
+ const blocks = await this.getInflatedBlocks(startBlock, endBlock);
27272
+ if (blocks.length === 1) {
27273
+ return blocks[0];
27274
+ }
27275
+ let len = 0;
27276
+ for (const b of blocks) {
27277
+ len += b.byteLength;
27278
+ }
27279
+ const c = new Uint8Array(len);
27280
+ let offset = 0;
27281
+ for (const b of blocks) {
27282
+ c.set(b, offset);
27283
+ offset += b.byteLength;
27284
+ }
27285
+ return c;
27286
+ }
27287
+
27288
+ /**
27289
+ * Return the inflated data for the specified blocks as an array of Uint8Arrays. This method is public so
27290
+ * it can be unit tested. *
27291
+ * @param startBlock
27292
+ * @param endBlock
27293
+ * @returns {Promise<*[Uint8Array]>}
27294
+ */
27295
+ async getInflatedBlocks(startBlock, endBlock) {
27296
+ if (!this.cacheBlocks) {
27297
+ const buffer = await this.loadBLockData(startBlock, endBlock);
27298
+ return inflateBlocks(buffer);
27299
+ } else {
27300
+ const c = this.cache;
27301
+ if (c && c.startBlock <= startBlock && c.endBlock >= endBlock) {
27302
+ //console.log("Complete overlap")
27303
+ const startOffset = startBlock - c.startBlock;
27304
+ const endOffset = endBlock - c.startBlock;
27305
+ return inflateBlocks(c.buffer, startOffset, endOffset);
27306
+ // Don't update cache, still valid
27307
+ } else {
27308
+ let buffer;
27309
+ if (!c || c.startBlock > endBlock || c.endBlock < startBlock) {
27310
+ // no overlap with cache
27311
+ buffer = await this.loadBLockData(startBlock, endBlock);
27312
+ } else {
27313
+ //console.log("Some overlap")
27314
+ const arrayBuffers = [];
27315
+
27316
+ // Load blocks preceding cache start, if any
27317
+ if (startBlock < c.startBlock) {
27318
+ // load first blocks
27319
+ const startBuffer = await this.loadBLockData(startBlock, c.startBlock, {
27320
+ skipEnd: true
27321
+ });
27322
+ arrayBuffers.push(startBuffer);
27323
+ }
27324
+
27325
+ // Slice cached buffer as needed
27326
+ let cachedBuffer;
27327
+ if (startBlock <= c.startBlock && endBlock >= c.endBlock) {
27328
+ cachedBuffer = c.buffer;
27329
+ } else {
27330
+ const start = Math.max(0, startBlock - c.startBlock);
27331
+ let end;
27332
+ if (endBlock >= c.endBlock) {
27333
+ end = c.buffer.byteLength;
27334
+ } else {
27335
+ // We need to find the byte position of the end of "endBlock"
27336
+ const boundaries = findBlockBoundaries(c.buffer);
27337
+ for (let i = 0; i < boundaries.length - 1; i++) {
27338
+ if (c.startBlock + boundaries[i] === endBlock) {
27339
+ end = boundaries[i + 1];
27340
+ break;
27341
+ }
27342
+ }
27343
+ // Do something if end not found
27344
+ }
27345
+
27346
+ cachedBuffer = c.buffer.slice(start, end);
27347
+ }
27348
+ arrayBuffers.push(cachedBuffer);
27349
+
27350
+ // Load end blocks, if any
27351
+ if (endBlock > c.endBlock) {
27352
+ const endBuffer = await this.loadBLockData(c.endBlock, endBlock, {
27353
+ skipStart: true
27354
+ });
27355
+ arrayBuffers.push(endBuffer);
27356
+ }
27357
+ buffer = concatenateArrayBuffers(arrayBuffers);
27358
+ }
27359
+ this.cache = {
27360
+ startBlock,
27361
+ endBlock,
27362
+ buffer
27363
+ };
27364
+ return inflateBlocks(buffer);
27365
+ }
27366
+ }
27367
+ }
27368
+ async loadBLockData(startBlock, endBlock, options) {
27369
+ const config = this.config;
27370
+ const skipStart = options && options.skipStart;
27371
+ const skipEnd = options && options.skipEnd;
27372
+
27373
+ // Get size of last block if not skipped
27374
+ let lastBlockSize = 0;
27375
+ if (!skipEnd) {
27376
+ const bsizeOptions = buildOptions(config, {
27377
+ range: {
27378
+ start: endBlock,
27379
+ size: 26
27380
+ }
27381
+ });
27382
+ const abuffer = await igvxhr.loadArrayBuffer(config.url, bsizeOptions);
27383
+ lastBlockSize = bgzBlockSize(abuffer);
27384
+ }
27385
+ if (skipStart) {
27386
+ const bsizeOptions = buildOptions(config, {
27387
+ range: {
27388
+ start: startBlock,
27389
+ size: 26
27390
+ }
27391
+ });
27392
+ const abuffer = await igvxhr.loadArrayBuffer(config.url, bsizeOptions);
27393
+ startBlock += bgzBlockSize(abuffer);
27394
+ }
27395
+
27396
+ // Load data for all blocks
27397
+ const loadOptions = buildOptions(config, {
27398
+ range: {
27399
+ start: startBlock,
27400
+ size: endBlock + lastBlockSize - startBlock
27401
+ }
27402
+ });
27403
+
27404
+ //console.log(`${this.config.name} Loaded ${startBlock} - ${endBlock + lastBlockSize} (${(endBlock + lastBlockSize - startBlock) / 1000} kb)`)
27405
+
27406
+ return igvxhr.loadArrayBuffer(config.url, loadOptions);
27407
+ }
27408
+ }
27409
+ function findBlockBoundaries(arrayBuffer) {
27410
+ const byteLengh = arrayBuffer.byteLength;
27411
+ let offset = 0;
27412
+ const blockBoundaries = [0];
27413
+ while (offset < byteLengh) {
27414
+ //console.log("Cache block " + offset)
27415
+ const ba = new Uint8Array(arrayBuffer, offset);
27416
+ const bsize = (ba[17] << 8 | ba[16]) + 1;
27417
+ offset += bsize;
27418
+ if (offset < byteLengh) {
27419
+ blockBoundaries.push(offset);
27420
+ }
27421
+ }
27422
+ return blockBoundaries;
27423
+ }
27424
+
27425
+ /**
27426
+ * Inflate compressed blocks within the data buffer*
27427
+ * @param data
27428
+ * @param startBlock - optional file location for start block. Default == 0
27429
+ * @param endBlock - optional file location for last block to decompress.
27430
+ * @returns {*[]}
27431
+ */
27432
+ function inflateBlocks(data, startBlock, endBlock) {
27433
+ startBlock = startBlock || 0;
27434
+ const oBlockList = [];
27435
+ let ptr = startBlock;
27436
+ const lim = data.byteLength - 18;
27437
+ while (ptr < lim) {
27438
+ try {
27439
+ //console.log(113873 + ptr)
27440
+ const header = new Uint8Array(data, ptr, 18);
27441
+ const xlen = header[11] << 8 | header[10];
27442
+ const bsize = header[17] << 8 | header[16]; // Total block size, including header, minus 1
27443
+ const start = 12 + xlen + ptr; // Start of CDATA
27444
+ const bytesLeft = data.byteLength - start;
27445
+ const cDataSize = bsize - xlen - 18;
27446
+ if (bytesLeft < cDataSize || cDataSize <= 0) {
27447
+ // This is unexpected. Throw error?
27448
+ break;
27449
+ }
27450
+ const cdata = new Uint8Array(data, start, cDataSize);
27451
+ const unc = inflateRaw(cdata);
27452
+ oBlockList.push(unc);
27453
+ if (endBlock === ptr) {
27454
+ break;
27455
+ } else {
27456
+ // Advance to next block
27457
+ ptr += bsize + 1;
27458
+ }
27459
+ } catch (e) {
27460
+ console.error(e);
27461
+ break;
27462
+ }
27463
+ }
27464
+ return oBlockList;
27465
+ }
27466
+
27234
27467
  /*
27235
27468
  * The MIT License (MIT)
27236
27469
  *
@@ -27332,7 +27565,8 @@
27332
27565
  }
27333
27566
  let dataWrapper;
27334
27567
  if (index.tabix) {
27335
- dataWrapper = new BGZipLineReader(this.config);
27568
+ this._blockLoader = new BGZBlockLoader(this.config);
27569
+ dataWrapper = new BGZLineReader(this.config);
27336
27570
  } else {
27337
27571
  // Tribble
27338
27572
  const maxSize = Object.values(index.chrIndex).flatMap(chr => chr.blocks).map(block => block.max).reduce((previous, current) => Math.min(previous, current), Number.MAX_SAFE_INTEGER);
@@ -27408,46 +27642,25 @@
27408
27642
  return [];
27409
27643
  }
27410
27644
  const genome = this.genome;
27411
- const blocks = this.index.blocksForRange(refId, start, end);
27412
- if (!blocks || blocks.length === 0) {
27645
+ const chunks = this.index.chunksForRange(refId, start, end);
27646
+ if (!chunks || chunks.length === 0) {
27413
27647
  return [];
27414
27648
  } else {
27415
27649
  const allFeatures = [];
27416
- for (let block of blocks) {
27417
- const startPos = block.minv.block;
27418
- const startOffset = block.minv.offset;
27419
- const endOffset = block.maxv.offset;
27420
- let endPos;
27421
- if (tabix) {
27422
- let lastBlockSize = 0;
27423
- if (endOffset > 0) {
27424
- const bsizeOptions = buildOptions(config, {
27425
- range: {
27426
- start: block.maxv.block,
27427
- size: 26
27428
- }
27429
- });
27430
- const abuffer = await igvxhr.loadArrayBuffer(config.url, bsizeOptions);
27431
- lastBlockSize = bgzBlockSize(abuffer);
27432
- }
27433
- endPos = block.maxv.block + lastBlockSize;
27434
- } else {
27435
- endPos = block.maxv.block;
27436
- }
27437
- const options = buildOptions(config, {
27438
- range: {
27439
- start: startPos,
27440
- size: endPos - startPos + 1
27441
- }
27442
- });
27650
+ for (let chunk of chunks) {
27443
27651
  let inflated;
27444
27652
  if (tabix) {
27445
- const data = await igvxhr.loadArrayBuffer(config.url, options);
27446
- inflated = unbgzf(data);
27653
+ inflated = await this._blockLoader.getData(chunk.minv.block, chunk.maxv.block);
27447
27654
  } else {
27655
+ const options = buildOptions(config, {
27656
+ range: {
27657
+ start: chunk.minv.block,
27658
+ size: chunk.maxv.block - chunk.minv.block + 1
27659
+ }
27660
+ });
27448
27661
  inflated = await igvxhr.loadString(config.url, options);
27449
27662
  }
27450
- const slicedData = startOffset ? inflated.slice(startOffset) : inflated;
27663
+ const slicedData = chunk.minv.offset ? inflated.slice(chunk.minv.offset) : inflated;
27451
27664
  const dataWrapper = getDataWrapper(slicedData);
27452
27665
  let slicedFeatures = await parser.parseFeatures(dataWrapper);
27453
27666
 
@@ -29873,6 +30086,7 @@
29873
30086
  var documentAll$2 = typeof document == 'object' && document.all;
29874
30087
 
29875
30088
  // https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
30089
+ // eslint-disable-next-line unicorn/no-typeof-undefined -- required for testing
29876
30090
  var IS_HTMLDDA = typeof documentAll$2 == 'undefined' && documentAll$2 !== undefined;
29877
30091
  var documentAll_1 = {
29878
30092
  all: documentAll$2,
@@ -30127,10 +30341,10 @@
30127
30341
  (module.exports = function (key, value) {
30128
30342
  return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {});
30129
30343
  })('versions', []).push({
30130
- version: '3.26.1',
30344
+ version: '3.27.1',
30131
30345
  mode: 'global',
30132
30346
  copyright: '© 2014-2022 Denis Pushkarev (zloirock.ru)',
30133
- license: 'https://github.com/zloirock/core-js/blob/v3.26.1/LICENSE',
30347
+ license: 'https://github.com/zloirock/core-js/blob/v3.27.1/LICENSE',
30134
30348
  source: 'https://github.com/zloirock/core-js'
30135
30349
  });
30136
30350
  });
@@ -33368,6 +33582,7 @@
33368
33582
  this.bamPath = config.url;
33369
33583
  this.baiPath = config.indexURL;
33370
33584
  BamUtils.setReaderDefaults(this, config);
33585
+ this._blockLoader = new BGZBlockLoader(config);
33371
33586
  }
33372
33587
  async readAlignments(chr, bpStart, bpEnd) {
33373
33588
  const chrToIndex = await this.getChrIndex();
@@ -33378,37 +33593,14 @@
33378
33593
  return alignmentContainer;
33379
33594
  } else {
33380
33595
  const bamIndex = await this.getIndex();
33381
- const chunks = bamIndex.blocksForRange(chrId, bpStart, bpEnd);
33596
+ const chunks = bamIndex.chunksForRange(chrId, bpStart, bpEnd);
33382
33597
  if (!chunks || chunks.length === 0) {
33383
33598
  return alignmentContainer;
33384
33599
  }
33385
33600
  for (let c of chunks) {
33386
- let lastBlockSize;
33387
- if (c.maxv.offset === 0) {
33388
- lastBlockSize = 0; // Don't need to read the last block.
33389
- } else {
33390
- const bsizeOptions = buildOptions(this.config, {
33391
- range: {
33392
- start: c.maxv.block,
33393
- size: 26
33394
- }
33395
- });
33396
- const abuffer = await igvxhr.loadArrayBuffer(this.bamPath, bsizeOptions);
33397
- lastBlockSize = bgzBlockSize(abuffer);
33398
- }
33399
- const fetchMin = c.minv.block;
33400
- const fetchMax = c.maxv.block + lastBlockSize;
33401
- const range = {
33402
- start: fetchMin,
33403
- size: fetchMax - fetchMin + 1
33404
- };
33405
- const compressed = await igvxhr.loadArrayBuffer(this.bamPath, buildOptions(this.config, {
33406
- range: range
33407
- }));
33408
- var ba = unbgzf(compressed); //new Uint8Array(BGZip.unbgzf(compressed)); //, c.maxv.block - c.minv.block + 1));
33601
+ const ba = await this._blockLoader.getData(c.minv.block, c.maxv.block);
33409
33602
  const done = BamUtils.decodeBamRecords(ba, c.minv.offset, alignmentContainer, this.indexToChr, chrId, bpStart, bpEnd, this.filter);
33410
33603
  if (done) {
33411
- // console.log(`Loaded ${counter} chunks out of ${chunks.length}`);
33412
33604
  break;
33413
33605
  }
33414
33606
  }
@@ -33429,7 +33621,7 @@
33429
33621
  }
33430
33622
  });
33431
33623
  const abuffer = await igvxhr.loadArrayBuffer(this.bamPath, bsizeOptions);
33432
- const bsize = bgzBlockSize(abuffer);
33624
+ const bsize = bgzBlockSize$1(abuffer);
33433
33625
  len = index.firstBlockPosition + bsize; // Insure we get the complete compressed block containing the header
33434
33626
  } else {
33435
33627
  len = 64000;
@@ -33967,7 +34159,7 @@
33967
34159
  var clear = global$1.clearImmediate;
33968
34160
  var process$1 = global$1.process;
33969
34161
  var Dispatch = global$1.Dispatch;
33970
- var Function$1 = global$1.Function;
34162
+ var Function$2 = global$1.Function;
33971
34163
  var MessageChannel$1 = global$1.MessageChannel;
33972
34164
  var String$1 = global$1.String;
33973
34165
  var counter = 0;
@@ -34002,7 +34194,7 @@
34002
34194
  if (!set || !clear) {
34003
34195
  set = function setImmediate(handler) {
34004
34196
  validateArgumentsLength(arguments.length, 1);
34005
- var fn = isCallable(handler) ? handler : Function$1(handler);
34197
+ var fn = isCallable(handler) ? handler : Function$2(handler);
34006
34198
  var args = arraySlice(arguments, 1);
34007
34199
  queue[++counter] = function () {
34008
34200
  functionApply(fn, undefined, args);
@@ -34068,7 +34260,36 @@
34068
34260
  clearImmediate: clearImmediate
34069
34261
  });
34070
34262
 
34071
- var setImmediate = task.set;
34263
+ /* global Bun -- Deno case */
34264
+ var engineIsBun = typeof Bun == 'function' && Bun && typeof Bun.version == 'string';
34265
+
34266
+ var Function$1 = global$1.Function;
34267
+ // dirty IE9- and Bun 0.3.0- checks
34268
+ var WRAP = /MSIE .\./.test(engineUserAgent) || engineIsBun && function () {
34269
+ var version = global$1.Bun.version.split('.');
34270
+ return version.length < 3 || version[0] == 0 && (version[1] < 3 || version[1] == 3 && version[2] == 0);
34271
+ }();
34272
+
34273
+ // IE9- / Bun 0.3.0- setTimeout / setInterval / setImmediate additional parameters fix
34274
+ // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers
34275
+ // https://github.com/oven-sh/bun/issues/1633
34276
+ var schedulersFix = function (scheduler, hasTimeArg) {
34277
+ var firstParamIndex = hasTimeArg ? 2 : 1;
34278
+ return WRAP ? function (handler, timeout /* , ...arguments */) {
34279
+ var boundArgs = validateArgumentsLength(arguments.length, 1) > firstParamIndex;
34280
+ var fn = isCallable(handler) ? handler : Function$1(handler);
34281
+ var params = boundArgs ? arraySlice(arguments, firstParamIndex) : [];
34282
+ var callback = boundArgs ? function () {
34283
+ functionApply(fn, this, params);
34284
+ } : fn;
34285
+ return hasTimeArg ? scheduler(callback, timeout) : scheduler(callback);
34286
+ } : scheduler;
34287
+ };
34288
+
34289
+ var setTask = task.set;
34290
+
34291
+ // https://github.com/oven-sh/bun/issues/1633
34292
+ var setImmediate = global$1.setImmediate ? schedulersFix(setTask, false) : setTask;
34072
34293
 
34073
34294
  // `setImmediate` method
34074
34295
  // http://w3c.github.io/setImmediate/#si-setImmediate
@@ -50411,7 +50632,9 @@
50411
50632
  hoverText(clickState) {
50412
50633
  if (true === this.showCoverage && clickState.y >= this.coverageTrack.top && clickState.y < this.coverageTrack.height) {
50413
50634
  const clickedObject = this.coverageTrack.getClickedObject(clickState);
50414
- return clickedObject.hoverText();
50635
+ if (clickedObject) {
50636
+ return clickedObject.hoverText();
50637
+ }
50415
50638
  }
50416
50639
  }
50417
50640
  menuItemList() {