igv 3.0.1 → 3.0.2
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 -10
- package/dist/igv.esm.js +220 -179
- package/dist/igv.esm.min.js +9 -9
- package/dist/igv.esm.min.js.map +1 -1
- package/dist/igv.js +220 -179
- package/dist/igv.min.js +9 -9
- package/dist/igv.min.js.map +1 -1
- package/package.json +1 -1
package/dist/igv.js
CHANGED
|
@@ -19021,13 +19021,13 @@
|
|
|
19021
19021
|
if (Array.isArray(trackViewOrTrackViewList)) {
|
|
19022
19022
|
dataRange = { min: Number.MAX_SAFE_INTEGER, max:-Number.MAX_SAFE_INTEGER };
|
|
19023
19023
|
for (const trackView of trackViewOrTrackViewList) {
|
|
19024
|
-
if (trackView.dataRange) {
|
|
19025
|
-
dataRange.min = Math.min(trackView.dataRange.min, dataRange.min);
|
|
19026
|
-
dataRange.max = Math.max(trackView.dataRange.max, dataRange.max);
|
|
19024
|
+
if (trackView.track.dataRange) {
|
|
19025
|
+
dataRange.min = Math.min(trackView.track.dataRange.min, dataRange.min);
|
|
19026
|
+
dataRange.max = Math.max(trackView.track.dataRange.max, dataRange.max);
|
|
19027
19027
|
}
|
|
19028
19028
|
}
|
|
19029
19029
|
} else {
|
|
19030
|
-
dataRange = trackViewOrTrackViewList.dataRange;
|
|
19030
|
+
dataRange = trackViewOrTrackViewList.track.dataRange;
|
|
19031
19031
|
}
|
|
19032
19032
|
|
|
19033
19033
|
if (dataRange) {
|
|
@@ -19069,7 +19069,7 @@
|
|
|
19069
19069
|
} else {
|
|
19070
19070
|
const list = Array.isArray(trackViewOfTrackViewList) ? trackViewOfTrackViewList : [ trackViewOfTrackViewList ];
|
|
19071
19071
|
for (const trackView of list) {
|
|
19072
|
-
trackView.
|
|
19072
|
+
trackView.track.setDataRange({ min, max });
|
|
19073
19073
|
}
|
|
19074
19074
|
|
|
19075
19075
|
}
|
|
@@ -26702,6 +26702,14 @@
|
|
|
26702
26702
|
return menuItems
|
|
26703
26703
|
}
|
|
26704
26704
|
|
|
26705
|
+
setDataRange({ min, max }) {
|
|
26706
|
+
|
|
26707
|
+
this.dataRange = { min, max };
|
|
26708
|
+
this.autoscale = false;
|
|
26709
|
+
this.autoscaleGroup = undefined;
|
|
26710
|
+
this.trackView.repaintViews();
|
|
26711
|
+
}
|
|
26712
|
+
|
|
26705
26713
|
/**
|
|
26706
26714
|
* Return the first feature in this track whose start position is > position
|
|
26707
26715
|
* @param chr
|
|
@@ -27069,7 +27077,7 @@
|
|
|
27069
27077
|
this.filter = tokens[6];
|
|
27070
27078
|
this.info = {};
|
|
27071
27079
|
const infoStr = tokens[7];
|
|
27072
|
-
if (infoStr) {
|
|
27080
|
+
if (infoStr && infoStr !== '.') {
|
|
27073
27081
|
for (let elem of infoStr.split(';')) {
|
|
27074
27082
|
var element = elem.split('=');
|
|
27075
27083
|
this.info[element[0]] = element[1];
|
|
@@ -27228,9 +27236,10 @@
|
|
|
27228
27236
|
}
|
|
27229
27237
|
}
|
|
27230
27238
|
|
|
27231
|
-
|
|
27239
|
+
const infoKeys = Object.keys(this.info);
|
|
27240
|
+
if (this.info && infoKeys.length > 0) {
|
|
27232
27241
|
fields.push({html: '<hr style="border-top: dotted 1px;border-color: #c9c3ba" />'});
|
|
27233
|
-
for (let key of
|
|
27242
|
+
for (let key of infoKeys) {
|
|
27234
27243
|
fields.push({name: key, value: arrayToString(decodeURIComponent(this.info[key]))});
|
|
27235
27244
|
}
|
|
27236
27245
|
}
|
|
@@ -27297,7 +27306,7 @@
|
|
|
27297
27306
|
}
|
|
27298
27307
|
|
|
27299
27308
|
getAttributeValue(key) {
|
|
27300
|
-
|
|
27309
|
+
return this.mate.getAttributeValue(key)
|
|
27301
27310
|
}
|
|
27302
27311
|
|
|
27303
27312
|
getInfo(tag) {
|
|
@@ -27320,7 +27329,7 @@
|
|
|
27320
27329
|
popupData.push({name: 'Pos', value: `${numberFormatter$1(this.pos)}`});
|
|
27321
27330
|
popupData.push({html: '<hr style="border-top: dotted 1px;border-color: #c9c3ba" />'});
|
|
27322
27331
|
popupData.push("SV");
|
|
27323
|
-
popupData.push(...
|
|
27332
|
+
popupData.push(...this.mate.popupData(genomicLocation, genomeId));
|
|
27324
27333
|
|
|
27325
27334
|
return popupData
|
|
27326
27335
|
}
|
|
@@ -31216,7 +31225,7 @@
|
|
|
31216
31225
|
|
|
31217
31226
|
function getDecoder(definedFieldCount, fieldCount, autoSql, format) {
|
|
31218
31227
|
|
|
31219
|
-
if ("biginteract" === format || (autoSql && ('chromatinInteract' === autoSql.table
|
|
31228
|
+
if ("biginteract" === format || (autoSql && ('chromatinInteract' === autoSql.table || 'interact' === autoSql.table))) {
|
|
31220
31229
|
return decodeInteract
|
|
31221
31230
|
} else {
|
|
31222
31231
|
const standardFieldCount = definedFieldCount - 3;
|
|
@@ -34422,7 +34431,7 @@
|
|
|
34422
34431
|
}
|
|
34423
34432
|
|
|
34424
34433
|
|
|
34425
|
-
if (!this.
|
|
34434
|
+
if (!this.isMergedTrack) {
|
|
34426
34435
|
IGVGraphics.fillRect(context, 0, options.pixelTop, pixelWidth, pixelHeight, {'fillStyle': "rgb(255, 255, 255)"});
|
|
34427
34436
|
}
|
|
34428
34437
|
|
|
@@ -41611,39 +41620,36 @@
|
|
|
41611
41620
|
* THE SOFTWARE.
|
|
41612
41621
|
*/
|
|
41613
41622
|
|
|
41614
|
-
|
|
41615
41623
|
/**
|
|
41616
|
-
* Represents 2 or more
|
|
41624
|
+
* Represents 2 or more tracks overlaid on a common viewport.
|
|
41617
41625
|
*/
|
|
41618
41626
|
class MergedTrack extends TrackBase {
|
|
41619
41627
|
|
|
41620
41628
|
static defaults = {
|
|
41629
|
+
autoscale: undefined,
|
|
41621
41630
|
alpha: 0.5,
|
|
41622
41631
|
height: 50
|
|
41623
41632
|
}
|
|
41624
41633
|
|
|
41625
|
-
constructor(config, browser) {
|
|
41634
|
+
constructor(config, browser, tracks) {
|
|
41626
41635
|
super(config, browser);
|
|
41627
41636
|
this.type = "merged";
|
|
41628
|
-
this.featureType = "numeric";
|
|
41629
41637
|
this.paintAxis = paintAxis;
|
|
41630
41638
|
this.graphType = config.graphType;
|
|
41631
|
-
|
|
41632
|
-
|
|
41633
|
-
|
|
41634
|
-
|
|
41635
|
-
throw Error("Error: no tracks defined for merged track" + config)
|
|
41639
|
+
if (tracks) {
|
|
41640
|
+
this.tracks = tracks; // Dynamic creation, actual track objects (not configurations)
|
|
41641
|
+
} else {
|
|
41642
|
+
this.tracks = [];
|
|
41636
41643
|
}
|
|
41637
|
-
super.init(config);
|
|
41638
41644
|
}
|
|
41639
41645
|
|
|
41646
|
+
|
|
41640
41647
|
async postInit() {
|
|
41641
41648
|
|
|
41642
|
-
this.tracks = [];
|
|
41643
41649
|
if (this.config.tracks) {
|
|
41644
|
-
//
|
|
41650
|
+
// Track configurations, this indicates a configured merged track as opposed to dynamic merge through the UI
|
|
41651
|
+
// Actual track objects need to be created.
|
|
41645
41652
|
for (let tconf of this.config.tracks) {
|
|
41646
|
-
tconf.isMergedTrack = true;
|
|
41647
41653
|
const t = await this.browser.createTrack(tconf);
|
|
41648
41654
|
if (t) {
|
|
41649
41655
|
this.tracks.push(t);
|
|
@@ -41654,24 +41660,27 @@
|
|
|
41654
41660
|
await t.postInit();
|
|
41655
41661
|
}
|
|
41656
41662
|
}
|
|
41657
|
-
//
|
|
41658
|
-
|
|
41659
|
-
|
|
41660
|
-
|
|
41661
|
-
this.dataRange = {
|
|
41662
|
-
min: this.config.min || 0,
|
|
41663
|
-
max: this.config.max
|
|
41664
|
-
};
|
|
41665
|
-
} else {
|
|
41666
|
-
this.autoscale = !this.tracks.every(t => t.config.autoscale || t.config.max !== undefined);
|
|
41663
|
+
// Default to autoscale unless scale if range or autoscale is not otherwise defined
|
|
41664
|
+
const allTracksSpecified = this.config.tracks.every(config => config.autoscale !== undefined || config.max !== undefined);
|
|
41665
|
+
if (!allTracksSpecified) {
|
|
41666
|
+
this.config.autoscale = this.config.max === undefined;
|
|
41667
41667
|
}
|
|
41668
|
-
} else {
|
|
41669
|
-
// Dynamic merged track
|
|
41670
|
-
this.tracks = this.config._tracks;
|
|
41671
|
-
this.autoscale = false;
|
|
41672
|
-
delete this.config._tracks;
|
|
41673
41668
|
}
|
|
41674
41669
|
|
|
41670
|
+
// Mark constitutive tracks as merged.
|
|
41671
|
+
for (let t of this.tracks) t.isMergedTrack = true;
|
|
41672
|
+
|
|
41673
|
+
// Explicit settings -- these will override any individual track settings
|
|
41674
|
+
if(this.config.autoscale) {
|
|
41675
|
+
this.autoscale = this.config.autoscale;
|
|
41676
|
+
} else if (this.config.max !== undefined) {
|
|
41677
|
+
this.setDataRange ({
|
|
41678
|
+
min: this.config.min || 0,
|
|
41679
|
+
max: this.config.max
|
|
41680
|
+
});
|
|
41681
|
+
}
|
|
41682
|
+
|
|
41683
|
+
|
|
41675
41684
|
if (this.config.flipAxis !== undefined) {
|
|
41676
41685
|
for (let t of this.tracks) t.flipAxis = this.config.flipAxis;
|
|
41677
41686
|
}
|
|
@@ -41681,25 +41690,28 @@
|
|
|
41681
41690
|
}
|
|
41682
41691
|
|
|
41683
41692
|
this.resolutionAware = this.tracks.some(t => t.resolutionAware);
|
|
41684
|
-
|
|
41685
41693
|
}
|
|
41686
41694
|
|
|
41687
41695
|
set flipAxis(b) {
|
|
41688
41696
|
this.config.flipAxis = b;
|
|
41689
|
-
for (let t of this.tracks)
|
|
41697
|
+
for (let t of numericTracks(this.tracks)) {
|
|
41698
|
+
t.flipAxis = b;
|
|
41699
|
+
}
|
|
41690
41700
|
}
|
|
41691
41701
|
|
|
41692
41702
|
get flipAxis() {
|
|
41693
|
-
return this.tracks.every(t => t.flipAxis)
|
|
41703
|
+
return numericTracks(this.tracks).every(t => t.flipAxis)
|
|
41694
41704
|
}
|
|
41695
41705
|
|
|
41696
41706
|
set logScale(b) {
|
|
41697
41707
|
this.config.logScale = b;
|
|
41698
|
-
for (let t of this.tracks)
|
|
41708
|
+
for (let t of numericTracks(this.tracks)) {
|
|
41709
|
+
t.logScale = b;
|
|
41710
|
+
}
|
|
41699
41711
|
}
|
|
41700
41712
|
|
|
41701
41713
|
get logScale() {
|
|
41702
|
-
return this.tracks.every(t => t.logScale)
|
|
41714
|
+
return numericTracks(this.tracks).every(t => t.logScale)
|
|
41703
41715
|
}
|
|
41704
41716
|
|
|
41705
41717
|
get height() {
|
|
@@ -41717,49 +41729,76 @@
|
|
|
41717
41729
|
}
|
|
41718
41730
|
}
|
|
41719
41731
|
|
|
41720
|
-
|
|
41721
|
-
|
|
41722
|
-
if
|
|
41723
|
-
|
|
41732
|
+
set autoscale(b) {
|
|
41733
|
+
this._autoscale = b;
|
|
41734
|
+
if(b === false && this.tracks) {
|
|
41735
|
+
for(let t of this.tracks) t.autoscale = false;
|
|
41724
41736
|
}
|
|
41737
|
+
}
|
|
41725
41738
|
|
|
41726
|
-
|
|
41727
|
-
|
|
41728
|
-
|
|
41729
|
-
}
|
|
41739
|
+
get autoscale() {
|
|
41740
|
+
return this._autoscale
|
|
41741
|
+
}
|
|
41730
41742
|
|
|
41731
|
-
|
|
41732
|
-
|
|
41733
|
-
|
|
41734
|
-
|
|
41743
|
+
/**
|
|
41744
|
+
* Set the data range of all constitutive numeric tracks. This method is called from the menu item, i.e. an explicit
|
|
41745
|
+
* setting, so it should disable autoscale as well.
|
|
41746
|
+
*
|
|
41747
|
+
* @param min
|
|
41748
|
+
* @param max
|
|
41749
|
+
*/
|
|
41735
41750
|
|
|
41736
|
-
|
|
41737
|
-
|
|
41738
|
-
|
|
41751
|
+
setDataRange({min, max}) {
|
|
41752
|
+
this.autoscale = false;
|
|
41753
|
+
for (const track of numericTracks(this.tracks)) {
|
|
41754
|
+
track.dataRange = {min, max};
|
|
41755
|
+
track.autoscale = false;
|
|
41756
|
+
track.autoscaleGroup = false;
|
|
41739
41757
|
}
|
|
41758
|
+
}
|
|
41740
41759
|
|
|
41741
|
-
|
|
41760
|
+
set dataRange({min, max}) {
|
|
41761
|
+
for (const track of numericTracks(this.tracks)) {
|
|
41762
|
+
track.dataRange = {min, max};
|
|
41763
|
+
}
|
|
41742
41764
|
}
|
|
41743
41765
|
|
|
41744
|
-
|
|
41745
|
-
|
|
41746
|
-
|
|
41766
|
+
/**
|
|
41767
|
+
* Return a DataRang {min, max} if all constitutive numeric tracks have identical range. A numeric track is defined
|
|
41768
|
+
* as a track with a data range. Otherwise return undefined.
|
|
41769
|
+
*
|
|
41770
|
+
* @returns {{min: any, max: any}|undefined}
|
|
41771
|
+
*/
|
|
41772
|
+
get dataRange() {
|
|
41773
|
+
if(this.tracks) {
|
|
41774
|
+
const num = numericTracks(this.tracks);
|
|
41775
|
+
if (num.length > 0) {
|
|
41776
|
+
const firstRange = num[0].dataRange;
|
|
41777
|
+
if (num.every(t => t.dataRange && t.dataRange.min === firstRange.min && t.dataRange.max === firstRange.max)) {
|
|
41778
|
+
return firstRange
|
|
41779
|
+
}
|
|
41780
|
+
}
|
|
41747
41781
|
}
|
|
41782
|
+
return undefined
|
|
41748
41783
|
}
|
|
41749
41784
|
|
|
41785
|
+
|
|
41750
41786
|
menuItemList() {
|
|
41751
41787
|
const items = [];
|
|
41752
|
-
if (this.
|
|
41753
|
-
items.push({
|
|
41754
|
-
label: "Flip y-axis",
|
|
41755
|
-
click: function flipYAxisHandler() {
|
|
41756
|
-
this.flipAxis = !this.flipAxis;
|
|
41757
|
-
this.trackView.repaintViews();
|
|
41758
|
-
}
|
|
41759
|
-
});
|
|
41760
|
-
}
|
|
41788
|
+
if (numericTracks(this.tracks).length > 0) {
|
|
41761
41789
|
|
|
41762
|
-
|
|
41790
|
+
if (this.flipAxis !== undefined) {
|
|
41791
|
+
items.push({
|
|
41792
|
+
label: "Flip y-axis",
|
|
41793
|
+
click: function flipYAxisHandler() {
|
|
41794
|
+
this.flipAxis = !this.flipAxis;
|
|
41795
|
+
this.trackView.repaintViews();
|
|
41796
|
+
}
|
|
41797
|
+
});
|
|
41798
|
+
}
|
|
41799
|
+
|
|
41800
|
+
items.push(...this.numericDataMenuItems());
|
|
41801
|
+
}
|
|
41763
41802
|
|
|
41764
41803
|
items.push('<hr/>');
|
|
41765
41804
|
items.push(this.overlayTrackAlphaAdjustmentMenuItem());
|
|
@@ -41776,7 +41815,14 @@
|
|
|
41776
41815
|
|
|
41777
41816
|
const promises = this.tracks.map((t) => t.getFeatures(chr, bpStart, bpEnd, bpPerPixel));
|
|
41778
41817
|
const featureArrays = await Promise.all(promises);
|
|
41779
|
-
|
|
41818
|
+
|
|
41819
|
+
if (featureArrays.every((arr) => arr.length === 0)){
|
|
41820
|
+
return new MergedFeatureCollection([], [])
|
|
41821
|
+
}
|
|
41822
|
+
else {
|
|
41823
|
+
const trackNames = this.tracks.map((t) => t.name);
|
|
41824
|
+
return new MergedFeatureCollection(featureArrays, trackNames)
|
|
41825
|
+
}
|
|
41780
41826
|
}
|
|
41781
41827
|
|
|
41782
41828
|
draw(options) {
|
|
@@ -41788,11 +41834,6 @@
|
|
|
41788
41834
|
trackOptions.features = mergedFeatures.featureArrays[i];
|
|
41789
41835
|
trackOptions.alpha = this.alpha;
|
|
41790
41836
|
|
|
41791
|
-
if (this.dataRange) {
|
|
41792
|
-
// Single data scale for all tracks
|
|
41793
|
-
this.tracks[i].dataRange = this.dataRange;
|
|
41794
|
-
}
|
|
41795
|
-
|
|
41796
41837
|
if (this.graphType) {
|
|
41797
41838
|
this.tracks[i].graphType = this.graphType;
|
|
41798
41839
|
}
|
|
@@ -41886,6 +41927,7 @@
|
|
|
41886
41927
|
let scaleChange;
|
|
41887
41928
|
|
|
41888
41929
|
if (this.autoscale) {
|
|
41930
|
+
// Overrides any specific track scale settings
|
|
41889
41931
|
scaleChange = true;
|
|
41890
41932
|
let allFeatures = [];
|
|
41891
41933
|
for (let visibleViewport of visibleViewports) {
|
|
@@ -41900,7 +41942,12 @@
|
|
|
41900
41942
|
allFeatures.push({value: mergedFeatureCollection.getMin(start, end)});
|
|
41901
41943
|
}
|
|
41902
41944
|
}
|
|
41903
|
-
|
|
41945
|
+
const dataRange = doAutoscale(allFeatures);
|
|
41946
|
+
for (const track of numericTracks(this.tracks)) {
|
|
41947
|
+
// Do not use this.dataRange, as that has side effects
|
|
41948
|
+
track.dataRange = dataRange;
|
|
41949
|
+
}
|
|
41950
|
+
|
|
41904
41951
|
}
|
|
41905
41952
|
} else {
|
|
41906
41953
|
// Individual track scaling
|
|
@@ -41980,6 +42027,7 @@
|
|
|
41980
42027
|
if (groupAutoscale) {
|
|
41981
42028
|
track.autoscaleGroup = name;
|
|
41982
42029
|
}
|
|
42030
|
+
track.isMergedTrack = false;
|
|
41983
42031
|
browser.addTrack(track.config, track);
|
|
41984
42032
|
}
|
|
41985
42033
|
browser.updateViews();
|
|
@@ -41993,25 +42041,30 @@
|
|
|
41993
42041
|
|
|
41994
42042
|
class MergedFeatureCollection {
|
|
41995
42043
|
|
|
41996
|
-
constructor(featureArrays) {
|
|
42044
|
+
constructor(featureArrays,trackNames) {
|
|
41997
42045
|
this.featureArrays = featureArrays;
|
|
42046
|
+
//trackNames is needed for the popup data to populate track names
|
|
42047
|
+
//preserving the order of the actual tracks
|
|
42048
|
+
this.trackNames = trackNames;
|
|
41998
42049
|
}
|
|
41999
42050
|
|
|
42000
42051
|
getMax(start, end) {
|
|
42001
42052
|
let max = -Number.MAX_VALUE;
|
|
42002
42053
|
|
|
42003
42054
|
for (let a of this.featureArrays) {
|
|
42004
|
-
|
|
42005
|
-
|
|
42006
|
-
|
|
42007
|
-
|
|
42008
|
-
|
|
42009
|
-
|
|
42010
|
-
|
|
42011
|
-
|
|
42012
|
-
|
|
42055
|
+
if (Array.isArray(a)) {
|
|
42056
|
+
for (let f of a) {
|
|
42057
|
+
if (typeof f.value === 'undefined' || Number.isNaN(f.value)) {
|
|
42058
|
+
continue
|
|
42059
|
+
}
|
|
42060
|
+
if (f.end < start) {
|
|
42061
|
+
continue
|
|
42062
|
+
}
|
|
42063
|
+
if (f.start > end) {
|
|
42064
|
+
break
|
|
42065
|
+
}
|
|
42066
|
+
max = Math.max(max, f.value);
|
|
42013
42067
|
}
|
|
42014
|
-
max = Math.max(max, f.value);
|
|
42015
42068
|
}
|
|
42016
42069
|
}
|
|
42017
42070
|
|
|
@@ -42022,15 +42075,17 @@
|
|
|
42022
42075
|
getMin(start, end) {
|
|
42023
42076
|
let min = 0;
|
|
42024
42077
|
for (let a of this.featureArrays) {
|
|
42025
|
-
|
|
42026
|
-
|
|
42027
|
-
if (f.
|
|
42028
|
-
|
|
42029
|
-
|
|
42030
|
-
|
|
42031
|
-
|
|
42078
|
+
if (Array.isArray(a)) {
|
|
42079
|
+
for (let f of a) {
|
|
42080
|
+
if (typeof f.value !== 'undefined' && !Number.isNaN(f.value)) {
|
|
42081
|
+
if (f.end < start) {
|
|
42082
|
+
continue
|
|
42083
|
+
}
|
|
42084
|
+
if (f.start > end) {
|
|
42085
|
+
break
|
|
42086
|
+
}
|
|
42087
|
+
min = Math.min(min, f.value);
|
|
42032
42088
|
}
|
|
42033
|
-
min = Math.min(min, f.value);
|
|
42034
42089
|
}
|
|
42035
42090
|
}
|
|
42036
42091
|
}
|
|
@@ -42038,6 +42093,16 @@
|
|
|
42038
42093
|
}
|
|
42039
42094
|
}
|
|
42040
42095
|
|
|
42096
|
+
/**
|
|
42097
|
+
* Heuristic for finding numeric tracks.
|
|
42098
|
+
*
|
|
42099
|
+
* @param tracks
|
|
42100
|
+
* @returns {*}
|
|
42101
|
+
*/
|
|
42102
|
+
const numericTracks = (tracks) => {
|
|
42103
|
+
return tracks ? tracks.filter(track => undefined !== track.dataRange || undefined !== track.autoscale || undefined !== track.autoscaleGroup) : []
|
|
42104
|
+
};
|
|
42105
|
+
|
|
42041
42106
|
class OverlayTrackButton extends NavbarButton {
|
|
42042
42107
|
constructor(browser, parent) {
|
|
42043
42108
|
|
|
@@ -42083,13 +42148,13 @@
|
|
|
42083
42148
|
{
|
|
42084
42149
|
name: 'Overlay',
|
|
42085
42150
|
type: 'merged',
|
|
42151
|
+
autoscale: false,
|
|
42086
42152
|
alpha: 0.5, //fudge * (1.0/tracks.length),
|
|
42087
42153
|
height: Math.max(...tracks.map(({ height }) => height)),
|
|
42088
42154
|
order: Math.min(...tracks.map(({ order }) => order)),
|
|
42089
|
-
_tracks: flattenedTracks
|
|
42090
42155
|
};
|
|
42091
42156
|
|
|
42092
|
-
const mergedTrack = new MergedTrack(config, this.browser);
|
|
42157
|
+
const mergedTrack = new MergedTrack(config, this.browser, flattenedTracks);
|
|
42093
42158
|
|
|
42094
42159
|
for (const track of tracks) {
|
|
42095
42160
|
this.browser.removeTrack(track);
|
|
@@ -42309,27 +42374,6 @@
|
|
|
42309
42374
|
}
|
|
42310
42375
|
}
|
|
42311
42376
|
|
|
42312
|
-
get dataRange() {
|
|
42313
|
-
return this.track.dataRange ? this.track.dataRange : undefined
|
|
42314
|
-
}
|
|
42315
|
-
|
|
42316
|
-
set dataRange({ min, max }) {
|
|
42317
|
-
|
|
42318
|
-
this.track.dataRange = { min, max };
|
|
42319
|
-
|
|
42320
|
-
this.track.autoscale = false;
|
|
42321
|
-
this.track.autoscaleGroup = undefined;
|
|
42322
|
-
|
|
42323
|
-
const list = this.browser.trackViews.filter(({track}) => track.autoscaleGroup);
|
|
42324
|
-
if (1 === list.length) {
|
|
42325
|
-
list[0].track.autoscale = false;
|
|
42326
|
-
list[0].track.autoscaleGroup = undefined;
|
|
42327
|
-
list[0].repaintViews();
|
|
42328
|
-
}
|
|
42329
|
-
|
|
42330
|
-
this.repaintViews();
|
|
42331
|
-
|
|
42332
|
-
}
|
|
42333
42377
|
|
|
42334
42378
|
presentColorPicker(key) {
|
|
42335
42379
|
|
|
@@ -49778,46 +49822,41 @@
|
|
|
49778
49822
|
},
|
|
49779
49823
|
|
|
49780
49824
|
/**
|
|
49825
|
+
* @param ba - UInt8Array bytes to decode
|
|
49781
49826
|
*
|
|
49782
|
-
* @
|
|
49783
|
-
* @param genome optional igv genome object
|
|
49784
|
-
* @returns {{ magicNumer: number, size: number, chrNames: Array, chrToIndex: ({}|*), chrAliasTable: ({}|*) }}
|
|
49827
|
+
* @returns {{size: *, chrNames: *[], magicNumber: *, chrToIndex: {}}}
|
|
49785
49828
|
*/
|
|
49786
|
-
decodeBamHeader: function (ba
|
|
49829
|
+
decodeBamHeader: function (ba) {
|
|
49787
49830
|
|
|
49788
|
-
var magic, samHeaderLen, samHeader, chrToIndex, chrNames;
|
|
49789
49831
|
|
|
49790
|
-
magic = readInt(ba, 0);
|
|
49832
|
+
const magic = readInt(ba, 0);
|
|
49791
49833
|
if (magic !== BAM1_MAGIC_NUMBER) {
|
|
49792
49834
|
throw new Error('BAM header errror: bad magic number. This could be caused by either a corrupt or missing file.')
|
|
49793
49835
|
}
|
|
49794
49836
|
|
|
49795
|
-
samHeaderLen = readInt(ba, 4);
|
|
49796
|
-
samHeader = '';
|
|
49797
|
-
|
|
49837
|
+
const samHeaderLen = readInt(ba, 4);
|
|
49838
|
+
let samHeader = '';
|
|
49798
49839
|
for (var i = 0; i < samHeaderLen; ++i) {
|
|
49799
49840
|
samHeader += String.fromCharCode(ba[i + 8]);
|
|
49800
49841
|
}
|
|
49801
49842
|
|
|
49802
|
-
|
|
49803
|
-
|
|
49843
|
+
const nRef = readInt(ba, samHeaderLen + 8);
|
|
49844
|
+
let p = samHeaderLen + 12;
|
|
49804
49845
|
|
|
49805
|
-
chrToIndex = {};
|
|
49806
|
-
chrNames = [];
|
|
49846
|
+
const chrToIndex = {};
|
|
49847
|
+
const chrNames = [];
|
|
49807
49848
|
|
|
49808
49849
|
for (i = 0; i < nRef; ++i) {
|
|
49809
|
-
|
|
49810
|
-
|
|
49811
|
-
for (var j = 0; j <
|
|
49850
|
+
const len = readInt(ba, p);
|
|
49851
|
+
let name = '';
|
|
49852
|
+
for (var j = 0; j < len - 1; ++j) {
|
|
49812
49853
|
name += String.fromCharCode(ba[p + 4 + j]);
|
|
49813
49854
|
}
|
|
49814
|
-
readInt(ba, p + lName + 4);
|
|
49815
|
-
//dlog(name + ': ' + lRef);
|
|
49816
49855
|
|
|
49817
49856
|
chrToIndex[name] = i;
|
|
49818
49857
|
chrNames[i] = name;
|
|
49819
49858
|
|
|
49820
|
-
p = p + 8 +
|
|
49859
|
+
p = p + 8 + len;
|
|
49821
49860
|
}
|
|
49822
49861
|
|
|
49823
49862
|
return {
|
|
@@ -50807,8 +50846,8 @@
|
|
|
50807
50846
|
const ba = unbgzf(compressedData.buffer);
|
|
50808
50847
|
this.header = BamUtils.decodeBamHeader(ba, this.genome);
|
|
50809
50848
|
this.chrAliasTable = new Map();
|
|
50810
|
-
for (let
|
|
50811
|
-
this.chrAliasTable.set(
|
|
50849
|
+
for (let name of this.header.chrNames) {
|
|
50850
|
+
this.chrAliasTable.set(name, this.genome.getChromosomeName(name));
|
|
50812
50851
|
}
|
|
50813
50852
|
}
|
|
50814
50853
|
|
|
@@ -50818,6 +50857,7 @@
|
|
|
50818
50857
|
|
|
50819
50858
|
// BAM decoding
|
|
50820
50859
|
const ba = unbgzf(compressedData.buffer);
|
|
50860
|
+
this.header = BamUtils.decodeBamHeader(ba, this.genome);
|
|
50821
50861
|
|
|
50822
50862
|
const chrIdx = this.header.chrToIndex[chr];
|
|
50823
50863
|
const alignmentContainer = new AlignmentContainer(chr, start, end, this.config);
|
|
@@ -57662,6 +57702,7 @@
|
|
|
57662
57702
|
|
|
57663
57703
|
|
|
57664
57704
|
constructor(config, parent) {
|
|
57705
|
+
this.featureType = 'numeric';
|
|
57665
57706
|
this.parent = parent;
|
|
57666
57707
|
this.featureSource = parent.featureSource;
|
|
57667
57708
|
|
|
@@ -66140,12 +66181,12 @@
|
|
|
66140
66181
|
if (this.signals.includes(signal_name)) {
|
|
66141
66182
|
let tconf = {};
|
|
66142
66183
|
tconf.type = "wig";
|
|
66143
|
-
tconf.isMergedTrack = true;
|
|
66144
66184
|
tconf.features = wig;
|
|
66145
66185
|
tconf.name = signal_name;
|
|
66146
66186
|
tconf.color = this.signal_colors.filter(x => x.singal_name === signal_name).map(x => x.color);
|
|
66147
66187
|
const t = await this.browser.createTrack(tconf);
|
|
66148
66188
|
if (t) {
|
|
66189
|
+
t.isMergedTrack = true;
|
|
66149
66190
|
t.autoscale = false; // Scaling done from merged track
|
|
66150
66191
|
this.tracks.push(t);
|
|
66151
66192
|
} else {
|
|
@@ -66324,12 +66365,12 @@
|
|
|
66324
66365
|
if (this.signals.includes(signal_name)) {
|
|
66325
66366
|
let tconf = {};
|
|
66326
66367
|
tconf.type = "wig";
|
|
66327
|
-
tconf.isMergedTrack = true;
|
|
66328
66368
|
tconf.features = wig;
|
|
66329
66369
|
tconf.name = signal_name;
|
|
66330
66370
|
tconf.color = this.signal_colors.filter(x => x.singal_name === signal_name).map(x => x.color);
|
|
66331
66371
|
const t = await this.browser.createTrack(tconf);
|
|
66332
66372
|
if (t) {
|
|
66373
|
+
t.isMergedTrack = true;
|
|
66333
66374
|
t.autoscale = false; // Scaling done from merged track
|
|
66334
66375
|
this.tracks.push(t);
|
|
66335
66376
|
} else {
|
|
@@ -66722,23 +66763,26 @@
|
|
|
66722
66763
|
this.header = await this.getHeader();
|
|
66723
66764
|
|
|
66724
66765
|
// Set colorBy, if not explicitly set default to allele frequency, if available, otherwise default to none (undefined)
|
|
66725
|
-
|
|
66726
|
-
|
|
66727
|
-
|
|
66728
|
-
|
|
66729
|
-
this.
|
|
66730
|
-
|
|
66766
|
+
if(this.header.INFO) {
|
|
66767
|
+
const infoFields = new Set(Object.keys(this.header.INFO));
|
|
66768
|
+
if (this.config.colorBy) {
|
|
66769
|
+
this.colorBy = this.config.colorBy;
|
|
66770
|
+
} else if (!this.config.color && infoFields.has('AF')) {
|
|
66771
|
+
this.colorBy = 'AF';
|
|
66772
|
+
}
|
|
66731
66773
|
|
|
66732
|
-
|
|
66733
|
-
|
|
66734
|
-
|
|
66735
|
-
|
|
66736
|
-
|
|
66737
|
-
|
|
66738
|
-
|
|
66739
|
-
|
|
66740
|
-
|
|
66774
|
+
// Configure menu items based on info available
|
|
66775
|
+
if (infoFields.has('AF')) {
|
|
66776
|
+
this._colorByItems.set('AF', 'Allele frequency');
|
|
66777
|
+
}
|
|
66778
|
+
if (infoFields.has('VT')) {
|
|
66779
|
+
this._colorByItems.set('VT', 'Variant Type');
|
|
66780
|
+
}
|
|
66781
|
+
if (infoFields.has('SVTYPE')) {
|
|
66782
|
+
this._colorByItems.set('SVTYPE', 'SV Type');
|
|
66783
|
+
}
|
|
66741
66784
|
}
|
|
66785
|
+
|
|
66742
66786
|
if (this.config.colorBy && !this._colorByItems.has(this.config.colorBy)) {
|
|
66743
66787
|
this._colorByItems.set(this.config.colorBy, this.config.colorBy);
|
|
66744
66788
|
}
|
|
@@ -69583,11 +69627,15 @@
|
|
|
69583
69627
|
JUNCTION_MOTIF_PALETTE.getColor(motif);
|
|
69584
69628
|
});
|
|
69585
69629
|
|
|
69586
|
-
// rendering context with values that only need to be computed once per render, rather than for each splice junction
|
|
69587
|
-
const junctionRenderingContext = {};
|
|
69588
69630
|
|
|
69589
69631
|
class SpliceJunctionTrack extends TrackBase {
|
|
69590
69632
|
|
|
69633
|
+
static defaults = {
|
|
69634
|
+
margin: 10,
|
|
69635
|
+
colorByNumReadsThreshold: 5,
|
|
69636
|
+
height: 100
|
|
69637
|
+
}
|
|
69638
|
+
|
|
69591
69639
|
constructor(config, browser) {
|
|
69592
69640
|
super(config, browser);
|
|
69593
69641
|
}
|
|
@@ -69608,16 +69656,6 @@
|
|
|
69608
69656
|
FeatureSource(config, this.browser.genome);
|
|
69609
69657
|
}
|
|
69610
69658
|
|
|
69611
|
-
this.margin = config.margin === undefined ? 10 : config.margin;
|
|
69612
|
-
|
|
69613
|
-
if (!this.height) {
|
|
69614
|
-
this.height = 100;
|
|
69615
|
-
}
|
|
69616
|
-
|
|
69617
|
-
//set defaults
|
|
69618
|
-
if (config.colorByNumReadsThreshold === undefined) {
|
|
69619
|
-
config.colorByNumReadsThreshold = 5;
|
|
69620
|
-
}
|
|
69621
69659
|
}
|
|
69622
69660
|
|
|
69623
69661
|
async postInit() {
|
|
@@ -69672,13 +69710,16 @@
|
|
|
69672
69710
|
const bpEnd = bpStart + pixelWidth * bpPerPixel + 1;
|
|
69673
69711
|
|
|
69674
69712
|
|
|
69675
|
-
if (!this.
|
|
69713
|
+
if (!this.isMergedTrack) {
|
|
69676
69714
|
IGVGraphics.fillRect(ctx, 0, options.pixelTop, pixelWidth, pixelHeight, {'fillStyle': "rgb(255, 255, 255)"});
|
|
69677
69715
|
}
|
|
69678
69716
|
|
|
69679
69717
|
if (featureList) {
|
|
69680
69718
|
|
|
69681
69719
|
|
|
69720
|
+
// rendering context with values that only need to be computed once per render, rather than for each splice junction
|
|
69721
|
+
const junctionRenderingContext = {};
|
|
69722
|
+
|
|
69682
69723
|
junctionRenderingContext.referenceFrame = options.viewport.referenceFrame;
|
|
69683
69724
|
junctionRenderingContext.referenceFrameStart = junctionRenderingContext.referenceFrame.start;
|
|
69684
69725
|
junctionRenderingContext.referenceFrameEnd = junctionRenderingContext.referenceFrameStart +
|
|
@@ -69691,7 +69732,7 @@
|
|
|
69691
69732
|
for (let feature of featureList) {
|
|
69692
69733
|
if (feature.end < bpStart) continue
|
|
69693
69734
|
if (feature.start > bpEnd) break
|
|
69694
|
-
this.renderJunction(feature, bpStart, bpPerPixel, pixelHeight, ctx);
|
|
69735
|
+
this.renderJunction(feature, bpStart, bpPerPixel, pixelHeight, ctx, junctionRenderingContext);
|
|
69695
69736
|
}
|
|
69696
69737
|
|
|
69697
69738
|
} else {
|
|
@@ -69708,7 +69749,7 @@
|
|
|
69708
69749
|
* @param pixelHeight pixel height of the current canvas
|
|
69709
69750
|
* @param ctx the canvas 2d context
|
|
69710
69751
|
*/
|
|
69711
|
-
renderJunction(feature, bpStart, xScale, pixelHeight, ctx) {
|
|
69752
|
+
renderJunction(feature, bpStart, xScale, pixelHeight, ctx, junctionRenderingContext) {
|
|
69712
69753
|
// cache whether this junction is rendered or filtered out. Use later to exclude non-rendered junctions from click detection.
|
|
69713
69754
|
feature.isVisible = false;
|
|
69714
69755
|
|
|
@@ -69792,7 +69833,7 @@
|
|
|
69792
69833
|
}
|
|
69793
69834
|
|
|
69794
69835
|
const py = this.margin;
|
|
69795
|
-
const rowHeight =
|
|
69836
|
+
const rowHeight = pixelHeight;
|
|
69796
69837
|
|
|
69797
69838
|
const cy = py + 0.5 * rowHeight;
|
|
69798
69839
|
let topY = py;
|
|
@@ -70477,7 +70518,7 @@
|
|
|
70477
70518
|
})
|
|
70478
70519
|
}
|
|
70479
70520
|
|
|
70480
|
-
const _version = "3.0.
|
|
70521
|
+
const _version = "3.0.2";
|
|
70481
70522
|
function version() {
|
|
70482
70523
|
return _version
|
|
70483
70524
|
}
|
|
@@ -72928,7 +72969,7 @@
|
|
|
72928
72969
|
}
|
|
72929
72970
|
|
|
72930
72971
|
/**
|
|
72931
|
-
* Return the canonical chromosome name for the alias. If none found return the alias.
|
|
72972
|
+
* Return the cached canonical chromosome name for the alias. If none found return the alias.
|
|
72932
72973
|
*
|
|
72933
72974
|
* Note this will only work if a "search" for ths chromosome has been performed previously.
|
|
72934
72975
|
*
|