igv 2.11.1 → 2.12.1
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 -23
- package/dist/igv.esm.js +566 -665
- package/dist/igv.esm.min.js +9 -9
- package/dist/igv.esm.min.js.map +1 -1
- package/dist/igv.js +556 -607
- package/dist/igv.min.js +10 -10
- package/dist/igv.min.js.map +1 -1
- package/package.json +2 -2
package/dist/igv.js
CHANGED
|
@@ -19911,7 +19911,7 @@
|
|
|
19911
19911
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19912
19912
|
* THE SOFTWARE.
|
|
19913
19913
|
*/
|
|
19914
|
-
const knownFileExtensions = new Set(["narrowpeak", "broadpeak", "regionpeak", "peaks", "bedgraph", "wig", "gff3", "gff", "gtf", "fusionjuncspan", "refflat", "seg", "aed", "bed", "vcf", "bb", "bigbed", "biginteract", "bw", "bigwig", "bam", "tdf", "refgene", "genepred", "genepredext", "bedpe", "bp", "snp", "rmsk", "cram", "gwas", "maf", "mut"]);
|
|
19914
|
+
const knownFileExtensions = new Set(["narrowpeak", "broadpeak", "regionpeak", "peaks", "bedgraph", "wig", "gff3", "gff", "gtf", "fusionjuncspan", "refflat", "seg", "aed", "bed", "vcf", "bb", "bigbed", "biginteract", "biggenepred", "bignarrowpeak", "bw", "bigwig", "bam", "tdf", "refgene", "genepred", "genepredext", "bedpe", "bp", "snp", "rmsk", "cram", "gwas", "maf", "mut"]);
|
|
19915
19915
|
/**
|
|
19916
19916
|
* Return a custom format object with the given name.
|
|
19917
19917
|
* @param name
|
|
@@ -20032,6 +20032,7 @@
|
|
|
20032
20032
|
|
|
20033
20033
|
case "bedpe":
|
|
20034
20034
|
case "bedpe-loop":
|
|
20035
|
+
case "biginteract":
|
|
20035
20036
|
return "interact";
|
|
20036
20037
|
|
|
20037
20038
|
case "bp":
|
|
@@ -20043,7 +20044,8 @@
|
|
|
20043
20044
|
case "bed":
|
|
20044
20045
|
case "bigbed":
|
|
20045
20046
|
case "bb":
|
|
20046
|
-
case "
|
|
20047
|
+
case "biggenepred":
|
|
20048
|
+
case "bignarrowpeak":
|
|
20047
20049
|
return "bedtype";
|
|
20048
20050
|
|
|
20049
20051
|
default:
|
|
@@ -20287,6 +20289,30 @@
|
|
|
20287
20289
|
return window.location.protocol === "https:" || window.location.hostname === "localhost";
|
|
20288
20290
|
}
|
|
20289
20291
|
|
|
20292
|
+
const pairs = [['A', 'T'], ['G', 'C'], ['Y', 'R'], ['W', 'S'], ['K', 'M'], ['D', 'H'], ['B', 'V']];
|
|
20293
|
+
const complements = new Map();
|
|
20294
|
+
|
|
20295
|
+
for (let p of pairs) {
|
|
20296
|
+
const p1 = p[0];
|
|
20297
|
+
const p2 = p[1];
|
|
20298
|
+
complements.set(p1, p2);
|
|
20299
|
+
complements.set(p2, p1);
|
|
20300
|
+
complements.set(p1.toLowerCase(), p2.toLowerCase());
|
|
20301
|
+
complements.set(p2.toLowerCase(), p1.toLowerCase());
|
|
20302
|
+
}
|
|
20303
|
+
|
|
20304
|
+
function reverseComplementSequence(sequence) {
|
|
20305
|
+
let comp = '';
|
|
20306
|
+
let idx = sequence.length;
|
|
20307
|
+
|
|
20308
|
+
while (idx-- > 0) {
|
|
20309
|
+
const base = sequence[idx];
|
|
20310
|
+
comp += complements.has(base) ? complements.get(base) : base;
|
|
20311
|
+
}
|
|
20312
|
+
|
|
20313
|
+
return comp;
|
|
20314
|
+
}
|
|
20315
|
+
|
|
20290
20316
|
/*
|
|
20291
20317
|
* The MIT License (MIT)
|
|
20292
20318
|
*
|
|
@@ -20440,16 +20466,21 @@
|
|
|
20440
20466
|
const viewport = clickState.viewport;
|
|
20441
20467
|
|
|
20442
20468
|
if (viewport.referenceFrame.bpPerPixel <= 1) {
|
|
20469
|
+
const pixelWidth = viewport.getWidth();
|
|
20470
|
+
const bpWindow = pixelWidth * viewport.referenceFrame.bpPerPixel;
|
|
20471
|
+
const chr = viewport.referenceFrame.chr;
|
|
20472
|
+
const start = Math.floor(viewport.referenceFrame.start);
|
|
20473
|
+
const end = Math.ceil(start + bpWindow);
|
|
20443
20474
|
const items = [{
|
|
20444
|
-
label: 'View visible sequence...',
|
|
20475
|
+
label: this.reversed ? 'View visible sequence (reversed)...' : 'View visible sequence...',
|
|
20445
20476
|
click: async () => {
|
|
20446
|
-
|
|
20447
|
-
|
|
20448
|
-
|
|
20449
|
-
|
|
20450
|
-
|
|
20451
|
-
|
|
20452
|
-
Alert.presentAlert(
|
|
20477
|
+
let seq = await this.browser.genome.sequence.getSequence(chr, start, end);
|
|
20478
|
+
|
|
20479
|
+
if (this.reversed) {
|
|
20480
|
+
seq = reverseComplementSequence(seq);
|
|
20481
|
+
}
|
|
20482
|
+
|
|
20483
|
+
Alert.presentAlert(seq);
|
|
20453
20484
|
}
|
|
20454
20485
|
}];
|
|
20455
20486
|
|
|
@@ -20457,13 +20488,18 @@
|
|
|
20457
20488
|
items.push({
|
|
20458
20489
|
label: 'Copy visible sequence',
|
|
20459
20490
|
click: async () => {
|
|
20460
|
-
|
|
20461
|
-
|
|
20462
|
-
|
|
20463
|
-
|
|
20464
|
-
|
|
20465
|
-
|
|
20466
|
-
|
|
20491
|
+
let seq = await this.browser.genome.sequence.getSequence(chr, start, end);
|
|
20492
|
+
|
|
20493
|
+
if (this.reversed) {
|
|
20494
|
+
seq = reverseComplementSequence(seq);
|
|
20495
|
+
}
|
|
20496
|
+
|
|
20497
|
+
try {
|
|
20498
|
+
await navigator.clipboard.writeText(seq);
|
|
20499
|
+
} catch (e) {
|
|
20500
|
+
console.error(e);
|
|
20501
|
+
Alert.presentAlert(`error copying sequence to clipboard ${e}`);
|
|
20502
|
+
}
|
|
20467
20503
|
}
|
|
20468
20504
|
});
|
|
20469
20505
|
}
|
|
@@ -20604,7 +20640,7 @@
|
|
|
20604
20640
|
}
|
|
20605
20641
|
}
|
|
20606
20642
|
|
|
20607
|
-
supportsWholeGenome() {
|
|
20643
|
+
get supportsWholeGenome() {
|
|
20608
20644
|
return false;
|
|
20609
20645
|
}
|
|
20610
20646
|
|
|
@@ -20672,12 +20708,13 @@
|
|
|
20672
20708
|
});
|
|
20673
20709
|
this.$viewport.append(this.$content);
|
|
20674
20710
|
this.$content.height(this.$viewport.height());
|
|
20675
|
-
this.contentDiv = this.$content.get(0);
|
|
20676
|
-
this.$
|
|
20677
|
-
|
|
20678
|
-
this.canvas = this.$canvas.get(0)
|
|
20679
|
-
this.ctx = this.canvas.getContext("2d")
|
|
20680
|
-
|
|
20711
|
+
this.contentDiv = this.$content.get(0); // this.$canvas = $('<canvas>')
|
|
20712
|
+
// this.$content.append(this.$canvas)
|
|
20713
|
+
//
|
|
20714
|
+
// this.canvas = this.$canvas.get(0)
|
|
20715
|
+
// this.ctx = this.canvas.getContext("2d")
|
|
20716
|
+
|
|
20717
|
+
this.$viewport.width(width);
|
|
20681
20718
|
this.initializationHelper();
|
|
20682
20719
|
}
|
|
20683
20720
|
|
|
@@ -20759,7 +20796,6 @@
|
|
|
20759
20796
|
// Maximum height of a canvas is ~32,000 pixels on Chrome, possibly smaller on other platforms
|
|
20760
20797
|
contentHeight = Math.min(contentHeight, 32000);
|
|
20761
20798
|
this.$content.height(contentHeight);
|
|
20762
|
-
if (this.canvas._data) this.canvas._data.invalidate = true;
|
|
20763
20799
|
}
|
|
20764
20800
|
|
|
20765
20801
|
isLoading() {
|
|
@@ -20801,7 +20837,6 @@
|
|
|
20801
20837
|
this.popover.dispose();
|
|
20802
20838
|
}
|
|
20803
20839
|
|
|
20804
|
-
this.removeMouseHandlers();
|
|
20805
20840
|
this.$viewport.get(0).remove(); // Null out all properties -- this should not be neccessary, but just in case there is a
|
|
20806
20841
|
// reference to self somewhere we want to free memory.
|
|
20807
20842
|
|
|
@@ -23058,7 +23093,7 @@
|
|
|
23058
23093
|
}
|
|
23059
23094
|
};
|
|
23060
23095
|
|
|
23061
|
-
const _version = "2.
|
|
23096
|
+
const _version = "2.12.1";
|
|
23062
23097
|
|
|
23063
23098
|
function version$1() {
|
|
23064
23099
|
return _version;
|
|
@@ -23201,7 +23236,7 @@
|
|
|
23201
23236
|
class Genome {
|
|
23202
23237
|
constructor(config, sequence, ideograms, aliases) {
|
|
23203
23238
|
this.config = config;
|
|
23204
|
-
this.id = config.id;
|
|
23239
|
+
this.id = config.id || generateGenomeID(config);
|
|
23205
23240
|
this.sequence = sequence;
|
|
23206
23241
|
this.chromosomeNames = sequence.chromosomeNames;
|
|
23207
23242
|
this.chromosomes = sequence.chromosomes; // An object (functions as a dictionary)
|
|
@@ -23408,6 +23443,7 @@
|
|
|
23408
23443
|
}
|
|
23409
23444
|
|
|
23410
23445
|
async getSequence(chr, start, end) {
|
|
23446
|
+
chr = this.getChromosomeName(chr);
|
|
23411
23447
|
return this.sequence.getSequence(chr, start, end);
|
|
23412
23448
|
}
|
|
23413
23449
|
|
|
@@ -23516,6 +23552,18 @@
|
|
|
23516
23552
|
}
|
|
23517
23553
|
}
|
|
23518
23554
|
|
|
23555
|
+
function generateGenomeID(config) {
|
|
23556
|
+
if (config.id !== undefined) {
|
|
23557
|
+
return config.id;
|
|
23558
|
+
} else if (config.fastaURL && isString$3(config.fastaURL)) {
|
|
23559
|
+
return config.fastaURL;
|
|
23560
|
+
} else if (config.fastaURL && config.fastaURL.name) {
|
|
23561
|
+
return config.fastaURL.name;
|
|
23562
|
+
} else {
|
|
23563
|
+
return ("0000" + (Math.random() * Math.pow(36, 4) << 0).toString(36)).slice(-4);
|
|
23564
|
+
}
|
|
23565
|
+
}
|
|
23566
|
+
|
|
23519
23567
|
/**
|
|
23520
23568
|
* Created by dat on 9/16/16.
|
|
23521
23569
|
*/
|
|
@@ -23534,15 +23582,13 @@
|
|
|
23534
23582
|
});
|
|
23535
23583
|
this.$viewport.append(this.$spinner);
|
|
23536
23584
|
this.$spinner.append($$1('<div>'));
|
|
23537
|
-
const
|
|
23538
|
-
track
|
|
23539
|
-
} = this.trackView;
|
|
23585
|
+
const track = this.trackView.track;
|
|
23540
23586
|
|
|
23541
23587
|
if ('sequence' !== track.type) {
|
|
23542
23588
|
this.$zoomInNotice = this.createZoomInNotice(this.$content);
|
|
23543
23589
|
}
|
|
23544
23590
|
|
|
23545
|
-
if (track.name && "sequence" !== track.
|
|
23591
|
+
if (track.name && "sequence" !== track.id) {
|
|
23546
23592
|
this.$trackLabel = $$1('<div class="igv-track-label">');
|
|
23547
23593
|
this.$viewport.append(this.$trackLabel);
|
|
23548
23594
|
this.setTrackLabel(track.name);
|
|
@@ -23556,6 +23602,11 @@
|
|
|
23556
23602
|
this.addMouseHandlers();
|
|
23557
23603
|
}
|
|
23558
23604
|
|
|
23605
|
+
setContentHeight(contentHeight) {
|
|
23606
|
+
super.setContentHeight(contentHeight);
|
|
23607
|
+
if (this.featureCache) this.featureCache.redraw = true;
|
|
23608
|
+
}
|
|
23609
|
+
|
|
23559
23610
|
setTrackLabel(label) {
|
|
23560
23611
|
this.$trackLabel.empty();
|
|
23561
23612
|
this.$trackLabel.html(label);
|
|
@@ -23572,10 +23623,18 @@
|
|
|
23572
23623
|
this.$spinner.hide();
|
|
23573
23624
|
}
|
|
23574
23625
|
}
|
|
23626
|
+
/**
|
|
23627
|
+
* Test to determine if we are zoomed in far enough to see features. Applicable to tracks with visibility windows.
|
|
23628
|
+
*
|
|
23629
|
+
* As a side effect the viewports canvas is removed if zoomed out.
|
|
23630
|
+
*
|
|
23631
|
+
* @returns {boolean} true if we are zoomed in past visibility window, false otherwise
|
|
23632
|
+
*/
|
|
23633
|
+
|
|
23575
23634
|
|
|
23576
23635
|
checkZoomIn() {
|
|
23577
|
-
const
|
|
23578
|
-
if (this.referenceFrame.chr.toLowerCase() === "all" && !this.trackView.track.supportsWholeGenome
|
|
23636
|
+
const zoomedOutOfWindow = () => {
|
|
23637
|
+
if (this.referenceFrame.chr.toLowerCase() === "all" && !this.trackView.track.supportsWholeGenome) {
|
|
23579
23638
|
return true;
|
|
23580
23639
|
} else {
|
|
23581
23640
|
const visibilityWindow = this.trackView.track.visibilityWindow;
|
|
@@ -23584,7 +23643,8 @@
|
|
|
23584
23643
|
};
|
|
23585
23644
|
|
|
23586
23645
|
if (this.trackView.track && "sequence" === this.trackView.track.type && this.referenceFrame.bpPerPixel > 1) {
|
|
23587
|
-
|
|
23646
|
+
$$1(this.canvas).remove();
|
|
23647
|
+
this.canvas = undefined; //this.featureCache = undefined
|
|
23588
23648
|
|
|
23589
23649
|
return false;
|
|
23590
23650
|
}
|
|
@@ -23593,30 +23653,30 @@
|
|
|
23593
23653
|
return false;
|
|
23594
23654
|
}
|
|
23595
23655
|
|
|
23596
|
-
if (
|
|
23597
|
-
|
|
23598
|
-
|
|
23599
|
-
|
|
23600
|
-
|
|
23601
|
-
|
|
23602
|
-
this.featureCache = undefined;
|
|
23603
|
-
}
|
|
23656
|
+
if (zoomedOutOfWindow()) {
|
|
23657
|
+
// Out of visibility window
|
|
23658
|
+
if (this.canvas) {
|
|
23659
|
+
$$1(this.canvas).remove();
|
|
23660
|
+
this.canvas = undefined; //this.featureCache = undefined
|
|
23661
|
+
}
|
|
23604
23662
|
|
|
23605
|
-
|
|
23663
|
+
if (this.trackView.track.autoHeight) {
|
|
23664
|
+
const minHeight = this.trackView.minHeight || 0;
|
|
23665
|
+
this.setContentHeight(minHeight);
|
|
23666
|
+
}
|
|
23606
23667
|
|
|
23607
|
-
|
|
23608
|
-
|
|
23609
|
-
|
|
23610
|
-
}
|
|
23668
|
+
if (this.$zoomInNotice) {
|
|
23669
|
+
this.$zoomInNotice.show();
|
|
23670
|
+
}
|
|
23611
23671
|
|
|
23612
|
-
|
|
23613
|
-
|
|
23672
|
+
return false;
|
|
23673
|
+
} else {
|
|
23674
|
+
if (this.$zoomInNotice) {
|
|
23614
23675
|
this.$zoomInNotice.hide();
|
|
23615
|
-
return true;
|
|
23616
23676
|
}
|
|
23617
|
-
}
|
|
23618
23677
|
|
|
23619
|
-
|
|
23678
|
+
return true;
|
|
23679
|
+
}
|
|
23620
23680
|
}
|
|
23621
23681
|
/**
|
|
23622
23682
|
* Adjust the canvas to the current genomic state.
|
|
@@ -23689,9 +23749,8 @@
|
|
|
23689
23749
|
}
|
|
23690
23750
|
}
|
|
23691
23751
|
/**
|
|
23692
|
-
* Repaint the canvas
|
|
23752
|
+
* Repaint the canvas using the cached features
|
|
23693
23753
|
*
|
|
23694
|
-
* @returns {Promise<void>}
|
|
23695
23754
|
*/
|
|
23696
23755
|
|
|
23697
23756
|
|
|
@@ -23706,24 +23765,15 @@
|
|
|
23706
23765
|
} = this.featureCache; //this.tile.bpPerPixel = this.referenceFrame.bpPerPixel
|
|
23707
23766
|
// const isWGV = GenomeUtils.isWholeGenomeView(this.browser.referenceFrameList[0].chr)
|
|
23708
23767
|
|
|
23709
|
-
const isWGV = GenomeUtils.isWholeGenomeView(this.referenceFrame.chr);
|
|
23710
|
-
|
|
23711
|
-
const startBP = this.featureCache.startBP;
|
|
23712
|
-
const endBP = this.featureCache.endBP;
|
|
23713
|
-
let bpPerPixel = this.referenceFrame.bpPerPixel;
|
|
23714
|
-
|
|
23715
|
-
if (isWGV) {
|
|
23716
|
-
pixelWidth = this.$viewport.width();
|
|
23717
|
-
} else {
|
|
23718
|
-
pixelWidth = 3 * this.$viewport.width();
|
|
23719
|
-
} // For deep tracks we paint a canvas == 3*viewportHeight centered on the current vertical scroll position
|
|
23720
|
-
|
|
23768
|
+
const isWGV = GenomeUtils.isWholeGenomeView(this.referenceFrame.chr); // Canvas dimensions. There is no left-right panning for WGV so canvas width is viewport width.
|
|
23769
|
+
// For deep tracks we paint a canvas == 3*viewportHeight centered on the current vertical scroll position
|
|
23721
23770
|
|
|
23771
|
+
const pixelWidth = isWGV ? this.$viewport.width() : 3 * this.$viewport.width();
|
|
23722
23772
|
const viewportHeight = this.$viewport.height();
|
|
23723
23773
|
const contentHeight = this.getContentHeight();
|
|
23724
23774
|
const minHeight = roiFeatures ? Math.max(contentHeight, viewportHeight) : contentHeight; // Need to fill viewport for ROIs.
|
|
23725
23775
|
|
|
23726
|
-
|
|
23776
|
+
const pixelHeight = Math.min(minHeight, 3 * viewportHeight);
|
|
23727
23777
|
|
|
23728
23778
|
if (0 === pixelWidth || 0 === pixelHeight) {
|
|
23729
23779
|
if (this.canvas) {
|
|
@@ -23733,26 +23783,22 @@
|
|
|
23733
23783
|
return;
|
|
23734
23784
|
}
|
|
23735
23785
|
|
|
23736
|
-
const canvasTop = Math.max(0, -this.$content.position().top - viewportHeight);
|
|
23737
|
-
|
|
23738
|
-
|
|
23739
|
-
|
|
23740
|
-
|
|
23741
|
-
devicePixelRatio = window.devicePixelRatio;
|
|
23742
|
-
} else {
|
|
23743
|
-
devicePixelRatio = this.trackView.track.supportHiDPI === false ? 1 : window.devicePixelRatio;
|
|
23744
|
-
}
|
|
23745
|
-
|
|
23746
|
-
const pixelXOffset = Math.round((startBP - this.referenceFrame.start) / this.referenceFrame.bpPerPixel);
|
|
23786
|
+
const canvasTop = Math.max(0, -this.$content.position().top - viewportHeight);
|
|
23787
|
+
const bpPerPixel = this.referenceFrame.bpPerPixel;
|
|
23788
|
+
const startBP = this.referenceFrame.start - (isWGV ? 0 : pixelWidth / 3 * bpPerPixel);
|
|
23789
|
+
const endBP = this.referenceFrame.end + (isWGV ? 0 : pixelWidth / 3 * bpPerPixel);
|
|
23790
|
+
const pixelXOffset = Math.round((startBP - this.referenceFrame.start) / bpPerPixel);
|
|
23747
23791
|
const newCanvas = $$1('<canvas class="igv-canvas">').get(0);
|
|
23748
|
-
const ctx = newCanvas.getContext("2d");
|
|
23749
23792
|
newCanvas.style.width = pixelWidth + "px";
|
|
23750
23793
|
newCanvas.style.height = pixelHeight + "px";
|
|
23794
|
+
newCanvas.style.left = pixelXOffset + "px";
|
|
23795
|
+
newCanvas.style.top = canvasTop + "px"; // Always use high DPI if in "FILL" display mode, otherwise use track setting;
|
|
23796
|
+
|
|
23797
|
+
const devicePixelRatio = "FILL" === this.trackView.track.displayMode || this.trackView.track.supportHiDPI !== false ? window.devicePixelRatio : 1;
|
|
23751
23798
|
newCanvas.width = devicePixelRatio * pixelWidth;
|
|
23752
23799
|
newCanvas.height = devicePixelRatio * pixelHeight;
|
|
23800
|
+
const ctx = newCanvas.getContext("2d");
|
|
23753
23801
|
ctx.scale(devicePixelRatio, devicePixelRatio);
|
|
23754
|
-
newCanvas.style.left = pixelXOffset + "px";
|
|
23755
|
-
newCanvas.style.top = canvasTop + "px";
|
|
23756
23802
|
ctx.translate(0, -canvasTop);
|
|
23757
23803
|
const drawConfiguration = {
|
|
23758
23804
|
context: ctx,
|
|
@@ -23768,23 +23814,23 @@
|
|
|
23768
23814
|
viewport: this,
|
|
23769
23815
|
viewportWidth: this.$viewport.width()
|
|
23770
23816
|
};
|
|
23771
|
-
this.draw(drawConfiguration, features, roiFeatures);
|
|
23772
|
-
|
|
23773
|
-
|
|
23774
|
-
chr: this.referenceFrame.chr,
|
|
23775
|
-
startBP,
|
|
23776
|
-
endBP,
|
|
23777
|
-
bpPerPixel,
|
|
23778
|
-
top: canvasTop,
|
|
23779
|
-
bottom: canvasTop + pixelHeight
|
|
23780
|
-
};
|
|
23817
|
+
this.draw(drawConfiguration, features, roiFeatures);
|
|
23818
|
+
this.featureCache.canvasTop = canvasTop;
|
|
23819
|
+
this.featureCache.height = pixelHeight;
|
|
23781
23820
|
|
|
23782
23821
|
if (this.canvas) {
|
|
23783
23822
|
$$1(this.canvas).remove();
|
|
23784
23823
|
}
|
|
23785
23824
|
|
|
23825
|
+
newCanvas._data = {
|
|
23826
|
+
chr: this.featureCache.chr,
|
|
23827
|
+
bpPerPixel,
|
|
23828
|
+
startBP,
|
|
23829
|
+
endBP,
|
|
23830
|
+
pixelHeight,
|
|
23831
|
+
pixelTop: canvasTop
|
|
23832
|
+
};
|
|
23786
23833
|
this.canvas = newCanvas;
|
|
23787
|
-
this.ctx = ctx;
|
|
23788
23834
|
this.$content.append($$1(newCanvas));
|
|
23789
23835
|
}
|
|
23790
23836
|
/**
|
|
@@ -23824,15 +23870,16 @@
|
|
|
23824
23870
|
}
|
|
23825
23871
|
|
|
23826
23872
|
savePNG() {
|
|
23827
|
-
if (!this.
|
|
23828
|
-
const canvasMetadata = this.
|
|
23829
|
-
const canvasTop = canvasMetadata ? canvasMetadata.
|
|
23873
|
+
if (!this.canvas) return;
|
|
23874
|
+
const canvasMetadata = this.featureCache;
|
|
23875
|
+
const canvasTop = canvasMetadata ? canvasMetadata.canvasTop : 0;
|
|
23830
23876
|
const devicePixelRatio = window.devicePixelRatio;
|
|
23831
23877
|
const w = this.$viewport.width() * devicePixelRatio;
|
|
23832
23878
|
const h = this.$viewport.height() * devicePixelRatio;
|
|
23833
23879
|
const x = -$$1(this.canvas).position().left * devicePixelRatio;
|
|
23834
23880
|
const y = (-this.$content.position().top - canvasTop) * devicePixelRatio;
|
|
23835
|
-
const
|
|
23881
|
+
const ctx = this.canvas.getContext("2d");
|
|
23882
|
+
const imageData = ctx.getImageData(x, y, w, h);
|
|
23836
23883
|
const exportCanvas = document.createElement('canvas');
|
|
23837
23884
|
const exportCtx = exportCanvas.getContext('2d');
|
|
23838
23885
|
exportCanvas.width = imageData.width;
|
|
@@ -23970,6 +24017,22 @@
|
|
|
23970
24017
|
}
|
|
23971
24018
|
}
|
|
23972
24019
|
|
|
24020
|
+
needsRepaint() {
|
|
24021
|
+
if (!this.canvas) return true;
|
|
24022
|
+
const data = this.canvas._data;
|
|
24023
|
+
return !data || this.referenceFrame.start < data.startBP || this.referenceFrame.end > data.endBP || this.referenceFrame.chr !== data.chr || this.referenceFrame.bpPerPixel != data.bpPerPixel;
|
|
24024
|
+
}
|
|
24025
|
+
|
|
24026
|
+
needsReload() {
|
|
24027
|
+
if (!this.featureCache) return true;
|
|
24028
|
+
const referenceFrame = this.referenceFrame;
|
|
24029
|
+
const chr = this.referenceFrame.chr;
|
|
24030
|
+
const start = referenceFrame.start;
|
|
24031
|
+
const end = start + referenceFrame.toBP($$1(this.contentDiv).width());
|
|
24032
|
+
const bpPerPixel = referenceFrame.bpPerPixel;
|
|
24033
|
+
return !this.featureCache.containsRange(chr, start, end, bpPerPixel);
|
|
24034
|
+
}
|
|
24035
|
+
|
|
23973
24036
|
createZoomInNotice($parent) {
|
|
23974
24037
|
const $container = $$1('<div>', {
|
|
23975
24038
|
class: 'igv-zoom-in-notice-container'
|
|
@@ -23987,36 +24050,42 @@
|
|
|
23987
24050
|
}
|
|
23988
24051
|
|
|
23989
24052
|
addMouseHandlers() {
|
|
23990
|
-
this
|
|
23991
|
-
this.
|
|
23992
|
-
this.addViewportTouchStartHandler(this.$viewport.get(0));
|
|
23993
|
-
this.addViewportMouseUpHandler(this.$viewport.get(0));
|
|
23994
|
-
this.addViewportTouchEndHandler(this.$viewport.get(0));
|
|
23995
|
-
this.addViewportClickHandler(this.$viewport.get(0));
|
|
24053
|
+
const viewport = this.$viewport.get(0);
|
|
24054
|
+
this.addViewportContextMenuHandler(viewport);
|
|
23996
24055
|
|
|
23997
|
-
|
|
23998
|
-
this.
|
|
23999
|
-
|
|
24000
|
-
|
|
24056
|
+
const md = event => {
|
|
24057
|
+
this.enableClick = true;
|
|
24058
|
+
this.browser.mouseDownOnViewport(event, this);
|
|
24059
|
+
pageCoordinates$1(event);
|
|
24060
|
+
};
|
|
24001
24061
|
|
|
24002
|
-
|
|
24003
|
-
|
|
24004
|
-
|
|
24005
|
-
|
|
24006
|
-
|
|
24007
|
-
|
|
24008
|
-
|
|
24062
|
+
viewport.addEventListener('mousedown', md);
|
|
24063
|
+
viewport.addEventListener('touchstart', md);
|
|
24064
|
+
|
|
24065
|
+
const mu = event => {
|
|
24066
|
+
// Any mouse up cancels drag and scrolling
|
|
24067
|
+
if (this.browser.dragObject || this.browser.isScrolling) {
|
|
24068
|
+
this.browser.cancelTrackPan(); // event.preventDefault();
|
|
24069
|
+
// event.stopPropagation();
|
|
24070
|
+
|
|
24071
|
+
this.enableClick = false; // Until next mouse down
|
|
24072
|
+
} else {
|
|
24073
|
+
this.browser.cancelTrackPan();
|
|
24074
|
+
this.browser.endTrackDrag();
|
|
24075
|
+
}
|
|
24076
|
+
};
|
|
24077
|
+
|
|
24078
|
+
viewport.addEventListener('mouseup', mu);
|
|
24079
|
+
viewport.addEventListener('touchend', mu);
|
|
24080
|
+
this.addViewportClickHandler(this.$viewport.get(0));
|
|
24009
24081
|
|
|
24010
24082
|
if (this.trackView.track.name && "sequence" !== this.trackView.track.config.type) {
|
|
24011
|
-
this.
|
|
24083
|
+
this.addTrackLabelClickHandler(this.$trackLabel.get(0));
|
|
24012
24084
|
}
|
|
24013
24085
|
}
|
|
24014
24086
|
|
|
24015
24087
|
addViewportContextMenuHandler(viewport) {
|
|
24016
|
-
|
|
24017
|
-
viewport.addEventListener('contextmenu', this.boundContextMenuHandler);
|
|
24018
|
-
|
|
24019
|
-
function contextMenuHandler(event) {
|
|
24088
|
+
viewport.addEventListener('contextmenu', event => {
|
|
24020
24089
|
// Ignore if we are doing a drag. This can happen with touch events.
|
|
24021
24090
|
if (this.browser.dragObject) {
|
|
24022
24091
|
return false;
|
|
@@ -24056,55 +24125,12 @@
|
|
|
24056
24125
|
click: () => this.saveSVG()
|
|
24057
24126
|
});
|
|
24058
24127
|
this.browser.menuPopup.presentTrackContextMenu(event, menuItems);
|
|
24059
|
-
}
|
|
24060
|
-
}
|
|
24061
|
-
|
|
24062
|
-
removeViewportContextMenuHandler(viewport) {
|
|
24063
|
-
viewport.removeEventListener('contextmenu', this.boundContextMenuHandler);
|
|
24064
|
-
}
|
|
24065
|
-
|
|
24066
|
-
addViewportMouseDownHandler(viewport) {
|
|
24067
|
-
this.boundMouseDownHandler = mouseDownHandler.bind(this);
|
|
24068
|
-
viewport.addEventListener('mousedown', this.boundMouseDownHandler);
|
|
24069
|
-
}
|
|
24070
|
-
|
|
24071
|
-
removeViewportMouseDownHandler(viewport) {
|
|
24072
|
-
viewport.removeEventListener('mousedown', this.boundMouseDownHandler);
|
|
24073
|
-
}
|
|
24074
|
-
|
|
24075
|
-
addViewportTouchStartHandler(viewport) {
|
|
24076
|
-
this.boundTouchStartHandler = mouseDownHandler.bind(this);
|
|
24077
|
-
viewport.addEventListener('touchstart', this.boundTouchStartHandler);
|
|
24078
|
-
}
|
|
24079
|
-
|
|
24080
|
-
removeViewportTouchStartHandler(viewport) {
|
|
24081
|
-
viewport.removeEventListener('touchstart', this.boundTouchStartHandler);
|
|
24082
|
-
}
|
|
24083
|
-
|
|
24084
|
-
addViewportMouseUpHandler(viewport) {
|
|
24085
|
-
this.boundMouseUpHandler = mouseUpHandler.bind(this);
|
|
24086
|
-
viewport.addEventListener('mouseup', this.boundMouseUpHandler);
|
|
24087
|
-
}
|
|
24088
|
-
|
|
24089
|
-
removeViewportMouseUpHandler(viewport) {
|
|
24090
|
-
viewport.removeEventListener('mouseup', this.boundMouseUpHandler);
|
|
24091
|
-
}
|
|
24092
|
-
|
|
24093
|
-
addViewportTouchEndHandler(viewport) {
|
|
24094
|
-
this.boundTouchEndHandler = mouseUpHandler.bind(this);
|
|
24095
|
-
viewport.addEventListener('touchend', this.boundTouchEndHandler);
|
|
24096
|
-
}
|
|
24097
|
-
|
|
24098
|
-
removeViewportTouchEndHandler(viewport) {
|
|
24099
|
-
viewport.removeEventListener('touchend', this.boundTouchEndHandler);
|
|
24128
|
+
});
|
|
24100
24129
|
}
|
|
24101
24130
|
|
|
24102
24131
|
addViewportClickHandler(viewport) {
|
|
24103
|
-
|
|
24104
|
-
|
|
24105
|
-
|
|
24106
|
-
function clickHandler(event) {
|
|
24107
|
-
if (this.enableClick) {
|
|
24132
|
+
viewport.addEventListener('click', event => {
|
|
24133
|
+
if (this.enableClick && this.canvas) {
|
|
24108
24134
|
if (3 === event.which || event.ctrlKey) {
|
|
24109
24135
|
return;
|
|
24110
24136
|
} // Close any currently open popups
|
|
@@ -24178,18 +24204,11 @@
|
|
|
24178
24204
|
|
|
24179
24205
|
lastClickTime = time;
|
|
24180
24206
|
}
|
|
24181
|
-
}
|
|
24182
|
-
}
|
|
24183
|
-
|
|
24184
|
-
removeViewportClickHandler(viewport) {
|
|
24185
|
-
viewport.removeEventListener('click', this.boundClickHandler);
|
|
24207
|
+
});
|
|
24186
24208
|
}
|
|
24187
24209
|
|
|
24188
24210
|
addTrackLabelClickHandler(trackLabel) {
|
|
24189
|
-
|
|
24190
|
-
trackLabel.addEventListener('click', this.boundTrackLabelClickHandler);
|
|
24191
|
-
|
|
24192
|
-
function clickHandler(event) {
|
|
24211
|
+
trackLabel.addEventListener('click', event => {
|
|
24193
24212
|
event.stopPropagation();
|
|
24194
24213
|
const {
|
|
24195
24214
|
track
|
|
@@ -24210,34 +24229,11 @@
|
|
|
24210
24229
|
this.popover = new Popover(this.browser.columnContainer, track.name || '');
|
|
24211
24230
|
this.popover.presentContentWithEvent(event, str);
|
|
24212
24231
|
}
|
|
24213
|
-
}
|
|
24214
|
-
}
|
|
24215
|
-
|
|
24216
|
-
removeTrackLabelClickHandler(trackLabel) {
|
|
24217
|
-
trackLabel.removeEventListener('click', this.boundTrackLabelClickHandler);
|
|
24232
|
+
});
|
|
24218
24233
|
}
|
|
24219
24234
|
|
|
24220
24235
|
}
|
|
24221
24236
|
|
|
24222
|
-
function mouseDownHandler(event) {
|
|
24223
|
-
this.enableClick = true;
|
|
24224
|
-
this.browser.mouseDownOnViewport(event, this);
|
|
24225
|
-
pageCoordinates$1(event);
|
|
24226
|
-
}
|
|
24227
|
-
|
|
24228
|
-
function mouseUpHandler(event) {
|
|
24229
|
-
// Any mouse up cancels drag and scrolling
|
|
24230
|
-
if (this.browser.dragObject || this.browser.isScrolling) {
|
|
24231
|
-
this.browser.cancelTrackPan(); // event.preventDefault();
|
|
24232
|
-
// event.stopPropagation();
|
|
24233
|
-
|
|
24234
|
-
this.enableClick = false; // Until next mouse down
|
|
24235
|
-
} else {
|
|
24236
|
-
this.browser.cancelTrackPan();
|
|
24237
|
-
this.browser.endTrackDrag();
|
|
24238
|
-
}
|
|
24239
|
-
}
|
|
24240
|
-
|
|
24241
24237
|
function createClickState(event, viewport) {
|
|
24242
24238
|
const referenceFrame = viewport.referenceFrame;
|
|
24243
24239
|
const viewportCoords = translateMouseCoordinates$1(event, viewport.contentDiv);
|
|
@@ -24456,10 +24452,12 @@
|
|
|
24456
24452
|
end: bp(this.rulerViewport.referenceFrame, left + width)
|
|
24457
24453
|
};
|
|
24458
24454
|
validateLocusExtent(this.rulerViewport.browser.genome.getChromosome(this.rulerViewport.referenceFrame.chr).bpLength, extent, this.rulerViewport.browser.minimumBases());
|
|
24459
|
-
|
|
24460
|
-
|
|
24461
|
-
this.rulerViewport.referenceFrame.
|
|
24462
|
-
this.rulerViewport.
|
|
24455
|
+
const newStart = Math.round(extent.start);
|
|
24456
|
+
const newEnd = Math.round(extent.end);
|
|
24457
|
+
this.rulerViewport.referenceFrame.bpPerPixel = (newEnd - newStart) / this.rulerViewport.contentDiv.clientWidth;
|
|
24458
|
+
this.rulerViewport.referenceFrame.start = newStart;
|
|
24459
|
+
this.rulerViewport.referenceFrame.end = newEnd;
|
|
24460
|
+
this.rulerViewport.browser.updateViews();
|
|
24463
24461
|
}
|
|
24464
24462
|
}
|
|
24465
24463
|
}
|
|
@@ -25469,7 +25467,7 @@
|
|
|
25469
25467
|
return this.firstAlignment.isProperPair();
|
|
25470
25468
|
}
|
|
25471
25469
|
|
|
25472
|
-
get
|
|
25470
|
+
get fragmentLength() {
|
|
25473
25471
|
return Math.abs(this.firstAlignment.fragmentLength);
|
|
25474
25472
|
}
|
|
25475
25473
|
|
|
@@ -26958,7 +26956,7 @@
|
|
|
26958
26956
|
const lseq = readInt(ba, offset + 20);
|
|
26959
26957
|
const mateChrIdx = readInt(ba, offset + 24);
|
|
26960
26958
|
const matePos = readInt(ba, offset + 28);
|
|
26961
|
-
const
|
|
26959
|
+
const fragmentLength = readInt(ba, offset + 32);
|
|
26962
26960
|
let readName = [];
|
|
26963
26961
|
|
|
26964
26962
|
for (let j = 0; j < nl - 1; ++j) {
|
|
@@ -26999,7 +26997,7 @@
|
|
|
26999
26997
|
alignment.readName = readName;
|
|
27000
26998
|
alignment.cigar = cigar;
|
|
27001
26999
|
alignment.lengthOnRef = lengthOnRef;
|
|
27002
|
-
alignment.fragmentLength =
|
|
27000
|
+
alignment.fragmentLength = fragmentLength;
|
|
27003
27001
|
alignment.mq = mq;
|
|
27004
27002
|
BamUtils.bam_tag2cigar(ba, blockEnd, p, lseq, alignment, cigarArray);
|
|
27005
27003
|
alignment.end = alignment.start + alignment.lengthOnRef;
|
|
@@ -45433,6 +45431,10 @@
|
|
|
45433
45431
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
45434
45432
|
* THE SOFTWARE.
|
|
45435
45433
|
*/
|
|
45434
|
+
|
|
45435
|
+
const fixColor = colorString => {
|
|
45436
|
+
return colorString.indexOf(",") > 0 && !colorString.startsWith("rgb") ? `rgb(${colorString})` : colorString;
|
|
45437
|
+
};
|
|
45436
45438
|
/**
|
|
45437
45439
|
* A collection of properties and methods shared by all (or most) track types.
|
|
45438
45440
|
*
|
|
@@ -45441,6 +45443,7 @@
|
|
|
45441
45443
|
* @constructor
|
|
45442
45444
|
*/
|
|
45443
45445
|
|
|
45446
|
+
|
|
45444
45447
|
class TrackBase {
|
|
45445
45448
|
constructor(config, browser) {
|
|
45446
45449
|
this.browser = browser;
|
|
@@ -45474,8 +45477,8 @@
|
|
|
45474
45477
|
|
|
45475
45478
|
this.id = this.config.id === undefined ? this.name : this.config.id;
|
|
45476
45479
|
this.order = config.order;
|
|
45477
|
-
this.color = config.color;
|
|
45478
|
-
this.altColor = config.altColor;
|
|
45480
|
+
if (config.color) this.color = fixColor(config.color);
|
|
45481
|
+
if (config.altColor) this.altColor = fixColor(config.altColor);
|
|
45479
45482
|
|
|
45480
45483
|
if ("civic-ws" === config.sourceType) {
|
|
45481
45484
|
// Ugly proxy for specialized track type
|
|
@@ -45588,7 +45591,7 @@
|
|
|
45588
45591
|
return state;
|
|
45589
45592
|
}
|
|
45590
45593
|
|
|
45591
|
-
supportsWholeGenome() {
|
|
45594
|
+
get supportsWholeGenome() {
|
|
45592
45595
|
return false;
|
|
45593
45596
|
}
|
|
45594
45597
|
/**
|
|
@@ -47679,7 +47682,7 @@
|
|
|
47679
47682
|
return this.tracks.find(t => name === t.name);
|
|
47680
47683
|
}
|
|
47681
47684
|
|
|
47682
|
-
|
|
47685
|
+
getChordSet(name) {
|
|
47683
47686
|
return this.chordSets.find(cs => name === cs.name);
|
|
47684
47687
|
}
|
|
47685
47688
|
|
|
@@ -47789,9 +47792,9 @@
|
|
|
47789
47792
|
buttonContainer.appendChild(this.showControlsButton);
|
|
47790
47793
|
this.showControlsButton.innerText = 'none' === this.controlPanel.style.display ? 'Show Controls' : 'Hide Controls';
|
|
47791
47794
|
this.showControlsButton.addEventListener('click', event => {
|
|
47792
|
-
const
|
|
47795
|
+
const panelRows = this.controlPanel.querySelectorAll('div');
|
|
47793
47796
|
|
|
47794
|
-
if (
|
|
47797
|
+
if (panelRows.length > 0) {
|
|
47795
47798
|
if ('none' === this.controlPanel.style.display) {
|
|
47796
47799
|
this.controlPanel.style.display = 'flex';
|
|
47797
47800
|
event.target.innerText = 'Hide Controls';
|
|
@@ -47871,10 +47874,10 @@
|
|
|
47871
47874
|
hideShowButton.innerText = true === chordSet.visible ? 'Hide' : 'Show';
|
|
47872
47875
|
hideShowButton.addEventListener('click', event => {
|
|
47873
47876
|
if (true === chordSet.visible) {
|
|
47874
|
-
this.
|
|
47877
|
+
this.hideChordSet(chordSet.name);
|
|
47875
47878
|
event.target.innerText = "Show";
|
|
47876
47879
|
} else {
|
|
47877
|
-
this.
|
|
47880
|
+
this.showChordSet(chordSet.name);
|
|
47878
47881
|
event.target.innerText = "Hide";
|
|
47879
47882
|
}
|
|
47880
47883
|
}); // The alpha range slider. Create this here so we can reference it from the color picker
|
|
@@ -47901,7 +47904,7 @@
|
|
|
47901
47904
|
rgbaString
|
|
47902
47905
|
}) => {
|
|
47903
47906
|
colorPickerButton.style.backgroundColor = setAlpha(rgbaString, 1);
|
|
47904
|
-
this.
|
|
47907
|
+
this.setColor(chordSet.name, rgbaString);
|
|
47905
47908
|
alphaSlider.value = alphaToValue(getAlpha(chordSet.color));
|
|
47906
47909
|
}
|
|
47907
47910
|
};
|
|
@@ -47919,7 +47922,7 @@
|
|
|
47919
47922
|
|
|
47920
47923
|
alphaSlider.oninput = () => {
|
|
47921
47924
|
const v = valueToAlpha(alphaSlider.value);
|
|
47922
|
-
this.
|
|
47925
|
+
this.setColor(chordSet.name, setAlpha(chordSet.color, v));
|
|
47923
47926
|
picker.setColor(chordSet.color);
|
|
47924
47927
|
};
|
|
47925
47928
|
|
|
@@ -47938,12 +47941,14 @@
|
|
|
47938
47941
|
|
|
47939
47942
|
|
|
47940
47943
|
setAssembly(igvGenome) {
|
|
47941
|
-
|
|
47944
|
+
const id = this.genomeId || guid();
|
|
47945
|
+
|
|
47946
|
+
if (this.genomeId === id) {
|
|
47942
47947
|
return;
|
|
47943
47948
|
}
|
|
47944
47949
|
|
|
47945
47950
|
this.chordManager.clearChords();
|
|
47946
|
-
this.genomeId =
|
|
47951
|
+
this.genomeId = id;
|
|
47947
47952
|
this.chrNames = new Set(igvGenome.chromosomes.map(chr => shortChrName$1(chr.name)));
|
|
47948
47953
|
const regions = [];
|
|
47949
47954
|
const colors = [];
|
|
@@ -47962,7 +47967,7 @@
|
|
|
47962
47967
|
this.assembly = {
|
|
47963
47968
|
name: igvGenome.name,
|
|
47964
47969
|
sequence: {
|
|
47965
|
-
trackId:
|
|
47970
|
+
trackId: id,
|
|
47966
47971
|
type: 'ReferenceSequenceTrack',
|
|
47967
47972
|
adapter: {
|
|
47968
47973
|
type: 'FromConfigSequenceAdapter',
|
|
@@ -48000,7 +48005,7 @@
|
|
|
48000
48005
|
|
|
48001
48006
|
|
|
48002
48007
|
addChords(newChords, options = {}) {
|
|
48003
|
-
const tmp = options.
|
|
48008
|
+
const tmp = options.name || options.track || "*";
|
|
48004
48009
|
const trackName = tmp.split(' ')[0].replaceAll("%20", " ");
|
|
48005
48010
|
const chordSetName = tmp.replaceAll("%20", " ");
|
|
48006
48011
|
const chordSet = {
|
|
@@ -48050,20 +48055,6 @@
|
|
|
48050
48055
|
clearSelection() {
|
|
48051
48056
|
this.viewState.pluginManager.rootModel.session.clearSelection();
|
|
48052
48057
|
}
|
|
48053
|
-
|
|
48054
|
-
getFeature(featureId) {
|
|
48055
|
-
// TODO -- broken
|
|
48056
|
-
// const display = this.viewState.pluginManager.rootModel.session.view.tracks[0].displays[0]
|
|
48057
|
-
// const feature = display.data.features.get(featureId)
|
|
48058
|
-
// return feature;
|
|
48059
|
-
const features = [...this.viewState.config.tracks[0].adapter.features.value];
|
|
48060
|
-
|
|
48061
|
-
for (let f of features) {
|
|
48062
|
-
if (featureId === f.uniqueId) {
|
|
48063
|
-
return f;
|
|
48064
|
-
}
|
|
48065
|
-
}
|
|
48066
|
-
}
|
|
48067
48058
|
/**
|
|
48068
48059
|
* Deprecated, use "visible" property
|
|
48069
48060
|
*/
|
|
@@ -48089,25 +48080,25 @@
|
|
|
48089
48080
|
this.parent.style.display = isVisible ? 'block' : 'none';
|
|
48090
48081
|
}
|
|
48091
48082
|
|
|
48092
|
-
|
|
48093
|
-
let
|
|
48083
|
+
hideChordSet(trackName) {
|
|
48084
|
+
let cs = this.getChordSet(trackName);
|
|
48094
48085
|
|
|
48095
|
-
if (
|
|
48096
|
-
|
|
48086
|
+
if (cs) {
|
|
48087
|
+
cs.visible = false;
|
|
48097
48088
|
this.render();
|
|
48098
48089
|
} else {
|
|
48099
48090
|
console.warn(`No track with name: ${name}`);
|
|
48100
48091
|
}
|
|
48101
48092
|
}
|
|
48102
48093
|
|
|
48103
|
-
|
|
48104
|
-
let
|
|
48094
|
+
showChordSet(name) {
|
|
48095
|
+
let cs = this.getChordSet(name);
|
|
48105
48096
|
|
|
48106
|
-
if (
|
|
48107
|
-
|
|
48097
|
+
if (cs) {
|
|
48098
|
+
cs.visible = true;
|
|
48108
48099
|
this.render();
|
|
48109
48100
|
} else {
|
|
48110
|
-
console.warn(`No track with name: ${
|
|
48101
|
+
console.warn(`No track with name: ${name}`);
|
|
48111
48102
|
}
|
|
48112
48103
|
} // showTrack(trackID) {
|
|
48113
48104
|
// let idx = this.tracks.findIndex(t => trackID === t.id)
|
|
@@ -48134,12 +48125,12 @@
|
|
|
48134
48125
|
this.render();
|
|
48135
48126
|
}
|
|
48136
48127
|
|
|
48137
|
-
|
|
48138
|
-
return this.groupByTrack ? this.chordManager.getTrack(name) : this.chordManager.
|
|
48128
|
+
getChordSet(name) {
|
|
48129
|
+
return this.groupByTrack ? this.chordManager.getTrack(name) : this.chordManager.getChordSet(name);
|
|
48139
48130
|
}
|
|
48140
48131
|
|
|
48141
|
-
|
|
48142
|
-
const t = this.
|
|
48132
|
+
setColor(name, color) {
|
|
48133
|
+
const t = this.getChordSet(name);
|
|
48143
48134
|
|
|
48144
48135
|
if (t) {
|
|
48145
48136
|
t.color = color;
|
|
@@ -48240,7 +48231,7 @@
|
|
|
48240
48231
|
}
|
|
48241
48232
|
|
|
48242
48233
|
function embedCSS$1() {
|
|
48243
|
-
const css = '.igv-circview-container {\n z-index: 2048;\n
|
|
48234
|
+
const css = '.igv-circview-container {\n z-index: 2048;\n width: fit-content;\n height: fit-content;\n box-sizing: content-box;\n color: dimgray;\n font-family: \"Open Sans\", sans-serif;\n font-size: 12px;\n background-color: white;\n border-color: dimgray;\n border-style: solid;\n border-width: thin;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n}\n\n.igv-circview-toolbar {\n position: relative;\n width: 100%;\n height: 32px;\n background-color: lightgrey;\n border-bottom-style: solid;\n border-bottom-color: dimgray;\n border-bottom-width: thin;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n}\n\n.igv-circview-toolbar-button-container {\n height: 100%;\n width: fit-content;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n}\n.igv-circview-toolbar-button-container > div {\n margin: 4px;\n}\n\n.igv-circview-track-panel {\n z-index: 1024;\n position: absolute;\n top: 33px;\n left: 0;\n width: 100%;\n height: fit-content;\n border-bottom-style: solid;\n border-bottom-color: dimgray;\n border-bottom-width: thin;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n}\n.igv-circview-track-panel > div {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n}\n.igv-circview-track-panel > div > div {\n margin: 4px;\n}\n\n.igv-circview-swatch-button {\n cursor: pointer;\n padding: 5px;\n width: 8px;\n height: 8px;\n border: 1px solid #8d8b8b;\n border-radius: 16px;\n}\n\n.igv-circview-button {\n cursor: pointer;\n padding: 5px;\n color: #444;\n vertical-align: middle;\n text-align: center;\n font-family: \"Open Sans\", sans-serif;\n font-size: 12px;\n border: 1px solid #8d8b8b;\n border-radius: 4px;\n background: #efefef;\n box-shadow: 0 0 5px -1px rgba(0, 0, 0, 0.2);\n}\n\n.igv-circview-button:hover {\n background: #efefef;\n box-shadow: 0 0 5px -1px rgba(0, 0, 0, 0.6);\n}\n\n.igv-circview-button:active {\n color: #007bff;\n box-shadow: 0 0 5px -1px rgba(0, 0, 0, 0.6);\n}\n\n/*# sourceMappingURL=circular-view.css.map */\n';
|
|
48244
48235
|
const style = document.createElement('style');
|
|
48245
48236
|
style.setAttribute('type', 'text/css');
|
|
48246
48237
|
style.innerHTML = css;
|
|
@@ -48398,7 +48389,9 @@
|
|
|
48398
48389
|
track: chordSetName,
|
|
48399
48390
|
color: chordSetColor,
|
|
48400
48391
|
trackColor: trackColor
|
|
48401
|
-
});
|
|
48392
|
+
}); // show circular view if hidden
|
|
48393
|
+
|
|
48394
|
+
if (!track.browser.circularViewVisible) track.browser.circularViewVisible = true;
|
|
48402
48395
|
}
|
|
48403
48396
|
|
|
48404
48397
|
function createCircularView(el, browser) {
|
|
@@ -48411,22 +48404,26 @@
|
|
|
48411
48404
|
|
|
48412
48405
|
function addFrameForFeature(feature) {
|
|
48413
48406
|
feature.chr = browser.genome.getChromosomeName(feature.refName);
|
|
48407
|
+
let frameFound = false;
|
|
48414
48408
|
|
|
48415
|
-
for (let referenceFrame of browser.
|
|
48409
|
+
for (let referenceFrame of browser.referenceFrameList) {
|
|
48416
48410
|
const l = Locus.fromLocusString(referenceFrame.getLocusString());
|
|
48417
48411
|
|
|
48418
48412
|
if (l.contains(feature)) {
|
|
48413
|
+
frameFound = true;
|
|
48419
48414
|
break;
|
|
48420
48415
|
} else if (l.overlaps(feature)) {
|
|
48421
48416
|
referenceFrame.extend(feature);
|
|
48422
|
-
|
|
48423
|
-
} else {
|
|
48424
|
-
const flanking = 2000;
|
|
48425
|
-
const center = (feature.start + feature.end) / 2;
|
|
48426
|
-
browser.addMultiLocusPanel(feature.chr, center - flanking, center + flanking);
|
|
48417
|
+
frameFound = true;
|
|
48427
48418
|
break;
|
|
48428
48419
|
}
|
|
48429
48420
|
}
|
|
48421
|
+
|
|
48422
|
+
if (!frameFound) {
|
|
48423
|
+
const flanking = 2000;
|
|
48424
|
+
const center = (feature.start + feature.end) / 2;
|
|
48425
|
+
browser.addMultiLocusPanel(feature.chr, center - flanking, center + flanking);
|
|
48426
|
+
}
|
|
48430
48427
|
}
|
|
48431
48428
|
}
|
|
48432
48429
|
});
|
|
@@ -48866,7 +48863,7 @@
|
|
|
48866
48863
|
} // Add chords to JBrowse circular view, if present
|
|
48867
48864
|
|
|
48868
48865
|
|
|
48869
|
-
if (this.browser.circularView &&
|
|
48866
|
+
if (this.browser.circularView && (this.alignmentTrack.hasPairs || this.alignmentTrack.hasSupplemental)) {
|
|
48870
48867
|
menuItems.push('<hr/>');
|
|
48871
48868
|
|
|
48872
48869
|
if (this.alignmentTrack.hasPairs) {
|
|
@@ -49383,7 +49380,7 @@
|
|
|
49383
49380
|
for (let alignment of alignmentRow.alignments) {
|
|
49384
49381
|
this.hasPairs = this.hasPairs || alignment.isPaired();
|
|
49385
49382
|
|
|
49386
|
-
if (this.browser.circularView
|
|
49383
|
+
if (this.browser.circularView) {
|
|
49387
49384
|
// This is an expensive check, only do it if needed
|
|
49388
49385
|
this.hasSupplemental = this.hasSupplemental || alignment.hasTag('SA');
|
|
49389
49386
|
}
|
|
@@ -49733,9 +49730,7 @@
|
|
|
49733
49730
|
list.push({
|
|
49734
49731
|
label: 'View read sequence',
|
|
49735
49732
|
click: () => {
|
|
49736
|
-
const
|
|
49737
|
-
if (!alignment) return;
|
|
49738
|
-
const seqstring = alignment.seq; //.map(b => String.fromCharCode(b)).join("");
|
|
49733
|
+
const seqstring = clickedAlignment.seq; //.map(b => String.fromCharCode(b)).join("");
|
|
49739
49734
|
|
|
49740
49735
|
if (!seqstring || "*" === seqstring) {
|
|
49741
49736
|
Alert.presentAlert("Read sequence: *");
|
|
@@ -49748,12 +49743,16 @@
|
|
|
49748
49743
|
if (isSecureContext()) {
|
|
49749
49744
|
list.push({
|
|
49750
49745
|
label: 'Copy read sequence',
|
|
49751
|
-
click: () => {
|
|
49752
|
-
const
|
|
49753
|
-
if (!alignment) return;
|
|
49754
|
-
const seqstring = alignment.seq; //.map(b => String.fromCharCode(b)).join("");
|
|
49746
|
+
click: async () => {
|
|
49747
|
+
const seq = clickedAlignment.seq; //.map(b => String.fromCharCode(b)).join("");
|
|
49755
49748
|
|
|
49756
|
-
|
|
49749
|
+
try {
|
|
49750
|
+
//console.log(`seq: ${seq}`)
|
|
49751
|
+
await navigator.clipboard.writeText(seq);
|
|
49752
|
+
} catch (e) {
|
|
49753
|
+
console.error(e);
|
|
49754
|
+
Alert.presentAlert(`error copying sequence to clipboard ${e}`);
|
|
49755
|
+
}
|
|
49757
49756
|
}
|
|
49758
49757
|
});
|
|
49759
49758
|
}
|
|
@@ -49763,7 +49762,7 @@
|
|
|
49763
49762
|
} // Experimental JBrowse feature
|
|
49764
49763
|
|
|
49765
49764
|
|
|
49766
|
-
if (this.browser.circularView &&
|
|
49765
|
+
if (this.browser.circularView && (this.hasPairs || this.hasSupplemental)) {
|
|
49767
49766
|
if (this.hasPairs) {
|
|
49768
49767
|
list.push({
|
|
49769
49768
|
label: 'Add discordant pairs to circular view',
|
|
@@ -49867,11 +49866,15 @@
|
|
|
49867
49866
|
case "unexpectedPair":
|
|
49868
49867
|
case "pairOrientation":
|
|
49869
49868
|
if (this.pairOrientation && alignment.pairOrientation) {
|
|
49870
|
-
|
|
49869
|
+
const oTypes = orientationTypes[this.pairOrientation];
|
|
49871
49870
|
|
|
49872
49871
|
if (oTypes) {
|
|
49873
|
-
|
|
49874
|
-
|
|
49872
|
+
const pairColor = this.pairColors[oTypes[alignment.pairOrientation]];
|
|
49873
|
+
|
|
49874
|
+
if (pairColor) {
|
|
49875
|
+
color = pairColor;
|
|
49876
|
+
break;
|
|
49877
|
+
}
|
|
49875
49878
|
}
|
|
49876
49879
|
}
|
|
49877
49880
|
|
|
@@ -50191,7 +50194,10 @@
|
|
|
50191
50194
|
currentViewport = this;
|
|
50192
50195
|
this.$tooltip.show();
|
|
50193
50196
|
} else if (currentViewport.guid !== this.guid) {
|
|
50194
|
-
currentViewport.$tooltip
|
|
50197
|
+
if (currentViewport.$tooltip) {
|
|
50198
|
+
currentViewport.$tooltip.hide();
|
|
50199
|
+
}
|
|
50200
|
+
|
|
50195
50201
|
this.$tooltip.show();
|
|
50196
50202
|
currentViewport = this;
|
|
50197
50203
|
} else {
|
|
@@ -50225,7 +50231,9 @@
|
|
|
50225
50231
|
}); // hide tooltip when movement stops
|
|
50226
50232
|
|
|
50227
50233
|
clearTimeout(timer);
|
|
50228
|
-
timer = setTimeout(() =>
|
|
50234
|
+
timer = setTimeout(() => {
|
|
50235
|
+
if (this.$tooltip) this.$tooltip.hide();
|
|
50236
|
+
}, toolTipTimeout);
|
|
50229
50237
|
}
|
|
50230
50238
|
}
|
|
50231
50239
|
|
|
@@ -50240,65 +50248,6 @@
|
|
|
50240
50248
|
|
|
50241
50249
|
}
|
|
50242
50250
|
|
|
50243
|
-
const viewportColumnManager = {
|
|
50244
|
-
createColumns: (columnContainer, count) => {
|
|
50245
|
-
for (let i = 0; i < count; i++) {
|
|
50246
|
-
if (0 === i) {
|
|
50247
|
-
createColumn(columnContainer, 'igv-column');
|
|
50248
|
-
} else {
|
|
50249
|
-
columnContainer.appendChild(div$1({
|
|
50250
|
-
class: 'igv-column-shim'
|
|
50251
|
-
}));
|
|
50252
|
-
createColumn(columnContainer, 'igv-column');
|
|
50253
|
-
}
|
|
50254
|
-
}
|
|
50255
|
-
},
|
|
50256
|
-
removeColumnAtIndex: (i, column) => {
|
|
50257
|
-
const shim = 0 === i ? column.nextElementSibling : column.previousElementSibling;
|
|
50258
|
-
column.remove();
|
|
50259
|
-
shim.remove();
|
|
50260
|
-
},
|
|
50261
|
-
insertAfter: referenceElement => {
|
|
50262
|
-
const shim = div$1({
|
|
50263
|
-
class: 'igv-column-shim'
|
|
50264
|
-
});
|
|
50265
|
-
insertElementAfter(shim, referenceElement);
|
|
50266
|
-
const column = div$1({
|
|
50267
|
-
class: 'igv-column'
|
|
50268
|
-
});
|
|
50269
|
-
insertElementAfter(column, shim);
|
|
50270
|
-
return column;
|
|
50271
|
-
},
|
|
50272
|
-
insertBefore: (referenceElement, count) => {
|
|
50273
|
-
for (let i = 0; i < count; i++) {
|
|
50274
|
-
const column = div$1({
|
|
50275
|
-
class: 'igv-column'
|
|
50276
|
-
});
|
|
50277
|
-
insertElementBefore(column, referenceElement);
|
|
50278
|
-
|
|
50279
|
-
if (count > 1 && i > 0) {
|
|
50280
|
-
const columnShim = div$1({
|
|
50281
|
-
class: 'igv-column-shim'
|
|
50282
|
-
});
|
|
50283
|
-
insertElementBefore(columnShim, column);
|
|
50284
|
-
}
|
|
50285
|
-
}
|
|
50286
|
-
},
|
|
50287
|
-
indexOfColumn: (columnContainer, column) => {
|
|
50288
|
-
const allColumns = columnContainer.querySelectorAll('.igv-column');
|
|
50289
|
-
|
|
50290
|
-
for (let i = 0; i < allColumns.length; i++) {
|
|
50291
|
-
const c = allColumns[i];
|
|
50292
|
-
|
|
50293
|
-
if (c === column) {
|
|
50294
|
-
return i;
|
|
50295
|
-
}
|
|
50296
|
-
}
|
|
50297
|
-
|
|
50298
|
-
return undefined;
|
|
50299
|
-
}
|
|
50300
|
-
};
|
|
50301
|
-
|
|
50302
50251
|
/*
|
|
50303
50252
|
* The MIT License (MIT)
|
|
50304
50253
|
*
|
|
@@ -50330,60 +50279,30 @@
|
|
|
50330
50279
|
}
|
|
50331
50280
|
|
|
50332
50281
|
initializationHelper() {
|
|
50333
|
-
this
|
|
50334
|
-
|
|
50335
|
-
|
|
50336
|
-
this
|
|
50337
|
-
const canvas = this.$ideogramCanvas.get(0);
|
|
50338
|
-
this.ideogram_ctx = canvas.getContext('2d');
|
|
50339
|
-
this.$canvas.remove();
|
|
50340
|
-
this.canvas = undefined;
|
|
50341
|
-
this.ctx = undefined;
|
|
50282
|
+
this.canvas = document.createElement('canvas');
|
|
50283
|
+
this.canvas.className = 'igv-ideogram-canvas';
|
|
50284
|
+
this.$content.append($$1(this.canvas));
|
|
50285
|
+
this.ideogram_ctx = this.canvas.getContext('2d');
|
|
50342
50286
|
this.addMouseHandlers();
|
|
50343
50287
|
}
|
|
50344
50288
|
|
|
50345
50289
|
addMouseHandlers() {
|
|
50346
|
-
this.addBrowserObserver();
|
|
50347
50290
|
this.addViewportClickHandler(this.$viewport.get(0));
|
|
50348
50291
|
}
|
|
50349
50292
|
|
|
50350
|
-
removeMouseHandlers() {
|
|
50351
|
-
this.removeBrowserObserver();
|
|
50352
|
-
this.removeViewportClickHandler(this.$viewport.get(0));
|
|
50353
|
-
}
|
|
50354
|
-
|
|
50355
|
-
addBrowserObserver() {
|
|
50356
|
-
function observerHandler(referenceFrameList) {
|
|
50357
|
-
const column = this.$viewport.get(0).parentElement;
|
|
50358
|
-
|
|
50359
|
-
if (null !== column) {
|
|
50360
|
-
const index = viewportColumnManager.indexOfColumn(this.browser.columnContainer, column); // console.log(`ideogram-viewport - locus-change-handler index(${ index }) ${ referenceFrameList[ index ].getLocusString() } ${ Date.now() } `)
|
|
50361
|
-
|
|
50362
|
-
this.update(this.ideogram_ctx, this.$viewport.width(), this.$viewport.height(), referenceFrameList[index]);
|
|
50363
|
-
}
|
|
50364
|
-
}
|
|
50365
|
-
|
|
50366
|
-
this.boundObserverHandler = observerHandler.bind(this);
|
|
50367
|
-
this.browser.on('locuschange', this.boundObserverHandler);
|
|
50368
|
-
}
|
|
50369
|
-
|
|
50370
|
-
removeBrowserObserver() {
|
|
50371
|
-
this.browser.off('locuschange', this.boundObserverHandler);
|
|
50372
|
-
}
|
|
50373
|
-
|
|
50374
50293
|
addViewportClickHandler(viewport) {
|
|
50294
|
+
this.boundClickHandler = clickHandler.bind(this);
|
|
50295
|
+
viewport.addEventListener('click', this.boundClickHandler);
|
|
50296
|
+
|
|
50375
50297
|
function clickHandler(event) {
|
|
50376
|
-
const column = viewport.parentElement;
|
|
50377
|
-
const index = viewportColumnManager.indexOfColumn(this.browser.columnContainer, column);
|
|
50378
|
-
const referenceFrame = this.browser.referenceFrameList[index];
|
|
50379
50298
|
const {
|
|
50380
50299
|
xNormalized,
|
|
50381
50300
|
width
|
|
50382
50301
|
} = translateMouseCoordinates$1(event, this.ideogram_ctx.canvas);
|
|
50383
50302
|
const {
|
|
50384
50303
|
bpLength
|
|
50385
|
-
} = this.browser.genome.getChromosome(referenceFrame.chr);
|
|
50386
|
-
const locusLength = referenceFrame.bpPerPixel * width;
|
|
50304
|
+
} = this.browser.genome.getChromosome(this.referenceFrame.chr);
|
|
50305
|
+
const locusLength = this.referenceFrame.bpPerPixel * width;
|
|
50387
50306
|
const chrCoveragePercentage = locusLength / bpLength;
|
|
50388
50307
|
let xPercentage = xNormalized;
|
|
50389
50308
|
|
|
@@ -50397,18 +50316,11 @@
|
|
|
50397
50316
|
|
|
50398
50317
|
const ss = Math.round((xPercentage - chrCoveragePercentage / 2.0) * bpLength);
|
|
50399
50318
|
const ee = Math.round((xPercentage + chrCoveragePercentage / 2.0) * bpLength);
|
|
50400
|
-
referenceFrame.start = ss;
|
|
50401
|
-
referenceFrame.end = ee;
|
|
50402
|
-
referenceFrame.bpPerPixel = (ee - ss) / width;
|
|
50403
|
-
this.browser.updateViews(true);
|
|
50319
|
+
this.referenceFrame.start = ss;
|
|
50320
|
+
this.referenceFrame.end = ee;
|
|
50321
|
+
this.referenceFrame.bpPerPixel = (ee - ss) / width;
|
|
50322
|
+
this.browser.updateViews(this.referenceFrame, this.browser.trackViews, true);
|
|
50404
50323
|
}
|
|
50405
|
-
|
|
50406
|
-
this.boundClickHandler = clickHandler.bind(this);
|
|
50407
|
-
viewport.addEventListener('click', this.boundClickHandler);
|
|
50408
|
-
}
|
|
50409
|
-
|
|
50410
|
-
removeViewportClickHandler(viewport) {
|
|
50411
|
-
viewport.removeEventListener('click', this.boundClickHandler);
|
|
50412
50324
|
}
|
|
50413
50325
|
|
|
50414
50326
|
setWidth(width) {
|
|
@@ -50426,14 +50338,22 @@
|
|
|
50426
50338
|
context.restore();
|
|
50427
50339
|
}
|
|
50428
50340
|
|
|
50429
|
-
|
|
50430
|
-
this
|
|
50431
|
-
|
|
50341
|
+
repaint() {
|
|
50342
|
+
this.draw({
|
|
50343
|
+
referenceFrame: this.referenceFrame
|
|
50344
|
+
});
|
|
50345
|
+
}
|
|
50346
|
+
|
|
50347
|
+
draw(_ref) {
|
|
50348
|
+
let {
|
|
50349
|
+
referenceFrame
|
|
50350
|
+
} = _ref;
|
|
50351
|
+
IGVGraphics.configureHighDPICanvas(this.ideogram_ctx, this.$viewport.width(), this.$viewport.height());
|
|
50432
50352
|
this.trackView.track.draw({
|
|
50433
|
-
context,
|
|
50353
|
+
context: this.ideogram_ctx,
|
|
50434
50354
|
referenceFrame,
|
|
50435
|
-
pixelWidth,
|
|
50436
|
-
pixelHeight
|
|
50355
|
+
pixelWidth: this.$viewport.width(),
|
|
50356
|
+
pixelHeight: this.$viewport.height()
|
|
50437
50357
|
});
|
|
50438
50358
|
}
|
|
50439
50359
|
|
|
@@ -50471,7 +50391,7 @@
|
|
|
50471
50391
|
function createViewport(trackView, column, referenceFrame, width) {
|
|
50472
50392
|
if ('ruler' === trackView.track.type) {
|
|
50473
50393
|
return new RulerViewport(trackView, column, referenceFrame, width);
|
|
50474
|
-
} else if ('ideogram' === trackView.track.
|
|
50394
|
+
} else if ('ideogram' === trackView.track.id) {
|
|
50475
50395
|
return new IdeogramViewport(trackView, column, referenceFrame, width);
|
|
50476
50396
|
} else {
|
|
50477
50397
|
return new TrackViewport(trackView, column, referenceFrame, width);
|
|
@@ -50998,7 +50918,6 @@
|
|
|
50998
50918
|
|
|
50999
50919
|
class TrackView {
|
|
51000
50920
|
constructor(browser, columnContainer, track) {
|
|
51001
|
-
this.namespace = `trackview-${guid$2()}`;
|
|
51002
50921
|
this.browser = browser;
|
|
51003
50922
|
this.track = track;
|
|
51004
50923
|
track.trackView = this;
|
|
@@ -51024,7 +50943,7 @@
|
|
|
51024
50943
|
|
|
51025
50944
|
addDOMToColumnContainer(browser, columnContainer, referenceFrameList) {
|
|
51026
50945
|
// Axis
|
|
51027
|
-
this.axis = this.createAxis(browser, this.track); //
|
|
50946
|
+
this.axis = this.createAxis(browser, this.track); // Create a viewport for each reference frame
|
|
51028
50947
|
|
|
51029
50948
|
this.viewports = [];
|
|
51030
50949
|
const viewportWidth = browser.calculateViewportWidth(referenceFrameList.length);
|
|
@@ -51091,7 +51010,6 @@
|
|
|
51091
51010
|
this.axis.remove(); // Track Viewports
|
|
51092
51011
|
|
|
51093
51012
|
for (let viewport of this.viewports) {
|
|
51094
|
-
viewport.removeMouseHandlers();
|
|
51095
51013
|
viewport.$viewport.remove();
|
|
51096
51014
|
} // SampleName Viewport
|
|
51097
51015
|
|
|
@@ -51209,7 +51127,7 @@
|
|
|
51209
51127
|
$viewport.height(newHeight);
|
|
51210
51128
|
}
|
|
51211
51129
|
|
|
51212
|
-
this.sampleNameViewport.viewport.style.height = `${newHeight}px`; // If the track does not manage its own content height set it here
|
|
51130
|
+
this.sampleNameViewport.viewport.style.height = `${newHeight}px`; // If the track does not manage its own content height set it equal to the viewport height here
|
|
51213
51131
|
|
|
51214
51132
|
if (typeof this.track.computePixelHeight !== "function") {
|
|
51215
51133
|
for (let vp of this.viewports) {
|
|
@@ -51261,14 +51179,6 @@
|
|
|
51261
51179
|
if (viewport.isLoading()) return true;
|
|
51262
51180
|
}
|
|
51263
51181
|
}
|
|
51264
|
-
|
|
51265
|
-
resize(viewportWidth) {
|
|
51266
|
-
for (let viewport of this.viewports) {
|
|
51267
|
-
viewport.setWidth(viewportWidth);
|
|
51268
|
-
}
|
|
51269
|
-
|
|
51270
|
-
this.updateViews(true);
|
|
51271
|
-
}
|
|
51272
51182
|
/**
|
|
51273
51183
|
* Repaint all viewports without loading any new data. Use this for events that change visual aspect of data,
|
|
51274
51184
|
* e.g. color, sort order, etc, but do not change the genomic state.
|
|
@@ -51301,6 +51211,19 @@
|
|
|
51301
51211
|
setTrackLabelName(name) {
|
|
51302
51212
|
this.viewports.forEach(viewport => viewport.setTrackLabel(name));
|
|
51303
51213
|
}
|
|
51214
|
+
/**
|
|
51215
|
+
* Called in response to a window resize event, change in # of multilocus panels, or other event that changes
|
|
51216
|
+
* the width of the track view.
|
|
51217
|
+
*
|
|
51218
|
+
* @param viewportWidth The width of each viewport in this track view.
|
|
51219
|
+
*/
|
|
51220
|
+
|
|
51221
|
+
|
|
51222
|
+
resize(viewportWidth) {
|
|
51223
|
+
for (let viewport of this.viewports) {
|
|
51224
|
+
viewport.setWidth(viewportWidth);
|
|
51225
|
+
}
|
|
51226
|
+
}
|
|
51304
51227
|
/**
|
|
51305
51228
|
* Update viewports to reflect current genomic state, possibly loading additional data.
|
|
51306
51229
|
*
|
|
@@ -51309,22 +51232,25 @@
|
|
|
51309
51232
|
*/
|
|
51310
51233
|
|
|
51311
51234
|
|
|
51312
|
-
async updateViews(
|
|
51235
|
+
async updateViews() {
|
|
51313
51236
|
if (!(this.browser && this.browser.referenceFrameList)) return;
|
|
51314
51237
|
const visibleViewports = this.viewports.filter(viewport => viewport.isVisible()); // Shift viewports left/right to current genomic state (pans canvas)
|
|
51315
51238
|
|
|
51316
|
-
visibleViewports.forEach(viewport => viewport.shift());
|
|
51317
|
-
const isDragging = this.browser.dragObject;
|
|
51239
|
+
visibleViewports.forEach(viewport => viewport.shift()); // If dragging (panning) return
|
|
51318
51240
|
|
|
51319
|
-
if (
|
|
51241
|
+
if (this.browser.dragObject) {
|
|
51320
51242
|
return;
|
|
51321
|
-
} //
|
|
51243
|
+
} // Get viewports to repaint
|
|
51244
|
+
|
|
51322
51245
|
|
|
51246
|
+
let viewportsToRepaint = this.track.autoscale || this.track.autoscaleGroup || this.track.type === 'ruler' ? visibleViewports : visibleViewports.filter(vp => vp.needsRepaint()); // Filter zoomed out views. This has the side effect or turning off or no the zoomed out notice
|
|
51323
51247
|
|
|
51324
|
-
|
|
51248
|
+
viewportsToRepaint = viewportsToRepaint.filter(viewport => viewport.checkZoomIn()); // Get viewports that require a data load
|
|
51249
|
+
|
|
51250
|
+
const viewportsToReload = viewportsToRepaint.filter(viewport => viewport.needsReload()); // Trigger viewport to load features needed to cover current genomic range
|
|
51325
51251
|
// NOTE: these must be loaded synchronously, do not user Promise.all, not all file readers are thread safe
|
|
51326
51252
|
|
|
51327
|
-
for (let viewport of
|
|
51253
|
+
for (let viewport of viewportsToReload) {
|
|
51328
51254
|
await viewport.loadFeatures();
|
|
51329
51255
|
}
|
|
51330
51256
|
|
|
@@ -51333,7 +51259,7 @@
|
|
|
51333
51259
|
// section depends on data from all the views. We only need to adjust this however if any data was loaded
|
|
51334
51260
|
// (i.e. reloadableViewports.length > 0)
|
|
51335
51261
|
|
|
51336
|
-
if (this.track && typeof this.track.variantRowCount === 'function' &&
|
|
51262
|
+
if (this.track && typeof this.track.variantRowCount === 'function' && viewportsToReload.length > 0) {
|
|
51337
51263
|
let maxRow = 0;
|
|
51338
51264
|
|
|
51339
51265
|
for (let viewport of this.viewports) {
|
|
@@ -51378,23 +51304,10 @@
|
|
|
51378
51304
|
} else {
|
|
51379
51305
|
this.track.dataRange = doAutoscale(allFeatures);
|
|
51380
51306
|
}
|
|
51381
|
-
}
|
|
51382
|
-
|
|
51383
|
-
|
|
51384
|
-
if (this.track.autoscale || this.track.autoscaleGroup || this.track.type === 'ruler' || force) {
|
|
51385
|
-
for (let vp of visibleViewports) {
|
|
51386
|
-
vp.repaint();
|
|
51387
|
-
}
|
|
51388
|
-
} else {
|
|
51389
|
-
const reloadedViewports = new Set(reloadableViewports);
|
|
51390
|
-
|
|
51391
|
-
for (let vp of visibleViewports) {
|
|
51392
|
-
const invalid = vp.canvas && vp.canvas._data && vp.canvas._data.invalidate;
|
|
51307
|
+
}
|
|
51393
51308
|
|
|
51394
|
-
|
|
51395
|
-
|
|
51396
|
-
}
|
|
51397
|
-
}
|
|
51309
|
+
for (let vp of viewportsToRepaint) {
|
|
51310
|
+
vp.repaint();
|
|
51398
51311
|
}
|
|
51399
51312
|
|
|
51400
51313
|
this.adjustTrackHeight(); // Repaint sample names last
|
|
@@ -51417,24 +51330,22 @@
|
|
|
51417
51330
|
}
|
|
51418
51331
|
}
|
|
51419
51332
|
/**
|
|
51420
|
-
* Return a promise to get all in-view features. Used for group autoscaling.
|
|
51333
|
+
* Return a promise to get all in-view features across all viewports. Used for group autoscaling.
|
|
51421
51334
|
*/
|
|
51422
51335
|
|
|
51423
51336
|
|
|
51424
51337
|
async getInViewFeatures() {
|
|
51425
51338
|
if (!(this.browser && this.browser.referenceFrameList)) {
|
|
51426
51339
|
return [];
|
|
51427
|
-
}
|
|
51428
|
-
|
|
51340
|
+
}
|
|
51429
51341
|
|
|
51430
|
-
const rpV = this.viewportsToReload();
|
|
51431
|
-
const promises = rpV.map(function (vp) {
|
|
51432
|
-
return vp.loadFeatures();
|
|
51433
|
-
});
|
|
51434
|
-
await Promise.all(promises);
|
|
51435
51342
|
let allFeatures = [];
|
|
51436
51343
|
|
|
51437
51344
|
for (let vp of this.viewports) {
|
|
51345
|
+
if (vp.needsReload()) {
|
|
51346
|
+
await vp.loadFeatures();
|
|
51347
|
+
}
|
|
51348
|
+
|
|
51438
51349
|
if (vp.featureCache && vp.featureCache.features) {
|
|
51439
51350
|
const referenceFrame = vp.referenceFrame;
|
|
51440
51351
|
const start = referenceFrame.start;
|
|
@@ -51488,27 +51399,6 @@
|
|
|
51488
51399
|
}
|
|
51489
51400
|
}
|
|
51490
51401
|
|
|
51491
|
-
viewportsToReload(force) {
|
|
51492
|
-
// List of viewports that need reloading
|
|
51493
|
-
const viewports = this.viewports.filter(viewport => {
|
|
51494
|
-
if (!viewport.isVisible()) {
|
|
51495
|
-
return false;
|
|
51496
|
-
}
|
|
51497
|
-
|
|
51498
|
-
if (!viewport.checkZoomIn()) {
|
|
51499
|
-
return false;
|
|
51500
|
-
} else {
|
|
51501
|
-
const referenceFrame = viewport.referenceFrame;
|
|
51502
|
-
const chr = viewport.referenceFrame.chr;
|
|
51503
|
-
const start = referenceFrame.start;
|
|
51504
|
-
const end = start + referenceFrame.toBP($$1(viewport.contentDiv).width());
|
|
51505
|
-
const bpPerPixel = referenceFrame.bpPerPixel;
|
|
51506
|
-
return !viewport.featureCache || !viewport.featureCache.containsRange(chr, start, end, bpPerPixel);
|
|
51507
|
-
}
|
|
51508
|
-
});
|
|
51509
|
-
return viewports;
|
|
51510
|
-
}
|
|
51511
|
-
|
|
51512
51402
|
createTrackScrollbar(browser) {
|
|
51513
51403
|
const outerScroll = div$1();
|
|
51514
51404
|
browser.columnContainer.querySelector('.igv-scrollbar-column').appendChild(outerScroll);
|
|
@@ -51602,7 +51492,7 @@
|
|
|
51602
51492
|
}
|
|
51603
51493
|
|
|
51604
51494
|
addTrackDragMouseHandlers(browser) {
|
|
51605
|
-
if ('ideogram' === this.track.
|
|
51495
|
+
if ('ideogram' === this.track.id || 'ruler' === this.track.id) ; else {
|
|
51606
51496
|
let currentDragHandle = undefined; // Mouse Down
|
|
51607
51497
|
|
|
51608
51498
|
this.boundTrackDragMouseDownHandler = trackDragMouseDownHandler.bind(this);
|
|
@@ -51666,7 +51556,7 @@
|
|
|
51666
51556
|
}
|
|
51667
51557
|
|
|
51668
51558
|
removeTrackDragMouseHandlers() {
|
|
51669
|
-
if ('ideogram' === this.track.
|
|
51559
|
+
if ('ideogram' === this.track.id || 'ruler' === this.track.id) ; else {
|
|
51670
51560
|
this.dragHandle.removeEventListener('mousedown', this.boundTrackDragMouseDownHandler);
|
|
51671
51561
|
document.removeEventListener('mouseup', this.boundDocumentTrackDragMouseUpHandler);
|
|
51672
51562
|
this.dragHandle.removeEventListener('mouseup', this.boundTrackDragMouseEnterHandler);
|
|
@@ -52561,7 +52451,7 @@
|
|
|
52561
52451
|
});
|
|
52562
52452
|
}
|
|
52563
52453
|
|
|
52564
|
-
findUTRs(exons, feature.cdStart, feature.cdEnd);
|
|
52454
|
+
findUTRs$1(exons, feature.cdStart, feature.cdEnd);
|
|
52565
52455
|
feature.exons = exons;
|
|
52566
52456
|
} // Optional extra columns
|
|
52567
52457
|
|
|
@@ -52666,7 +52556,7 @@
|
|
|
52666
52556
|
});
|
|
52667
52557
|
}
|
|
52668
52558
|
|
|
52669
|
-
findUTRs(exons, cdStart, cdEnd);
|
|
52559
|
+
findUTRs$1(exons, cdStart, cdEnd);
|
|
52670
52560
|
feature.exons = exons;
|
|
52671
52561
|
return feature;
|
|
52672
52562
|
}
|
|
@@ -52708,7 +52598,7 @@
|
|
|
52708
52598
|
});
|
|
52709
52599
|
}
|
|
52710
52600
|
|
|
52711
|
-
findUTRs(exons, cdStart, cdEnd);
|
|
52601
|
+
findUTRs$1(exons, cdStart, cdEnd);
|
|
52712
52602
|
feature.exons = exons;
|
|
52713
52603
|
return feature;
|
|
52714
52604
|
}
|
|
@@ -52749,12 +52639,12 @@
|
|
|
52749
52639
|
});
|
|
52750
52640
|
}
|
|
52751
52641
|
|
|
52752
|
-
findUTRs(exons, cdStart, cdEnd);
|
|
52642
|
+
findUTRs$1(exons, cdStart, cdEnd);
|
|
52753
52643
|
feature.exons = exons;
|
|
52754
52644
|
return feature;
|
|
52755
52645
|
}
|
|
52756
52646
|
|
|
52757
|
-
function findUTRs(exons, cdStart, cdEnd) {
|
|
52647
|
+
function findUTRs$1(exons, cdStart, cdEnd) {
|
|
52758
52648
|
for (let exon of exons) {
|
|
52759
52649
|
const end = exon.end;
|
|
52760
52650
|
const start = exon.start;
|
|
@@ -56313,7 +56203,7 @@
|
|
|
56313
56203
|
this.genome = genome;
|
|
56314
56204
|
this.sourceType = config.sourceType === undefined ? "file" : config.sourceType;
|
|
56315
56205
|
this.maxWGCount = config.maxWGCount || DEFAULT_MAX_WG_COUNT;
|
|
56316
|
-
const queryableFormats = new Set(["bigwig", "bw", "bigbed", "bb", "biginteract", "tdf"]);
|
|
56206
|
+
const queryableFormats = new Set(["bigwig", "bw", "bigbed", "bb", "biginteract", "biggenepred", "bignarrowpeak", "tdf"]);
|
|
56317
56207
|
|
|
56318
56208
|
if (config.features && Array.isArray(config.features)) {
|
|
56319
56209
|
// Explicit array of features
|
|
@@ -56724,10 +56614,8 @@
|
|
|
56724
56614
|
|
|
56725
56615
|
}
|
|
56726
56616
|
|
|
56727
|
-
//table chromatinInteract
|
|
56728
|
-
|
|
56729
56617
|
function getDecoder(definedFieldCount, fieldCount, autoSql, format) {
|
|
56730
|
-
if (autoSql && 'chromatinInteract' === autoSql.table ||
|
|
56618
|
+
if ("biginteract" === format || autoSql && 'chromatinInteract' === autoSql.table || 'interact' === autoSql.table) {
|
|
56731
56619
|
return decodeInteract;
|
|
56732
56620
|
} else {
|
|
56733
56621
|
const standardFieldCount = definedFieldCount - 3;
|
|
@@ -56774,6 +56662,7 @@
|
|
|
56774
56662
|
});
|
|
56775
56663
|
}
|
|
56776
56664
|
|
|
56665
|
+
findUTRs(exons, feature.cdStart, feature.cdEnd);
|
|
56777
56666
|
feature.exons = exons;
|
|
56778
56667
|
}
|
|
56779
56668
|
|
|
@@ -56790,7 +56679,29 @@
|
|
|
56790
56679
|
}
|
|
56791
56680
|
}
|
|
56792
56681
|
};
|
|
56793
|
-
}
|
|
56682
|
+
} //table chromatinInteract
|
|
56683
|
+
// "Chromatin interaction between two regions"
|
|
56684
|
+
// (
|
|
56685
|
+
// string chrom; "Chromosome (or contig, scaffold, etc.). For interchromosomal, use 2 records"
|
|
56686
|
+
// uint chromStart; "Start position of lower region. For interchromosomal, set to chromStart of this region"
|
|
56687
|
+
// uint chromEnd; "End position of upper region. For interchromosomal, set to chromEnd of this region"
|
|
56688
|
+
// string name; "Name of item, for display"
|
|
56689
|
+
// uint score; "Score from 0-1000"
|
|
56690
|
+
// double value; "Strength of interaction or other data value. Typically basis for score"
|
|
56691
|
+
// string exp; "Experiment name (metadata for filtering). Use . if not applicable"
|
|
56692
|
+
// string color; "Item color. Specified as r,g,b or hexadecimal #RRGGBB or html color name, as in //www.w3.org/TR/css3-color/#html4."
|
|
56693
|
+
// string region1Chrom; "Chromosome of lower region. For non-directional interchromosomal, chrom of this region."
|
|
56694
|
+
// uint region1Start; "Start position of lower/this region"
|
|
56695
|
+
// uint region1End; "End position in chromosome of lower/this region"
|
|
56696
|
+
// string region1Name; "Identifier of lower/this region"
|
|
56697
|
+
// string region1Strand; "Orientation of lower/this region: + or -. Use . if not applicable"
|
|
56698
|
+
// string region2Chrom; "Chromosome of upper region. For non-directional interchromosomal, chrom of other region"
|
|
56699
|
+
// uint region2Start; "Start position in chromosome of upper/this region"
|
|
56700
|
+
// uint region2End; "End position in chromosome of upper/this region"
|
|
56701
|
+
// string region2Name; "Identifier of upper/this region"
|
|
56702
|
+
// string region2Strand; "Orientation of upper/this region: + or -. Use . if not applicable"
|
|
56703
|
+
// )
|
|
56704
|
+
|
|
56794
56705
|
|
|
56795
56706
|
function decodeInteract(feature, tokens) {
|
|
56796
56707
|
feature.chr1 = tokens[5];
|
|
@@ -56807,6 +56718,25 @@
|
|
|
56807
56718
|
}
|
|
56808
56719
|
}
|
|
56809
56720
|
|
|
56721
|
+
function findUTRs(exons, cdStart, cdEnd) {
|
|
56722
|
+
for (let exon of exons) {
|
|
56723
|
+
const end = exon.end;
|
|
56724
|
+
const start = exon.start;
|
|
56725
|
+
|
|
56726
|
+
if (end < cdStart || start > cdEnd) {
|
|
56727
|
+
exon.utr = true;
|
|
56728
|
+
} else {
|
|
56729
|
+
if (cdStart >= start && cdStart <= end) {
|
|
56730
|
+
exon.cdStart = cdStart;
|
|
56731
|
+
}
|
|
56732
|
+
|
|
56733
|
+
if (cdEnd >= start && cdEnd <= end) {
|
|
56734
|
+
exon.cdEnd = cdEnd;
|
|
56735
|
+
}
|
|
56736
|
+
}
|
|
56737
|
+
}
|
|
56738
|
+
}
|
|
56739
|
+
|
|
56810
56740
|
function scoreShade(score, color) {
|
|
56811
56741
|
const alpha = Math.min(1, 0.11 + 0.89 * (score / 779));
|
|
56812
56742
|
return alpha.toString();
|
|
@@ -58252,7 +58182,7 @@
|
|
|
58252
58182
|
return features;
|
|
58253
58183
|
}
|
|
58254
58184
|
|
|
58255
|
-
supportsWholeGenome() {
|
|
58185
|
+
get supportsWholeGenome() {
|
|
58256
58186
|
return true;
|
|
58257
58187
|
}
|
|
58258
58188
|
|
|
@@ -58357,11 +58287,12 @@
|
|
|
58357
58287
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
58358
58288
|
* THE SOFTWARE.
|
|
58359
58289
|
*/
|
|
58290
|
+
const bbFormats = new Set(['bigwig', 'bw', 'bigbed', 'bb', 'biginteract', 'biggenepred', 'bignarrowpeak']);
|
|
58360
58291
|
|
|
58361
58292
|
function FeatureSource(config, genome) {
|
|
58362
58293
|
const format = config.format ? config.format.toLowerCase() : undefined;
|
|
58363
58294
|
|
|
58364
|
-
if (
|
|
58295
|
+
if (bbFormats.has(format)) {
|
|
58365
58296
|
return new BWSource(config, genome);
|
|
58366
58297
|
} else if ("tdf" === format) {
|
|
58367
58298
|
return new TDFSource(config, genome);
|
|
@@ -58370,30 +58301,6 @@
|
|
|
58370
58301
|
}
|
|
58371
58302
|
}
|
|
58372
58303
|
|
|
58373
|
-
const pairs = [['A', 'T'], ['G', 'C'], ['Y', 'R'], ['W', 'S'], ['K', 'M'], ['D', 'H'], ['B', 'V']];
|
|
58374
|
-
const complements = new Map();
|
|
58375
|
-
|
|
58376
|
-
for (let p of pairs) {
|
|
58377
|
-
const p1 = p[0];
|
|
58378
|
-
const p2 = p[1];
|
|
58379
|
-
complements.set(p1, p2);
|
|
58380
|
-
complements.set(p2, p1);
|
|
58381
|
-
complements.set(p1.toLowerCase(), p2.toLowerCase());
|
|
58382
|
-
complements.set(p2.toLowerCase(), p1.toLowerCase());
|
|
58383
|
-
}
|
|
58384
|
-
|
|
58385
|
-
function reverseComplementSequence(sequence) {
|
|
58386
|
-
let comp = '';
|
|
58387
|
-
let idx = sequence.length;
|
|
58388
|
-
|
|
58389
|
-
while (idx-- > 0) {
|
|
58390
|
-
const base = sequence[idx];
|
|
58391
|
-
comp += complements.has(base) ? complements.get(base) : base;
|
|
58392
|
-
}
|
|
58393
|
-
|
|
58394
|
-
return comp;
|
|
58395
|
-
}
|
|
58396
|
-
|
|
58397
58304
|
const GtexUtils = {
|
|
58398
58305
|
getTissueInfo: function (datasetId, baseURL) {
|
|
58399
58306
|
datasetId = datasetId || 'gtex_v8';
|
|
@@ -58489,7 +58396,7 @@
|
|
|
58489
58396
|
// single-exon transcript
|
|
58490
58397
|
const xLeft = Math.max(0, coord.px);
|
|
58491
58398
|
const xRight = Math.min(pixelWidth, coord.px1);
|
|
58492
|
-
const width =
|
|
58399
|
+
const width = xRight - xLeft;
|
|
58493
58400
|
ctx.fillRect(xLeft, py, width, h); // Arrows
|
|
58494
58401
|
// Do not draw if strand is not +/-
|
|
58495
58402
|
|
|
@@ -58634,8 +58541,8 @@
|
|
|
58634
58541
|
const xleft = centerX - textBox.width / 2;
|
|
58635
58542
|
const xright = centerX + textBox.width / 2;
|
|
58636
58543
|
|
|
58637
|
-
if (options.labelAllFeatures || xleft > options.
|
|
58638
|
-
options.
|
|
58544
|
+
if (options.labelAllFeatures || xleft > options.rowLastLabelX[feature.row] || gtexSelection) {
|
|
58545
|
+
options.rowLastLabelX[feature.row] = xright;
|
|
58639
58546
|
IGVGraphics.fillText(ctx, name, centerX, labelY, geneFontStyle, transform);
|
|
58640
58547
|
}
|
|
58641
58548
|
} finally {
|
|
@@ -58916,7 +58823,7 @@
|
|
|
58916
58823
|
return this;
|
|
58917
58824
|
}
|
|
58918
58825
|
|
|
58919
|
-
supportsWholeGenome() {
|
|
58826
|
+
get supportsWholeGenome() {
|
|
58920
58827
|
return (this.config.indexed === false || !this.config.indexURL) && this.config.supportsWholeGenome !== false;
|
|
58921
58828
|
}
|
|
58922
58829
|
|
|
@@ -58975,27 +58882,31 @@
|
|
|
58975
58882
|
if (featureList) {
|
|
58976
58883
|
const rowFeatureCount = [];
|
|
58977
58884
|
options.rowLastX = [];
|
|
58885
|
+
options.rowLastLabelX = [];
|
|
58978
58886
|
|
|
58979
58887
|
for (let feature of featureList) {
|
|
58980
|
-
|
|
58888
|
+
if (feature.start > bpStart && feature.end < bpEnd) {
|
|
58889
|
+
const row = this.displayMode === "COLLAPSED" ? 0 : feature.row || 0;
|
|
58981
58890
|
|
|
58982
|
-
|
|
58983
|
-
|
|
58984
|
-
|
|
58985
|
-
|
|
58986
|
-
|
|
58891
|
+
if (rowFeatureCount[row] === undefined) {
|
|
58892
|
+
rowFeatureCount[row] = 1;
|
|
58893
|
+
} else {
|
|
58894
|
+
rowFeatureCount[row]++;
|
|
58895
|
+
}
|
|
58987
58896
|
|
|
58988
|
-
|
|
58897
|
+
options.rowLastX[row] = -Number.MAX_SAFE_INTEGER;
|
|
58898
|
+
options.rowLastLabelX[row] = -Number.MAX_SAFE_INTEGER;
|
|
58899
|
+
}
|
|
58989
58900
|
}
|
|
58990
58901
|
|
|
58902
|
+
const pixelsPerFeature = pixelWidth / Math.max(...rowFeatureCount);
|
|
58991
58903
|
let lastPxEnd = [];
|
|
58992
58904
|
|
|
58993
58905
|
for (let feature of featureList) {
|
|
58994
58906
|
if (feature.end < bpStart) continue;
|
|
58995
58907
|
if (feature.start > bpEnd) break;
|
|
58996
58908
|
const row = this.displayMode === 'COLLAPSED' ? 0 : feature.row;
|
|
58997
|
-
|
|
58998
|
-
options.drawLabel = options.labelAllFeatures || featureDensity > 10;
|
|
58909
|
+
options.drawLabel = options.labelAllFeatures || pixelsPerFeature > 10;
|
|
58999
58910
|
const pxEnd = Math.ceil((feature.end - bpStart) / bpPerPixel);
|
|
59000
58911
|
const last = lastPxEnd[row];
|
|
59001
58912
|
|
|
@@ -59069,15 +58980,9 @@
|
|
|
59069
58980
|
for (let fd of featureData) {
|
|
59070
58981
|
data.push(fd);
|
|
59071
58982
|
|
|
59072
|
-
if (infoURL) {
|
|
59073
|
-
|
|
59074
|
-
|
|
59075
|
-
const href = url.replace("$$", feature.name);
|
|
59076
|
-
data.push({
|
|
59077
|
-
name: "Info",
|
|
59078
|
-
value: `<a target="_blank" href=${href}>${fd.value}</a>`
|
|
59079
|
-
});
|
|
59080
|
-
}
|
|
58983
|
+
if (infoURL && fd.name && fd.name.toLowerCase() === "name" && fd.value && isString$3(fd.value) && !fd.value.startsWith("<")) {
|
|
58984
|
+
const href = infoURL.replace("$$", feature.name);
|
|
58985
|
+
fd.value = `<a target=_blank href=${href}>${fd.value}</a>`;
|
|
59081
58986
|
}
|
|
59082
58987
|
} //Array.prototype.push.apply(data, featureData);
|
|
59083
58988
|
// If we have clicked over an exon number it.
|
|
@@ -59151,17 +59056,31 @@
|
|
|
59151
59056
|
}
|
|
59152
59057
|
|
|
59153
59058
|
contextMenuItemList(clickState) {
|
|
59154
|
-
|
|
59155
|
-
const features = this.clickedFeatures(clickState);
|
|
59059
|
+
const features = this.clickedFeatures(clickState);
|
|
59156
59060
|
|
|
59157
|
-
|
|
59158
|
-
|
|
59159
|
-
|
|
59061
|
+
if (features.length > 1) {
|
|
59062
|
+
features.sort((a, b) => b.end - b.start - (a.end - a.start));
|
|
59063
|
+
}
|
|
59064
|
+
|
|
59065
|
+
const f = features[0]; // The shortest clicked feature
|
|
59066
|
+
|
|
59067
|
+
if (f.end - f.start <= 1000000) {
|
|
59068
|
+
const list = [{
|
|
59069
|
+
label: 'View feature sequence',
|
|
59070
|
+
click: async () => {
|
|
59071
|
+
let seq = await this.browser.genome.getSequence(f.chr, f.start, f.end);
|
|
59072
|
+
|
|
59073
|
+
if (f.strand === '-') {
|
|
59074
|
+
seq = reverseComplementSequence(seq);
|
|
59075
|
+
}
|
|
59160
59076
|
|
|
59161
|
-
|
|
59077
|
+
if (!seq) seq = "Unknown sequence";
|
|
59078
|
+
Alert.presentAlert(seq);
|
|
59079
|
+
}
|
|
59080
|
+
}];
|
|
59162
59081
|
|
|
59163
|
-
if (
|
|
59164
|
-
|
|
59082
|
+
if (isSecureContext() && navigator.clipboard !== undefined) {
|
|
59083
|
+
list.push({
|
|
59165
59084
|
label: 'Copy feature sequence',
|
|
59166
59085
|
click: async () => {
|
|
59167
59086
|
let seq = await this.browser.genome.getSequence(f.chr, f.start, f.end);
|
|
@@ -59170,14 +59089,21 @@
|
|
|
59170
59089
|
seq = reverseComplementSequence(seq);
|
|
59171
59090
|
}
|
|
59172
59091
|
|
|
59173
|
-
|
|
59092
|
+
try {
|
|
59093
|
+
await navigator.clipboard.writeText(seq);
|
|
59094
|
+
} catch (e) {
|
|
59095
|
+
console.error(e);
|
|
59096
|
+
Alert.presentAlert(`error copying sequence to clipboard ${e}`);
|
|
59097
|
+
}
|
|
59174
59098
|
}
|
|
59175
|
-
}
|
|
59099
|
+
});
|
|
59176
59100
|
}
|
|
59177
|
-
} // Either not a secure context (i.e. http: protocol), or feature is too long
|
|
59178
|
-
|
|
59179
59101
|
|
|
59180
|
-
|
|
59102
|
+
list.push('<hr/>');
|
|
59103
|
+
return list;
|
|
59104
|
+
} else {
|
|
59105
|
+
return undefined;
|
|
59106
|
+
}
|
|
59181
59107
|
}
|
|
59182
59108
|
|
|
59183
59109
|
description() {
|
|
@@ -59516,7 +59442,7 @@
|
|
|
59516
59442
|
}
|
|
59517
59443
|
}
|
|
59518
59444
|
|
|
59519
|
-
supportsWholeGenome() {
|
|
59445
|
+
get supportsWholeGenome() {
|
|
59520
59446
|
return !this.config.indexURL && this.config.supportsWholeGenome !== false;
|
|
59521
59447
|
}
|
|
59522
59448
|
/**
|
|
@@ -60075,7 +60001,7 @@
|
|
|
60075
60001
|
}];
|
|
60076
60002
|
}
|
|
60077
60003
|
|
|
60078
|
-
supportsWholeGenome() {
|
|
60004
|
+
get supportsWholeGenome() {
|
|
60079
60005
|
return (this.config.indexed === false || !this.config.indexURL) && this.config.supportsWholeGenome !== false;
|
|
60080
60006
|
}
|
|
60081
60007
|
|
|
@@ -60295,7 +60221,7 @@
|
|
|
60295
60221
|
}
|
|
60296
60222
|
}
|
|
60297
60223
|
|
|
60298
|
-
supportsWholeGenome() {
|
|
60224
|
+
get supportsWholeGenome() {
|
|
60299
60225
|
return this.tracks.every(track => track.supportsWholeGenome());
|
|
60300
60226
|
}
|
|
60301
60227
|
|
|
@@ -60433,7 +60359,7 @@
|
|
|
60433
60359
|
return this;
|
|
60434
60360
|
}
|
|
60435
60361
|
|
|
60436
|
-
supportsWholeGenome() {
|
|
60362
|
+
get supportsWholeGenome() {
|
|
60437
60363
|
return true;
|
|
60438
60364
|
}
|
|
60439
60365
|
|
|
@@ -60854,7 +60780,7 @@
|
|
|
60854
60780
|
items = items.concat(MenuUtils.numericDataMenuItems(this.trackView));
|
|
60855
60781
|
}
|
|
60856
60782
|
|
|
60857
|
-
if (this.browser.circularView
|
|
60783
|
+
if (this.browser.circularView) {
|
|
60858
60784
|
items.push('<hr/>');
|
|
60859
60785
|
items.push({
|
|
60860
60786
|
label: 'Add interactions to circular view',
|
|
@@ -60871,7 +60797,7 @@
|
|
|
60871
60797
|
|
|
60872
60798
|
contextMenuItemList(clickState) {
|
|
60873
60799
|
// Experimental JBrowse feature
|
|
60874
|
-
if (this.browser.circularView
|
|
60800
|
+
if (this.browser.circularView) {
|
|
60875
60801
|
const viewport = clickState.viewport;
|
|
60876
60802
|
const list = [];
|
|
60877
60803
|
list.push({
|
|
@@ -60897,7 +60823,6 @@
|
|
|
60897
60823
|
|
|
60898
60824
|
const inView = cachedFeatures.filter(f => f.drawState);
|
|
60899
60825
|
if (inView.length === 0) return;
|
|
60900
|
-
this.browser.circularViewVisible = true;
|
|
60901
60826
|
const chords = makeBedPEChords(inView);
|
|
60902
60827
|
sendChords(chords, this, refFrame, 0.5); //
|
|
60903
60828
|
//
|
|
@@ -61368,7 +61293,7 @@
|
|
|
61368
61293
|
return this;
|
|
61369
61294
|
}
|
|
61370
61295
|
|
|
61371
|
-
supportsWholeGenome() {
|
|
61296
|
+
get supportsWholeGenome() {
|
|
61372
61297
|
return this.config.indexed === false || this.config.supportsWholeGenome === true;
|
|
61373
61298
|
}
|
|
61374
61299
|
|
|
@@ -61859,7 +61784,7 @@
|
|
|
61859
61784
|
} // Experimental JBrowse circular view integration
|
|
61860
61785
|
|
|
61861
61786
|
|
|
61862
|
-
if (this.browser.circularView
|
|
61787
|
+
if (this.browser.circularView) {
|
|
61863
61788
|
menuItems.push('<hr>');
|
|
61864
61789
|
menuItems.push({
|
|
61865
61790
|
label: 'Add SVs to circular view',
|
|
@@ -61877,7 +61802,7 @@
|
|
|
61877
61802
|
|
|
61878
61803
|
contextMenuItemList(clickState) {
|
|
61879
61804
|
// Experimental JBrowse circular view integration
|
|
61880
|
-
if (this.browser.circularView
|
|
61805
|
+
if (this.browser.circularView) {
|
|
61881
61806
|
const viewport = clickState.viewport;
|
|
61882
61807
|
const list = [];
|
|
61883
61808
|
list.push({
|
|
@@ -62407,7 +62332,7 @@
|
|
|
62407
62332
|
return this;
|
|
62408
62333
|
}
|
|
62409
62334
|
|
|
62410
|
-
supportsWholeGenome() {
|
|
62335
|
+
get supportsWholeGenome() {
|
|
62411
62336
|
return true;
|
|
62412
62337
|
}
|
|
62413
62338
|
|
|
@@ -62973,7 +62898,7 @@
|
|
|
62973
62898
|
return items;
|
|
62974
62899
|
}
|
|
62975
62900
|
|
|
62976
|
-
supportsWholeGenome() {
|
|
62901
|
+
get supportsWholeGenome() {
|
|
62977
62902
|
return false;
|
|
62978
62903
|
}
|
|
62979
62904
|
|
|
@@ -63334,12 +63259,15 @@
|
|
|
63334
63259
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
63335
63260
|
* THE SOFTWARE.
|
|
63336
63261
|
*/
|
|
63262
|
+
/**
|
|
63263
|
+
* Class represents an ideogram of a chromsome cytobands. It is used for the header of a track panel.
|
|
63264
|
+
*
|
|
63265
|
+
*/
|
|
63337
63266
|
|
|
63338
63267
|
class IdeogramTrack {
|
|
63339
63268
|
constructor(browser) {
|
|
63340
63269
|
this.browser = browser;
|
|
63341
63270
|
this.type = 'ideogram';
|
|
63342
|
-
this.id = this.type;
|
|
63343
63271
|
this.height = 16;
|
|
63344
63272
|
this.order = Number.MIN_SAFE_INTEGER;
|
|
63345
63273
|
this.disableButtons = true;
|
|
@@ -63599,7 +63527,7 @@
|
|
|
63599
63527
|
return this;
|
|
63600
63528
|
}
|
|
63601
63529
|
|
|
63602
|
-
supportsWholeGenome() {
|
|
63530
|
+
get supportsWholeGenome() {
|
|
63603
63531
|
return false;
|
|
63604
63532
|
}
|
|
63605
63533
|
|
|
@@ -64640,23 +64568,6 @@
|
|
|
64640
64568
|
});
|
|
64641
64569
|
}
|
|
64642
64570
|
|
|
64643
|
-
function adjustReferenceFrame(scaleFactor, referenceFrame, viewportWidth, alignmentStart, alignmentLength) {
|
|
64644
|
-
referenceFrame.bpPerPixel *= scaleFactor;
|
|
64645
|
-
const alignmentEE = alignmentStart + alignmentLength;
|
|
64646
|
-
const alignmentCC = (alignmentStart + alignmentEE) / 2;
|
|
64647
|
-
referenceFrame.start = alignmentCC - referenceFrame.bpPerPixel * (viewportWidth / 2);
|
|
64648
|
-
referenceFrame.end = referenceFrame.start + referenceFrame.bpPerPixel * viewportWidth;
|
|
64649
|
-
referenceFrame.locusSearchString = referenceFrame.getLocusString();
|
|
64650
|
-
}
|
|
64651
|
-
|
|
64652
|
-
function createReferenceFrameWithAlignment(genome, chromosomeName, bpp, viewportWidth, alignmentStart, alignmentLength) {
|
|
64653
|
-
const alignmentEE = alignmentStart + alignmentLength;
|
|
64654
|
-
const alignmentCC = (alignmentStart + alignmentEE) / 2;
|
|
64655
|
-
const ss = alignmentCC - bpp * (viewportWidth / 2);
|
|
64656
|
-
const ee = ss + bpp * viewportWidth;
|
|
64657
|
-
return new ReferenceFrame(genome, chromosomeName, ss, ee, bpp);
|
|
64658
|
-
}
|
|
64659
|
-
|
|
64660
64571
|
const defaultNucleotideColors = {
|
|
64661
64572
|
"A": "rgb( 0, 200, 0)",
|
|
64662
64573
|
"C": "rgb( 0,0,200)",
|
|
@@ -65703,6 +65614,65 @@
|
|
|
65703
65614
|
button.addEventListener('click', () => browser.saveSVGtoFile({}));
|
|
65704
65615
|
};
|
|
65705
65616
|
|
|
65617
|
+
const viewportColumnManager = {
|
|
65618
|
+
createColumns: (columnContainer, count) => {
|
|
65619
|
+
for (let i = 0; i < count; i++) {
|
|
65620
|
+
if (0 === i) {
|
|
65621
|
+
createColumn(columnContainer, 'igv-column');
|
|
65622
|
+
} else {
|
|
65623
|
+
columnContainer.appendChild(div$1({
|
|
65624
|
+
class: 'igv-column-shim'
|
|
65625
|
+
}));
|
|
65626
|
+
createColumn(columnContainer, 'igv-column');
|
|
65627
|
+
}
|
|
65628
|
+
}
|
|
65629
|
+
},
|
|
65630
|
+
removeColumnAtIndex: (i, column) => {
|
|
65631
|
+
const shim = 0 === i ? column.nextElementSibling : column.previousElementSibling;
|
|
65632
|
+
column.remove();
|
|
65633
|
+
shim.remove();
|
|
65634
|
+
},
|
|
65635
|
+
insertAfter: referenceElement => {
|
|
65636
|
+
const shim = div$1({
|
|
65637
|
+
class: 'igv-column-shim'
|
|
65638
|
+
});
|
|
65639
|
+
insertElementAfter(shim, referenceElement);
|
|
65640
|
+
const column = div$1({
|
|
65641
|
+
class: 'igv-column'
|
|
65642
|
+
});
|
|
65643
|
+
insertElementAfter(column, shim);
|
|
65644
|
+
return column;
|
|
65645
|
+
},
|
|
65646
|
+
insertBefore: (referenceElement, count) => {
|
|
65647
|
+
for (let i = 0; i < count; i++) {
|
|
65648
|
+
const column = div$1({
|
|
65649
|
+
class: 'igv-column'
|
|
65650
|
+
});
|
|
65651
|
+
insertElementBefore(column, referenceElement);
|
|
65652
|
+
|
|
65653
|
+
if (count > 1 && i > 0) {
|
|
65654
|
+
const columnShim = div$1({
|
|
65655
|
+
class: 'igv-column-shim'
|
|
65656
|
+
});
|
|
65657
|
+
insertElementBefore(columnShim, column);
|
|
65658
|
+
}
|
|
65659
|
+
}
|
|
65660
|
+
},
|
|
65661
|
+
indexOfColumn: (columnContainer, column) => {
|
|
65662
|
+
const allColumns = columnContainer.querySelectorAll('.igv-column');
|
|
65663
|
+
|
|
65664
|
+
for (let i = 0; i < allColumns.length; i++) {
|
|
65665
|
+
const c = allColumns[i];
|
|
65666
|
+
|
|
65667
|
+
if (c === column) {
|
|
65668
|
+
return i;
|
|
65669
|
+
}
|
|
65670
|
+
}
|
|
65671
|
+
|
|
65672
|
+
return undefined;
|
|
65673
|
+
}
|
|
65674
|
+
};
|
|
65675
|
+
|
|
65706
65676
|
/*
|
|
65707
65677
|
* The MIT License (MIT)
|
|
65708
65678
|
*
|
|
@@ -65953,7 +65923,7 @@
|
|
|
65953
65923
|
}
|
|
65954
65924
|
}
|
|
65955
65925
|
|
|
65956
|
-
supportsWholeGenome() {
|
|
65926
|
+
get supportsWholeGenome() {
|
|
65957
65927
|
return true;
|
|
65958
65928
|
}
|
|
65959
65929
|
|
|
@@ -66485,7 +66455,9 @@
|
|
|
66485
66455
|
// deferred because ideogram and ruler are treated as "tracks", and tracks require a reference frame
|
|
66486
66456
|
|
|
66487
66457
|
if (false !== session.showIdeogram) {
|
|
66488
|
-
|
|
66458
|
+
const ideogramTrack = new IdeogramTrack(this);
|
|
66459
|
+
ideogramTrack.id = 'ideogram';
|
|
66460
|
+
this.trackViews.push(new TrackView(this, this.columnContainer, ideogramTrack));
|
|
66489
66461
|
}
|
|
66490
66462
|
|
|
66491
66463
|
if (false !== session.showRuler) {
|
|
@@ -66535,9 +66507,9 @@
|
|
|
66535
66507
|
}
|
|
66536
66508
|
}
|
|
66537
66509
|
|
|
66538
|
-
await this.loadTrackList(trackConfigurations); // The ruler
|
|
66510
|
+
await this.loadTrackList(trackConfigurations); // The ruler and ideogram tracks are not explicitly loaded, but needs updated nonetheless.
|
|
66539
66511
|
|
|
66540
|
-
for (let rtv of this.trackViews.filter(tv => tv.track.type === 'ruler')) {
|
|
66512
|
+
for (let rtv of this.trackViews.filter(tv => tv.track.type === 'ruler' || tv.track.type === 'ideogram')) {
|
|
66541
66513
|
rtv.updateViews();
|
|
66542
66514
|
}
|
|
66543
66515
|
|
|
@@ -67077,10 +67049,11 @@
|
|
|
67077
67049
|
this.navbarManager.navbarDidResize(this.$navigation.width(), isWGV);
|
|
67078
67050
|
}
|
|
67079
67051
|
|
|
67080
|
-
|
|
67052
|
+
resize.call(this);
|
|
67053
|
+
await this.updateViews();
|
|
67081
67054
|
}
|
|
67082
67055
|
|
|
67083
|
-
async updateViews(
|
|
67056
|
+
async updateViews() {
|
|
67084
67057
|
const trackViews = this.trackViews;
|
|
67085
67058
|
this.updateLocusSearchWidget();
|
|
67086
67059
|
|
|
@@ -67091,7 +67064,7 @@
|
|
|
67091
67064
|
|
|
67092
67065
|
if (this.dragObject) {
|
|
67093
67066
|
for (let trackView of trackViews) {
|
|
67094
|
-
await trackView.updateViews(
|
|
67067
|
+
await trackView.updateViews();
|
|
67095
67068
|
}
|
|
67096
67069
|
} else {
|
|
67097
67070
|
// Group autoscale
|
|
@@ -67140,14 +67113,14 @@
|
|
|
67140
67113
|
for (let trackView of groupTrackViews) {
|
|
67141
67114
|
trackView.track.dataRange = dataRange;
|
|
67142
67115
|
trackView.track.autoscale = false;
|
|
67143
|
-
p.push(trackView.updateViews(
|
|
67116
|
+
p.push(trackView.updateViews());
|
|
67144
67117
|
}
|
|
67145
67118
|
|
|
67146
67119
|
await Promise.all(p);
|
|
67147
67120
|
}
|
|
67148
67121
|
}
|
|
67149
67122
|
|
|
67150
|
-
await Promise.all(otherTracks.map(tv => tv.updateViews(
|
|
67123
|
+
await Promise.all(otherTracks.map(tv => tv.updateViews())); // for (let trackView of otherTracks) {
|
|
67151
67124
|
// await trackView.updateViews(force);
|
|
67152
67125
|
// }
|
|
67153
67126
|
}
|
|
@@ -67216,42 +67189,6 @@
|
|
|
67216
67189
|
referenceFrame.zoomWithScaleFactor(this, scaleFactor, viewportWidth, centerBPOrUndefined);
|
|
67217
67190
|
}
|
|
67218
67191
|
}
|
|
67219
|
-
|
|
67220
|
-
async presentMultiLocusPanel(alignment, referenceFrameLeft) {
|
|
67221
|
-
// account for reduced viewport width as a result of adding right mate pair panel
|
|
67222
|
-
const viewportWidth = this.calculateViewportWidth(1 + this.referenceFrameList.length);
|
|
67223
|
-
const scaleFactor = this.calculateViewportWidth(this.referenceFrameList.length) / this.calculateViewportWidth(1 + this.referenceFrameList.length);
|
|
67224
|
-
adjustReferenceFrame(scaleFactor, referenceFrameLeft, viewportWidth, alignment.start, alignment.lengthOnRef); // create right mate pair reference frame
|
|
67225
|
-
|
|
67226
|
-
const mateChrName = this.genome.getChromosomeName(alignment.mate.chr);
|
|
67227
|
-
const referenceFrameRight = createReferenceFrameWithAlignment(this.genome, mateChrName, referenceFrameLeft.bpPerPixel, viewportWidth, alignment.mate.position, alignment.lengthOnRef); // add right mate panel beside left mate panel
|
|
67228
|
-
|
|
67229
|
-
const indexLeft = this.referenceFrameList.indexOf(referenceFrameLeft);
|
|
67230
|
-
const indexRight = 1 + this.referenceFrameList.indexOf(referenceFrameLeft);
|
|
67231
|
-
const {
|
|
67232
|
-
$viewport
|
|
67233
|
-
} = this.trackViews[0].viewports[indexLeft];
|
|
67234
|
-
const viewportColumn = viewportColumnManager.insertAfter($viewport.get(0).parentElement);
|
|
67235
|
-
|
|
67236
|
-
if (indexRight === this.referenceFrameList.length) {
|
|
67237
|
-
this.referenceFrameList.push(referenceFrameRight);
|
|
67238
|
-
|
|
67239
|
-
for (let trackView of this.trackViews) {
|
|
67240
|
-
const viewport = createViewport(trackView, viewportColumn, referenceFrameRight);
|
|
67241
|
-
trackView.viewports.push(viewport);
|
|
67242
|
-
}
|
|
67243
|
-
} else {
|
|
67244
|
-
this.referenceFrameList.splice(indexRight, 0, referenceFrameRight);
|
|
67245
|
-
|
|
67246
|
-
for (let trackView of this.trackViews) {
|
|
67247
|
-
const viewport = createViewport(trackView, viewportColumn, referenceFrameRight);
|
|
67248
|
-
trackView.viewports.splice(indexRight, 0, viewport);
|
|
67249
|
-
}
|
|
67250
|
-
}
|
|
67251
|
-
|
|
67252
|
-
this.centerLineList = this.createCenterLineList(this.columnContainer);
|
|
67253
|
-
await resize.call(this);
|
|
67254
|
-
}
|
|
67255
67192
|
/**
|
|
67256
67193
|
* Add a new multi-locus panel for the specified region
|
|
67257
67194
|
* @param chr
|
|
@@ -67298,6 +67235,7 @@
|
|
|
67298
67235
|
|
|
67299
67236
|
this.centerLineList = this.createCenterLineList(this.columnContainer);
|
|
67300
67237
|
resize.call(this);
|
|
67238
|
+
await this.updateViews(true);
|
|
67301
67239
|
}
|
|
67302
67240
|
|
|
67303
67241
|
async removeMultiLocusPanel(referenceFrame) {
|
|
@@ -67635,11 +67573,6 @@
|
|
|
67635
67573
|
const surl = (idx > 0 ? path.substring(0, idx) : path) + "?sessionURL=blob:" + this.compressedSession();
|
|
67636
67574
|
return surl;
|
|
67637
67575
|
}
|
|
67638
|
-
|
|
67639
|
-
currentReferenceFrames() {
|
|
67640
|
-
const anyTrackView = this.trackViews[0];
|
|
67641
|
-
return anyTrackView.viewports.map(vp => vp.referenceFrame);
|
|
67642
|
-
}
|
|
67643
67576
|
/**
|
|
67644
67577
|
* Record a mouse click on a specific viewport. This might be the start of a drag operation. Dragging
|
|
67645
67578
|
* (panning) is handled here so that the mouse can move out of a specific viewport (e.g. stray into another
|
|
@@ -67674,10 +67607,22 @@
|
|
|
67674
67607
|
this.fireEvent('trackdragend');
|
|
67675
67608
|
}
|
|
67676
67609
|
}
|
|
67610
|
+
/**
|
|
67611
|
+
* Track drag here refers to vertical dragging to reorder tracks, not horizontal panning.
|
|
67612
|
+
*
|
|
67613
|
+
* @param trackView
|
|
67614
|
+
*/
|
|
67615
|
+
|
|
67677
67616
|
|
|
67678
67617
|
startTrackDrag(trackView) {
|
|
67679
67618
|
this.dragTrack = trackView;
|
|
67680
67619
|
}
|
|
67620
|
+
/**
|
|
67621
|
+
* Track drag here refers to vertical dragging to reorder tracks, not horizontal panning.
|
|
67622
|
+
*
|
|
67623
|
+
* @param dragDestination
|
|
67624
|
+
*/
|
|
67625
|
+
|
|
67681
67626
|
|
|
67682
67627
|
updateTrackDrag(dragDestination) {
|
|
67683
67628
|
if (dragDestination && this.dragTrack) {
|
|
@@ -67825,6 +67770,8 @@
|
|
|
67825
67770
|
}
|
|
67826
67771
|
|
|
67827
67772
|
createCircularView(container, show) {
|
|
67773
|
+
show = show === true; // convert undefined to boolean
|
|
67774
|
+
|
|
67828
67775
|
this.circularView = createCircularView(container, this);
|
|
67829
67776
|
this.circularViewControl = new CircularViewControl(this.$toggle_button_container.get(0), this);
|
|
67830
67777
|
this.circularView.setAssembly({
|
|
@@ -67832,7 +67779,8 @@
|
|
|
67832
67779
|
id: this.genome.id,
|
|
67833
67780
|
chromosomes: makeCircViewChromosomes(this.genome)
|
|
67834
67781
|
});
|
|
67835
|
-
this.circularViewVisible = show
|
|
67782
|
+
this.circularViewVisible = show;
|
|
67783
|
+
return this.circularView;
|
|
67836
67784
|
}
|
|
67837
67785
|
|
|
67838
67786
|
get circularViewVisible() {
|
|
@@ -67885,7 +67833,8 @@
|
|
|
67885
67833
|
}
|
|
67886
67834
|
}
|
|
67887
67835
|
|
|
67888
|
-
this.updateUIWithReferenceFrameList();
|
|
67836
|
+
this.updateUIWithReferenceFrameList(); //TODO -- update view only if needed. Reducing size never needed. Increasing size maybe
|
|
67837
|
+
|
|
67889
67838
|
await this.updateViews(true);
|
|
67890
67839
|
}
|
|
67891
67840
|
|