igv 2.12.2 → 2.12.3

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
@@ -12,19 +12,19 @@ Below are examples and a quickstart guide. See the [Wiki](https://github.com/ig
12
12
 
13
13
  # Examples
14
14
 
15
- ***[Alignments](https://igv.org/web/release/2.12.2/examples/cram-vcf.html)***
15
+ ***[Alignments](https://igv.org/web/release/2.12.3/examples/cram-vcf.html)***
16
16
 
17
- ***[Interactions](https://igv.org/web/release/2.12.2/examples/interact.html)***
17
+ ***[Interactions](https://igv.org/web/release/2.12.3/examples/interact.html)***
18
18
 
19
- ***[Copy number](https://igv.org/web/release/2.12.2/examples/copyNumber.html)***
19
+ ***[Copy number](https://igv.org/web/release/2.12.3/examples/copyNumber.html)***
20
20
 
21
- ***[Multiple regions](https://igv.org/web/release/2.12.2/examples/multi-locus.html)***
21
+ ***[Multiple regions](https://igv.org/web/release/2.12.3/examples/multi-locus.html)***
22
22
 
23
- ***[Mutation Annotation Format (MAF)](https://igv.org/web/release/2.12.2/examples/maf-tcga.html)***
23
+ ***[Mutation Annotation Format (MAF)](https://igv.org/web/release/2.12.3/examples/maf-tcga.html)***
24
24
 
25
- ***[Variant color options](https://igv.org/web/release/2.12.2/examples/variant-colors.html)***
25
+ ***[Variant color options](https://igv.org/web/release/2.12.3/examples/variant-colors.html)***
26
26
 
27
- ***[More](https://igv.org/web/release/2.12.2/examples/)***
27
+ ***[More](https://igv.org/web/release/2.12.3/examples/)***
28
28
 
29
29
 
30
30
  # Quickstart
@@ -33,18 +33,18 @@ Below are examples and a quickstart guide. See the [Wiki](https://github.com/ig
33
33
  igv.js consists of a single javascript file with no external dependencies.
34
34
 
35
35
  Pre-built files for ES5 (igv.min.js) and ES6 (igv.esm.min.js)
36
- can be downloaded from [https://cdn.jsdelivr.net/npm/igv@2.12.2/dist/](https://cdn.jsdelivr.net/npm/igv@2.12.2/dist/).
36
+ can be downloaded from [https://cdn.jsdelivr.net/npm/igv@2.12.3/dist/](https://cdn.jsdelivr.net/npm/igv@2.12.3/dist/).
37
37
 
38
38
  To import igv as an ES6 module
39
39
 
40
40
  ```javascript
41
- import igv from "https://cdn.jsdelivr.net/npm/igv@2.12.2/dist/igv.esm.min.js"
41
+ import igv from "https://cdn.jsdelivr.net/npm/igv@2.12.3/dist/igv.esm.min.js"
42
42
  ```
43
43
 
44
44
  Or as a script include (defines the "igv" global)
45
45
 
46
46
  ```html
47
- <script src="https://cdn.jsdelivr.net/npm/igv@2.12.2/dist/igv.min.js"></script>
47
+ <script src="https://cdn.jsdelivr.net/npm/igv@2.12.3/dist/igv.min.js"></script>
48
48
  ```
49
49
 
50
50
  Alternatively you can install with npm
package/dist/igv.esm.js CHANGED
@@ -20251,6 +20251,12 @@ for (let i = 0; i < t1.length; i++) {
20251
20251
  complement[t1[i].toLowerCase()] = t2[i].toLowerCase();
20252
20252
  }
20253
20253
 
20254
+ const DEFAULT_HEIGHT = 25;
20255
+ const TRANSLATED_HEIGHT = 115;
20256
+ const SEQUENCE_HEIGHT = 15;
20257
+ const FRAME_HEIGHT = 25;
20258
+ const FRAME_BORDER = 5;
20259
+
20254
20260
  class SequenceTrack {
20255
20261
 
20256
20262
  constructor(config, browser) {
@@ -20262,13 +20268,13 @@ class SequenceTrack {
20262
20268
  this.name = "Sequence";
20263
20269
  this.id = "sequence";
20264
20270
  this.sequenceType = config.sequenceType || "dna"; // dna | rna | prot
20265
- this.height = 25;
20266
20271
  this.disableButtons = false;
20267
20272
  this.order = config.order || defaultSequenceTrackOrder;
20268
20273
  this.ignoreTrackMenu = false;
20269
20274
 
20270
- this.reversed = false;
20271
- this.frameTranslate = false;
20275
+ this.reversed = config.reversed === true;
20276
+ this.frameTranslate = config.frameTranslate === true;
20277
+ this.height = this.frameTranslate ? TRANSLATED_HEIGHT : DEFAULT_HEIGHT;
20272
20278
 
20273
20279
  }
20274
20280
 
@@ -20287,14 +20293,14 @@ class SequenceTrack {
20287
20293
  this.frameTranslate = !this.frameTranslate;
20288
20294
  if (this.frameTranslate) {
20289
20295
  for (let vp of this.trackView.viewports) {
20290
- vp.setContentHeight(115);
20296
+ vp.setContentHeight(TRANSLATED_HEIGHT);
20291
20297
  }
20292
- this.trackView.setTrackHeight(115);
20298
+ this.trackView.setTrackHeight(TRANSLATED_HEIGHT);
20293
20299
  } else {
20294
20300
  for (let vp of this.trackView.viewports) {
20295
- vp.setContentHeight(25);
20301
+ vp.setContentHeight(DEFAULT_HEIGHT);
20296
20302
  }
20297
- this.trackView.setTrackHeight(25);
20303
+ this.trackView.setTrackHeight(DEFAULT_HEIGHT);
20298
20304
  }
20299
20305
  this.trackView.repaintViews();
20300
20306
 
@@ -20377,7 +20383,8 @@ class SequenceTrack {
20377
20383
  }
20378
20384
 
20379
20385
  async getFeatures(chr, start, end, bpPerPixel) {
20380
-
20386
+ start = Math.floor(start);
20387
+ end = Math.floor(end);
20381
20388
  if (bpPerPixel && bpPerPixel > 1) {
20382
20389
  return null
20383
20390
  } else {
@@ -20395,89 +20402,79 @@ class SequenceTrack {
20395
20402
 
20396
20403
  if (options.features) {
20397
20404
 
20398
- const sequence = options.features.sequence;
20399
- const sequenceBpStart = options.features.bpStart;
20400
- const bpEnd = 1 + options.bpStart + (options.pixelWidth * options.bpPerPixel);
20405
+ let sequence = options.features.sequence;
20401
20406
 
20402
- let height = 15;
20403
- for (let bp = sequenceBpStart; bp <= bpEnd; bp++) {
20407
+ if (this.reversed) {
20408
+ sequence = sequence.split('').map(function (cv) {
20409
+ return complement[cv]
20410
+ }).join('');
20411
+ }
20404
20412
 
20405
- let seqOffsetBp = Math.floor(bp - sequenceBpStart);
20413
+ const sequenceBpStart = options.features.bpStart; // genomic position at start of sequence
20414
+ const bpEnd = 1 + options.bpStart + (options.pixelWidth * options.bpPerPixel);
20406
20415
 
20407
- if (seqOffsetBp < sequence.length) {
20408
- let letter = sequence[seqOffsetBp];
20416
+ for (let bp = Math.floor(options.bpStart); bp <= bpEnd; bp++) {
20409
20417
 
20410
- if (this.reversed) {
20411
- letter = complement[letter] || "";
20412
- }
20418
+ const seqIdx = Math.floor(bp - sequenceBpStart);
20413
20419
 
20414
- let offsetBP = bp - options.bpStart;
20415
- let aPixel = offsetBP / options.bpPerPixel;
20416
- let bPixel = (offsetBP + 1) / options.bpPerPixel;
20417
- let color = this.fillColor(letter);
20418
-
20419
- // IGVGraphics.fillRect(ctx, aPixel, 5, bPixel - aPixel, height - 5, { fillStyle: randomRGBConstantAlpha(150, 255, 0.75) });
20420
+ if (seqIdx >= 0 && seqIdx < sequence.length) {
20421
+ const baseLetter = sequence[seqIdx];
20422
+ const offsetBP = bp - options.bpStart;
20423
+ const aPixel = offsetBP / options.bpPerPixel;
20424
+ const pixelWidth = 1 / options.bpPerPixel;
20425
+ const color = this.fillColor(baseLetter);
20420
20426
 
20421
20427
  if (options.bpPerPixel > 1 / 10) {
20422
- IGVGraphics.fillRect(ctx, aPixel, 5, bPixel - aPixel, height - 5, {fillStyle: color});
20428
+ IGVGraphics.fillRect(ctx, aPixel, 5, pixelWidth, SEQUENCE_HEIGHT - 5, {fillStyle: color});
20423
20429
  } else {
20424
- let xPixel = 0.5 * (aPixel + bPixel - ctx.measureText(letter).width);
20425
- IGVGraphics.strokeText(ctx, letter, xPixel, height, {strokeStyle: color});
20430
+ let textPixel = aPixel + 0.5 * (pixelWidth - ctx.measureText(baseLetter).width);
20431
+ IGVGraphics.strokeText(ctx, baseLetter, textPixel, SEQUENCE_HEIGHT, {strokeStyle: color});
20426
20432
  }
20427
20433
  }
20428
20434
  }
20429
20435
 
20430
20436
  if (this.frameTranslate) {
20431
20437
 
20432
- let transSeq;
20433
- if (this.reversed) {
20434
- transSeq = sequence.split('').map(function (cv) {
20435
- return complement[cv]
20436
- });
20437
- transSeq = transSeq.join('');
20438
- } else {
20439
- transSeq = sequence;
20440
- }
20438
+ let y = SEQUENCE_HEIGHT + 2 * FRAME_BORDER;
20439
+ const translatedSequence = this.translateSequence(sequence);
20441
20440
 
20442
- let y = height;
20443
- let translatedSequence = this.translateSequence(transSeq);
20444
- for (let arr of translatedSequence) {
20441
+ for (let fNum = 0; fNum < translatedSequence.length; fNum++) { // == 3, 1 for each frame
20445
20442
 
20446
- let i = translatedSequence.indexOf(arr);
20447
- let fNum = i;
20448
- let h = 25;
20443
+ const aaSequence = translatedSequence[fNum]; // AA sequence for this frame
20449
20444
 
20450
- y = (i === 0) ? y + 10 : y + 30; //Little less room at first.
20445
+ for (let idx = 0; idx < aaSequence.length; idx++) {
20451
20446
 
20452
- for (let cv of arr) {
20453
-
20454
- let aaS;
20455
- let idx = arr.indexOf(cv);
20456
- let xSeed = (idx + fNum) + (2 * idx);
20457
20447
  let color = 0 === idx % 2 ? 'rgb(160,160,160)' : 'rgb(224,224,224)';
20448
+ const cv = aaSequence[idx];
20449
+
20450
+ const bpPos = sequenceBpStart + fNum + (idx * 3);
20451
+ const bpOffset = bpPos - options.bpStart;
20452
+ const p0 = Math.floor(bpOffset / options.bpPerPixel);
20453
+ const p1 = Math.floor((bpOffset + 3) / options.bpPerPixel);
20454
+ const pc = Math.round((p0 + p1) / 2);
20455
+
20456
+ if (p1 < 0) {
20457
+ continue // off left edge
20458
+ } else if (p0 > options.pixelWidth) {
20459
+ break // off right edge
20460
+ }
20458
20461
 
20459
- let p0 = Math.floor(xSeed / options.bpPerPixel);
20460
- let p1 = Math.floor((xSeed + 3) / options.bpPerPixel);
20461
- let pc = Math.round((p0 + p1) / 2);
20462
-
20462
+ let aaLabel = cv.aminoA;
20463
20463
  if (cv.aminoA.indexOf('STOP') > -1) {
20464
20464
  color = 'rgb(255, 0, 0)';
20465
- aaS = 'STOP'; //Color blind accessible
20466
- } else {
20467
- aaS = cv.aminoA;
20468
- }
20469
-
20470
- if (cv.aminoA === 'M') {
20465
+ aaLabel = 'STOP'; //Color blind accessible
20466
+ } else if (cv.aminoA === 'M') {
20471
20467
  color = 'rgb(0, 153, 0)';
20472
- aaS = 'START'; //Color blind accessible
20468
+ aaLabel = 'START'; //Color blind accessible
20473
20469
  }
20474
20470
 
20475
- IGVGraphics.fillRect(ctx, p0, y, p1 - p0, h, {fillStyle: color});
20471
+ IGVGraphics.fillRect(ctx, p0, y, p1 - p0, FRAME_HEIGHT, {fillStyle: color});
20476
20472
 
20477
20473
  if (options.bpPerPixel <= 1 / 10) {
20478
- IGVGraphics.strokeText(ctx, aaS, pc - (ctx.measureText(aaS).width / 2), y + 15);
20474
+ IGVGraphics.strokeText(ctx, aaLabel, pc - (ctx.measureText(aaLabel).width / 2), y + 15);
20479
20475
  }
20480
20476
  }
20477
+ y += (FRAME_HEIGHT + FRAME_BORDER);
20481
20478
  }
20482
20479
  }
20483
20480
  }
@@ -20488,6 +20485,7 @@ class SequenceTrack {
20488
20485
  }
20489
20486
 
20490
20487
  computePixelHeight(ignore) {
20488
+ this.height = this.frameTranslate ? TRANSLATED_HEIGHT : DEFAULT_HEIGHT;
20491
20489
  return this.height
20492
20490
  }
20493
20491
 
@@ -20500,8 +20498,21 @@ class SequenceTrack {
20500
20498
  } else {
20501
20499
  return 'rgb(0, 0, 150)'
20502
20500
  }
20501
+ }
20503
20502
 
20503
+ /**
20504
+ * Return the current state of the track. Used to create sessions and bookmarks.
20505
+ *
20506
+ * @returns {*|{}}
20507
+ */
20508
+ getState() {
20509
+
20510
+ const config = typeof super.getState === 'function' ? super.getState() : {};
20511
+ if (this.reversed) config.revealed = true;
20512
+ if (this.frameTranslate) config.frameTranslate = true;
20513
+ return config
20504
20514
  }
20515
+
20505
20516
  }
20506
20517
 
20507
20518
  /*
@@ -22337,7 +22348,9 @@ class FastaSequence {
22337
22348
 
22338
22349
  async getSequence(chr, start, end) {
22339
22350
 
22340
- if (!(this.interval && this.interval.contains(chr, start, end))) {
22351
+ const hasCachedSquence = this.interval && this.interval.contains(chr, start, end);
22352
+
22353
+ if (!hasCachedSquence) {
22341
22354
 
22342
22355
  // Expand query, to minimum of 50kb
22343
22356
  let qstart = start;
@@ -22796,7 +22809,7 @@ const Cytoband = function (start, end, name, typestain) {
22796
22809
  }
22797
22810
  };
22798
22811
 
22799
- const _version = "2.12.2";
22812
+ const _version = "2.12.3";
22800
22813
  function version() {
22801
22814
  return _version
22802
22815
  }
@@ -23460,6 +23473,17 @@ class TrackViewport extends Viewport {
23460
23473
  }
23461
23474
  }
23462
23475
 
23476
+ repaintDimensions() {
23477
+ const isWGV = GenomeUtils.isWholeGenomeView(this.referenceFrame.chr);
23478
+ const pixelWidth = isWGV ? this.$viewport.width() : 3 * this.$viewport.width();
23479
+ const bpPerPixel = this.referenceFrame.bpPerPixel;
23480
+ const startBP = this.referenceFrame.start - (isWGV ? 0 : pixelWidth / 3 * bpPerPixel);
23481
+ const endBP = this.referenceFrame.end + (isWGV ? 0 : pixelWidth / 3 * bpPerPixel);
23482
+ return {
23483
+ startBP, endBP, pixelWidth
23484
+ }
23485
+ }
23486
+
23463
23487
  /**
23464
23488
  * Repaint the canvas using the cached features
23465
23489
  *
@@ -23474,11 +23498,11 @@ class TrackViewport extends Viewport {
23474
23498
  //this.tile.bpPerPixel = this.referenceFrame.bpPerPixel
23475
23499
 
23476
23500
  // const isWGV = GenomeUtils.isWholeGenomeView(this.browser.referenceFrameList[0].chr)
23477
- const isWGV = GenomeUtils.isWholeGenomeView(this.referenceFrame.chr);
23501
+ GenomeUtils.isWholeGenomeView(this.referenceFrame.chr);
23478
23502
 
23479
23503
  // Canvas dimensions. There is no left-right panning for WGV so canvas width is viewport width.
23480
23504
  // For deep tracks we paint a canvas == 3*viewportHeight centered on the current vertical scroll position
23481
- const pixelWidth = isWGV ? this.$viewport.width() : 3 * this.$viewport.width();
23505
+ const {startBP, endBP, pixelWidth} = this.repaintDimensions();
23482
23506
  const viewportHeight = this.$viewport.height();
23483
23507
  const contentHeight = this.getContentHeight();
23484
23508
  const minHeight = roiFeatures ? Math.max(contentHeight, viewportHeight) : contentHeight; // Need to fill viewport for ROIs.
@@ -23492,8 +23516,8 @@ class TrackViewport extends Viewport {
23492
23516
  const canvasTop = Math.max(0, -(this.$content.position().top) - viewportHeight);
23493
23517
 
23494
23518
  const bpPerPixel = this.referenceFrame.bpPerPixel;
23495
- const startBP = this.referenceFrame.start - (isWGV ? 0 : pixelWidth / 3 * bpPerPixel);
23496
- const endBP = this.referenceFrame.end + (isWGV ? 0 : pixelWidth / 3 * bpPerPixel);
23519
+ //const startBP = this.referenceFrame.start - (isWGV ? 0 : pixelWidth / 3 * bpPerPixel)
23520
+ //const endBP = this.referenceFrame.end + (isWGV ? 0 : pixelWidth / 3 * bpPerPixel)
23497
23521
  const pixelXOffset = Math.round((startBP - this.referenceFrame.start) / bpPerPixel);
23498
23522
 
23499
23523
  const newCanvas = $$1('<canvas class="igv-canvas">').get(0);
@@ -23756,10 +23780,9 @@ class TrackViewport extends Viewport {
23756
23780
  if (!this.featureCache) return true
23757
23781
  const referenceFrame = this.referenceFrame;
23758
23782
  const chr = this.referenceFrame.chr;
23759
- const start = referenceFrame.start;
23760
- const end = start + referenceFrame.toBP($$1(this.contentDiv).width());
23761
23783
  const bpPerPixel = referenceFrame.bpPerPixel;
23762
- return (!this.featureCache.containsRange(chr, start, end, bpPerPixel))
23784
+ const {startBP, endBP} = this.repaintDimensions();
23785
+ return (!this.featureCache.containsRange(chr, startBP, endBP, bpPerPixel))
23763
23786
  }
23764
23787
 
23765
23788
  createZoomInNotice($parent) {