igv 3.0.5 → 3.0.6

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
@@ -22880,6 +22880,20 @@
22880
22880
  this.length = dataView.byteLength;
22881
22881
  }
22882
22882
 
22883
+ /**
22884
+ * Print the first "n" bytes to the console. Used for debugging.
22885
+ * @param n
22886
+ */
22887
+ dumpBytes (n = 100) {
22888
+ const pos = this.position;
22889
+ const bytes = [];
22890
+ for(let i=0; i<= n; i++) {
22891
+ bytes.push(this.getByte());
22892
+ }
22893
+ console.log(bytes.join(" "));
22894
+ this.setPosition(pos);
22895
+ }
22896
+
22883
22897
  setPosition(position) {
22884
22898
  this.position = position;
22885
22899
  }
@@ -31443,7 +31457,6 @@
31443
31457
  const idToName = [];
31444
31458
  let sumLengths = 0;
31445
31459
  const readTreeNode = (offset) => {
31446
-
31447
31460
  if (offset >= 0) binaryParser.position = offset;
31448
31461
  const type = binaryParser.getByte();
31449
31462
  binaryParser.getByte();
@@ -31480,7 +31493,7 @@
31480
31493
  };
31481
31494
 
31482
31495
  // Recursively walk tree to populate dictionary
31483
- readTreeNode(binaryParser);
31496
+ readTreeNode( -1);
31484
31497
 
31485
31498
  return new ChromTree(header, nameToId, idToName, sumLengths)
31486
31499
  }
@@ -32171,6 +32184,16 @@
32171
32184
  }
32172
32185
  }
32173
32186
 
32187
+ /**
32188
+ * The BB header consists of
32189
+ * (1) the common header
32190
+ * (2) the zoom headers
32191
+ * (3) autosql
32192
+ * (4) total summary block (version 2 and later)
32193
+ *
32194
+ * In addition, we read the chromomsome B+ tree
32195
+ * @returns {Promise<*>}
32196
+ */
32174
32197
  async loadHeader() {
32175
32198
 
32176
32199
  if (this.header) {
@@ -32188,7 +32211,7 @@
32188
32211
  // Assume low-to-high unless proven otherwise
32189
32212
  this.littleEndian = true;
32190
32213
 
32191
- let binaryParser = new BinaryParser$1(new DataView(data), this.littleEndian);
32214
+ const binaryParser = new BinaryParser$1(new DataView(data), this.littleEndian);
32192
32215
  let magic = binaryParser.getUInt();
32193
32216
  if (magic === BIGWIG_MAGIC_LTH$1) {
32194
32217
  this.type = "bigwig";
@@ -32223,30 +32246,33 @@
32223
32246
  extensionOffset: binaryParser.getLong()
32224
32247
  };
32225
32248
 
32249
+ // Read the next chunk containing zoom headers, autosql, and total summary if present. TotalSummary size = 40 bytes
32226
32250
  const startOffset = BBFILE_HEADER_SIZE;
32251
+ const size = header.totalSummaryOffset > 0 ?
32252
+ header.totalSummaryOffset - startOffset + 40 :
32253
+ Math.min(header.fullDataOffset, header.chromTreeOffset) - startOffset;
32227
32254
  let range = {
32228
32255
  start: startOffset,
32229
- size: (header.fullDataOffset - startOffset + 4)
32256
+ size: size
32230
32257
  };
32231
32258
  data = await this.loader.loadArrayBuffer(this.path, buildOptions(this.config, {range: range}));
32232
-
32233
- const nZooms = header.nZoomLevels;
32234
- binaryParser = new BinaryParser$1(new DataView(data), this.littleEndian);
32259
+ const extHeaderParser = new BinaryParser$1(new DataView(data), this.littleEndian);
32235
32260
 
32236
32261
  // Load zoom headers, store in order of decreasing reduction level (increasing resolution)
32262
+ const nZooms = header.nZoomLevels;
32237
32263
  this.zoomLevelHeaders = [];
32238
32264
  this.firstZoomDataOffset = Number.MAX_SAFE_INTEGER;
32239
32265
  for (let i = 1; i <= nZooms; i++) {
32240
32266
  const zoomNumber = nZooms - i;
32241
- const zlh = new ZoomLevelHeader(zoomNumber, binaryParser);
32267
+ const zlh = new ZoomLevelHeader(zoomNumber, extHeaderParser);
32242
32268
  this.firstZoomDataOffset = Math.min(zlh.dataOffset, this.firstZoomDataOffset);
32243
32269
  this.zoomLevelHeaders[zoomNumber] = zlh;
32244
32270
  }
32245
32271
 
32246
32272
  // Autosql
32247
32273
  if (header.autoSqlOffset > 0) {
32248
- binaryParser.position = header.autoSqlOffset - startOffset;
32249
- const autoSqlString = binaryParser.getString();
32274
+ extHeaderParser.position = header.autoSqlOffset - startOffset;
32275
+ const autoSqlString = extHeaderParser.getString();
32250
32276
  if (autoSqlString) {
32251
32277
  this.autoSql = parseAutoSQL(autoSqlString);
32252
32278
  }
@@ -32254,35 +32280,73 @@
32254
32280
 
32255
32281
  // Total summary
32256
32282
  if (header.totalSummaryOffset > 0) {
32257
- binaryParser.position = header.totalSummaryOffset - startOffset;
32258
- this.totalSummary = new BWTotalSummary(binaryParser);
32259
- }
32260
-
32261
- // Chrom data index
32262
- if (header.chromTreeOffset > 0) {
32263
- binaryParser.position = header.chromTreeOffset - startOffset;
32264
- this.chromTree = await ChromTree.parseTree(binaryParser, startOffset, this.genome);
32265
- this.chrNames = new Set(this.chromTree.idToName);
32266
- } else {
32267
- // TODO -- this is an error, not expected
32268
- throw "BigWig chromosome tree offset <= 0"
32283
+ extHeaderParser.position = header.totalSummaryOffset - startOffset;
32284
+ this.totalSummary = new BWTotalSummary(extHeaderParser);
32269
32285
  }
32270
32286
 
32271
- //Finally total data count
32272
- binaryParser.position = header.fullDataOffset - startOffset;
32273
- header.dataCount = binaryParser.getInt();
32287
+ // Chrom data index. The start is known, size is not, but we can estimate it
32288
+ const bufferSize = Math.min(200000, Math.max(10000, header.fullDataOffset - header.chromTreeOffset));
32289
+ this.chromTree = await this.#readChromTree(header.chromTreeOffset, bufferSize);
32290
+ this.chrNames = new Set(this.chromTree.idToName);
32274
32291
 
32275
- this.featureDensity = header.dataCount / this.chromTree.sumLengths;
32292
+ // Estimate feature density from dataCount (bigbed only)
32293
+ if("bigbed" === this.type) {
32294
+ const dataCount = await this.#readDataCount(header.fullDataOffset);
32295
+ this.featureDensity = dataCount / this.chromTree.sumLengths;
32296
+ }
32276
32297
 
32277
32298
  this.header = header;
32278
32299
 
32279
-
32280
32300
  //extension
32281
32301
  if (header.extensionOffset > 0) {
32282
32302
  await this.loadExtendedHeader(header.extensionOffset);
32283
32303
  }
32284
- return this.header
32304
+ return this.header
32305
+ }
32306
+ }
32307
+
32308
+ async #readDataCount(offset) {
32309
+ const data = await this.loader.loadArrayBuffer(this.path, buildOptions(this.config, {
32310
+ range: {
32311
+ start: offset,
32312
+ size: 4
32313
+ }
32314
+ }));
32315
+ const binaryParser = new BinaryParser$1(new DataView(data), this.littleEndian);
32316
+ return binaryParser.getInt()
32317
+ }
32318
+
32319
+ /**
32320
+ * Used when the chromTreeOffset is > fullDataOffset, that is when the chrom tree is not in the initial chunk
32321
+ * read for parsing the header. We know the start position, but not the total size of the chrom tree
32322
+ *
32323
+ * @returns {Promise<void>}
32324
+ */
32325
+ async #readChromTree(chromTreeOffset, bufferSize) {
32326
+
32327
+ let size = bufferSize;
32328
+ const load = async () => {
32329
+ const data = await this.loader.loadArrayBuffer(this.path, buildOptions(this.config, {
32330
+ range: {
32331
+ start: chromTreeOffset,
32332
+ size: size
32333
+ }
32334
+ }));
32335
+ const binaryParser = new BinaryParser$1(new DataView(data), this.littleEndian);
32336
+ return ChromTree.parseTree(binaryParser, chromTreeOffset, this.genome)
32337
+ };
32338
+
32339
+ let error;
32340
+ while (size < 1000000) {
32341
+ try {
32342
+ const chromTree = await load();
32343
+ return chromTree
32344
+ } catch (e) {
32345
+ error = e;
32346
+ size *= 2;
32347
+ }
32285
32348
  }
32349
+ throw (error)
32286
32350
  }
32287
32351
 
32288
32352
  async loadExtendedHeader(offset) {
@@ -33459,7 +33523,10 @@
33459
33523
  for (let feature of featureList) {
33460
33524
  for (let field of searchableFields) {
33461
33525
  let key;
33462
- if (typeof feature.getAttributeValue === 'function') {
33526
+ if(feature.hasOwnProperty(field)) {
33527
+ key = feature[field];
33528
+ }
33529
+ else if (typeof feature.getAttributeValue === 'function') {
33463
33530
  key = feature.getAttributeValue(field);
33464
33531
  }
33465
33532
  if (key) {
@@ -70527,7 +70594,7 @@
70527
70594
  })
70528
70595
  }
70529
70596
 
70530
- const _version = "3.0.5";
70597
+ const _version = "3.0.6";
70531
70598
  function version() {
70532
70599
  return _version
70533
70600
  }
@@ -76262,7 +76329,7 @@
76262
76329
  async function keyUpHandler(event) {
76263
76330
 
76264
76331
  // Feature jumping disabled in multi-locus view
76265
- if (this.referenceFrameList.length > 1) return
76332
+ if (!this.referenceFrameList || this.referenceFrameList.length > 1) return
76266
76333
 
76267
76334
  if (event.code === 'KeyF' || event.code === 'KeyB') {
76268
76335