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/README.md CHANGED
@@ -18,19 +18,19 @@ Below are examples and a quickstart guide. See the [developer documentation](ht
18
18
 
19
19
  # Examples
20
20
 
21
- ***[Alignments](https://igv.org/web/release/3.0.3/examples/cram-vcf.html)***
21
+ ***[Alignments](https://igv.org/web/release/3.0.6/examples/cram-vcf.html)***
22
22
 
23
- ***[Interactions](https://igv.org/web/release/3.0.3/examples/interact.html)***
23
+ ***[Interactions](https://igv.org/web/release/3.0.6/examples/interact.html)***
24
24
 
25
- ***[Copy number](https://igv.org/web/release/3.0.3/examples/copyNumber.html)***
25
+ ***[Copy number](https://igv.org/web/release/3.0.6/examples/copyNumber.html)***
26
26
 
27
- ***[Multiple regions](https://igv.org/web/release/3.0.3/examples/multi-locus.html)***
27
+ ***[Multiple regions](https://igv.org/web/release/3.0.6/examples/multi-locus.html)***
28
28
 
29
- ***[Mutation Annotation Format (MAF)](https://igv.org/web/release/3.0.3/examples/maf-tcga.html)***
29
+ ***[Mutation Annotation Format (MAF)](https://igv.org/web/release/3.0.6/examples/maf-tcga.html)***
30
30
 
31
- ***[Variant color options](https://igv.org/web/release/3.0.3/examples/variant-colors.html)***
31
+ ***[Variant color options](https://igv.org/web/release/3.0.6/examples/variant-colors.html)***
32
32
 
33
- ***[More](https://igv.org/web/release/3.0.3/examples/)***
33
+ ***[More](https://igv.org/web/release/3.0.6/examples/)***
34
34
 
35
35
 
36
36
  # Quickstart
@@ -39,18 +39,18 @@ Below are examples and a quickstart guide. See the [developer documentation](ht
39
39
  igv.js consists of a single javascript file with no external dependencies.
40
40
 
41
41
  Pre-built files for script include, AMD, or CJS module systems (igv.min.js) and an ES6 module (igv.esm.min.js)
42
- can be downloaded from [https://cdn.jsdelivr.net/npm/igv@3.0.3/dist/](https://cdn.jsdelivr.net/npm/igv@3.0.3/dist/).
42
+ can be downloaded from [https://cdn.jsdelivr.net/npm/igv@3.0.6/dist/](https://cdn.jsdelivr.net/npm/igv@3.0.6/dist/).
43
43
 
44
44
  To import igv as an ES6 module
45
45
 
46
46
  ```javascript
47
- import igv from "https://cdn.jsdelivr.net/npm/igv@3.0.3/dist/igv.esm.min.js"
47
+ import igv from "https://cdn.jsdelivr.net/npm/igv@3.0.6/dist/igv.esm.min.js"
48
48
  ```
49
49
 
50
50
  Or as a script include (defines the "igv" global)
51
51
 
52
52
  ```html
53
- <script src="https://cdn.jsdelivr.net/npm/igv@3.0.3/dist/igv.min.js"></script>
53
+ <script src="https://cdn.jsdelivr.net/npm/igv@3.0.6/dist/igv.min.js"></script>
54
54
  ```
55
55
 
56
56
  Alternatively you can install with npm
@@ -91,7 +91,9 @@ a browser on a single alignment track opened at a specific locus:
91
91
  })
92
92
  ```
93
93
 
94
- For more details see the [Wiki](https://github.com/igvteam/igv.js/wiki) for full documentation of the API.
94
+ ## Documentation
95
+
96
+ Full documentation of the igv.js API is available at [https://igv.org/doc/igvjs/](https://igv.org/doc/igvjs/).
95
97
 
96
98
  ## Development
97
99
 
package/dist/igv.esm.js CHANGED
@@ -22874,6 +22874,20 @@ class BinaryParser$1 {
22874
22874
  this.length = dataView.byteLength;
22875
22875
  }
22876
22876
 
22877
+ /**
22878
+ * Print the first "n" bytes to the console. Used for debugging.
22879
+ * @param n
22880
+ */
22881
+ dumpBytes (n = 100) {
22882
+ const pos = this.position;
22883
+ const bytes = [];
22884
+ for(let i=0; i<= n; i++) {
22885
+ bytes.push(this.getByte());
22886
+ }
22887
+ console.log(bytes.join(" "));
22888
+ this.setPosition(pos);
22889
+ }
22890
+
22877
22891
  setPosition(position) {
22878
22892
  this.position = position;
22879
22893
  }
@@ -31437,7 +31451,6 @@ class ChromTree {
31437
31451
  const idToName = [];
31438
31452
  let sumLengths = 0;
31439
31453
  const readTreeNode = (offset) => {
31440
-
31441
31454
  if (offset >= 0) binaryParser.position = offset;
31442
31455
  const type = binaryParser.getByte();
31443
31456
  binaryParser.getByte();
@@ -31474,7 +31487,7 @@ class ChromTree {
31474
31487
  };
31475
31488
 
31476
31489
  // Recursively walk tree to populate dictionary
31477
- readTreeNode(binaryParser);
31490
+ readTreeNode( -1);
31478
31491
 
31479
31492
  return new ChromTree(header, nameToId, idToName, sumLengths)
31480
31493
  }
@@ -32165,6 +32178,16 @@ class BWReader {
32165
32178
  }
32166
32179
  }
32167
32180
 
32181
+ /**
32182
+ * The BB header consists of
32183
+ * (1) the common header
32184
+ * (2) the zoom headers
32185
+ * (3) autosql
32186
+ * (4) total summary block (version 2 and later)
32187
+ *
32188
+ * In addition, we read the chromomsome B+ tree
32189
+ * @returns {Promise<*>}
32190
+ */
32168
32191
  async loadHeader() {
32169
32192
 
32170
32193
  if (this.header) {
@@ -32182,7 +32205,7 @@ class BWReader {
32182
32205
  // Assume low-to-high unless proven otherwise
32183
32206
  this.littleEndian = true;
32184
32207
 
32185
- let binaryParser = new BinaryParser$1(new DataView(data), this.littleEndian);
32208
+ const binaryParser = new BinaryParser$1(new DataView(data), this.littleEndian);
32186
32209
  let magic = binaryParser.getUInt();
32187
32210
  if (magic === BIGWIG_MAGIC_LTH$1) {
32188
32211
  this.type = "bigwig";
@@ -32217,30 +32240,33 @@ class BWReader {
32217
32240
  extensionOffset: binaryParser.getLong()
32218
32241
  };
32219
32242
 
32243
+ // Read the next chunk containing zoom headers, autosql, and total summary if present. TotalSummary size = 40 bytes
32220
32244
  const startOffset = BBFILE_HEADER_SIZE;
32245
+ const size = header.totalSummaryOffset > 0 ?
32246
+ header.totalSummaryOffset - startOffset + 40 :
32247
+ Math.min(header.fullDataOffset, header.chromTreeOffset) - startOffset;
32221
32248
  let range = {
32222
32249
  start: startOffset,
32223
- size: (header.fullDataOffset - startOffset + 4)
32250
+ size: size
32224
32251
  };
32225
32252
  data = await this.loader.loadArrayBuffer(this.path, buildOptions(this.config, {range: range}));
32226
-
32227
- const nZooms = header.nZoomLevels;
32228
- binaryParser = new BinaryParser$1(new DataView(data), this.littleEndian);
32253
+ const extHeaderParser = new BinaryParser$1(new DataView(data), this.littleEndian);
32229
32254
 
32230
32255
  // Load zoom headers, store in order of decreasing reduction level (increasing resolution)
32256
+ const nZooms = header.nZoomLevels;
32231
32257
  this.zoomLevelHeaders = [];
32232
32258
  this.firstZoomDataOffset = Number.MAX_SAFE_INTEGER;
32233
32259
  for (let i = 1; i <= nZooms; i++) {
32234
32260
  const zoomNumber = nZooms - i;
32235
- const zlh = new ZoomLevelHeader(zoomNumber, binaryParser);
32261
+ const zlh = new ZoomLevelHeader(zoomNumber, extHeaderParser);
32236
32262
  this.firstZoomDataOffset = Math.min(zlh.dataOffset, this.firstZoomDataOffset);
32237
32263
  this.zoomLevelHeaders[zoomNumber] = zlh;
32238
32264
  }
32239
32265
 
32240
32266
  // Autosql
32241
32267
  if (header.autoSqlOffset > 0) {
32242
- binaryParser.position = header.autoSqlOffset - startOffset;
32243
- const autoSqlString = binaryParser.getString();
32268
+ extHeaderParser.position = header.autoSqlOffset - startOffset;
32269
+ const autoSqlString = extHeaderParser.getString();
32244
32270
  if (autoSqlString) {
32245
32271
  this.autoSql = parseAutoSQL(autoSqlString);
32246
32272
  }
@@ -32248,35 +32274,73 @@ class BWReader {
32248
32274
 
32249
32275
  // Total summary
32250
32276
  if (header.totalSummaryOffset > 0) {
32251
- binaryParser.position = header.totalSummaryOffset - startOffset;
32252
- this.totalSummary = new BWTotalSummary(binaryParser);
32253
- }
32254
-
32255
- // Chrom data index
32256
- if (header.chromTreeOffset > 0) {
32257
- binaryParser.position = header.chromTreeOffset - startOffset;
32258
- this.chromTree = await ChromTree.parseTree(binaryParser, startOffset, this.genome);
32259
- this.chrNames = new Set(this.chromTree.idToName);
32260
- } else {
32261
- // TODO -- this is an error, not expected
32262
- throw "BigWig chromosome tree offset <= 0"
32277
+ extHeaderParser.position = header.totalSummaryOffset - startOffset;
32278
+ this.totalSummary = new BWTotalSummary(extHeaderParser);
32263
32279
  }
32264
32280
 
32265
- //Finally total data count
32266
- binaryParser.position = header.fullDataOffset - startOffset;
32267
- header.dataCount = binaryParser.getInt();
32281
+ // Chrom data index. The start is known, size is not, but we can estimate it
32282
+ const bufferSize = Math.min(200000, Math.max(10000, header.fullDataOffset - header.chromTreeOffset));
32283
+ this.chromTree = await this.#readChromTree(header.chromTreeOffset, bufferSize);
32284
+ this.chrNames = new Set(this.chromTree.idToName);
32268
32285
 
32269
- this.featureDensity = header.dataCount / this.chromTree.sumLengths;
32286
+ // Estimate feature density from dataCount (bigbed only)
32287
+ if("bigbed" === this.type) {
32288
+ const dataCount = await this.#readDataCount(header.fullDataOffset);
32289
+ this.featureDensity = dataCount / this.chromTree.sumLengths;
32290
+ }
32270
32291
 
32271
32292
  this.header = header;
32272
32293
 
32273
-
32274
32294
  //extension
32275
32295
  if (header.extensionOffset > 0) {
32276
32296
  await this.loadExtendedHeader(header.extensionOffset);
32277
32297
  }
32278
- return this.header
32298
+ return this.header
32299
+ }
32300
+ }
32301
+
32302
+ async #readDataCount(offset) {
32303
+ const data = await this.loader.loadArrayBuffer(this.path, buildOptions(this.config, {
32304
+ range: {
32305
+ start: offset,
32306
+ size: 4
32307
+ }
32308
+ }));
32309
+ const binaryParser = new BinaryParser$1(new DataView(data), this.littleEndian);
32310
+ return binaryParser.getInt()
32311
+ }
32312
+
32313
+ /**
32314
+ * Used when the chromTreeOffset is > fullDataOffset, that is when the chrom tree is not in the initial chunk
32315
+ * read for parsing the header. We know the start position, but not the total size of the chrom tree
32316
+ *
32317
+ * @returns {Promise<void>}
32318
+ */
32319
+ async #readChromTree(chromTreeOffset, bufferSize) {
32320
+
32321
+ let size = bufferSize;
32322
+ const load = async () => {
32323
+ const data = await this.loader.loadArrayBuffer(this.path, buildOptions(this.config, {
32324
+ range: {
32325
+ start: chromTreeOffset,
32326
+ size: size
32327
+ }
32328
+ }));
32329
+ const binaryParser = new BinaryParser$1(new DataView(data), this.littleEndian);
32330
+ return ChromTree.parseTree(binaryParser, chromTreeOffset, this.genome)
32331
+ };
32332
+
32333
+ let error;
32334
+ while (size < 1000000) {
32335
+ try {
32336
+ const chromTree = await load();
32337
+ return chromTree
32338
+ } catch (e) {
32339
+ error = e;
32340
+ size *= 2;
32341
+ }
32279
32342
  }
32343
+ throw (error)
32280
32344
  }
32281
32345
 
32282
32346
  async loadExtendedHeader(offset) {
@@ -33453,7 +33517,10 @@ class TextFeatureSource extends BaseFeatureSource {
33453
33517
  for (let feature of featureList) {
33454
33518
  for (let field of searchableFields) {
33455
33519
  let key;
33456
- if (typeof feature.getAttributeValue === 'function') {
33520
+ if(feature.hasOwnProperty(field)) {
33521
+ key = feature[field];
33522
+ }
33523
+ else if (typeof feature.getAttributeValue === 'function') {
33457
33524
  key = feature.getAttributeValue(field);
33458
33525
  }
33459
33526
  if (key) {
@@ -70521,7 +70588,7 @@ function createReferenceFrameList(loci, genome, browserFlanking, minimumBases, v
70521
70588
  })
70522
70589
  }
70523
70590
 
70524
- const _version = "3.0.5";
70591
+ const _version = "3.0.6";
70525
70592
  function version() {
70526
70593
  return _version
70527
70594
  }
@@ -76256,7 +76323,7 @@ function mouseUpOrLeave(e) {
76256
76323
  async function keyUpHandler(event) {
76257
76324
 
76258
76325
  // Feature jumping disabled in multi-locus view
76259
- if (this.referenceFrameList.length > 1) return
76326
+ if (!this.referenceFrameList || this.referenceFrameList.length > 1) return
76260
76327
 
76261
76328
  if (event.code === 'KeyF' || event.code === 'KeyB') {
76262
76329