igv 3.3.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/igv.d.ts +665 -0
- package/dist/igv.esm.js +464 -150
- package/dist/igv.esm.min.js +9 -9
- package/dist/igv.esm.min.js.map +1 -1
- package/dist/igv.js +464 -150
- package/dist/igv.min.js +9 -9
- package/dist/igv.min.js.map +1 -1
- package/package.json +5 -3
package/dist/igv.esm.js
CHANGED
|
@@ -373,7 +373,7 @@ class Dialog {
|
|
|
373
373
|
* @param x
|
|
374
374
|
* @returns {boolean}
|
|
375
375
|
*/
|
|
376
|
-
function isString$
|
|
376
|
+
function isString$3(x) {
|
|
377
377
|
return typeof x === "string" || x instanceof String
|
|
378
378
|
}
|
|
379
379
|
|
|
@@ -473,7 +473,7 @@ function getFilename$2(urlOrFile) {
|
|
|
473
473
|
|
|
474
474
|
if (urlOrFile.name !== undefined) {
|
|
475
475
|
return urlOrFile.name
|
|
476
|
-
} else if (isString$
|
|
476
|
+
} else if (isString$3(urlOrFile)) {
|
|
477
477
|
|
|
478
478
|
let index = urlOrFile.lastIndexOf("/");
|
|
479
479
|
let filename = index < 0 ? urlOrFile : urlOrFile.substr(index + 1);
|
|
@@ -10678,7 +10678,7 @@ const isNumber = function (num) {
|
|
|
10678
10678
|
};
|
|
10679
10679
|
|
|
10680
10680
|
async function getFilename$1(url) {
|
|
10681
|
-
if (isString$
|
|
10681
|
+
if (isString$3(url) && url.startsWith("https://drive.google.com")) {
|
|
10682
10682
|
// This will fail if Google API key is not defined
|
|
10683
10683
|
if (getApiKey() === undefined) {
|
|
10684
10684
|
throw Error("Google drive is referenced, but API key is not defined. An API key is required for Google Drive access")
|
|
@@ -10720,7 +10720,7 @@ function prettyBasePairNumber(raw) {
|
|
|
10720
10720
|
|
|
10721
10721
|
|
|
10722
10722
|
function isDataURL(obj) {
|
|
10723
|
-
return (isString$
|
|
10723
|
+
return (isString$3(obj) && obj.startsWith("data:"))
|
|
10724
10724
|
}
|
|
10725
10725
|
|
|
10726
10726
|
function createColumn(columnContainer, className) {
|
|
@@ -10946,7 +10946,7 @@ function createMenuElements$1(itemList, popover) {
|
|
|
10946
10946
|
return list;
|
|
10947
10947
|
}
|
|
10948
10948
|
|
|
10949
|
-
/*! @license DOMPurify 3.2.
|
|
10949
|
+
/*! @license DOMPurify 3.2.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.6/LICENSE */
|
|
10950
10950
|
|
|
10951
10951
|
const {
|
|
10952
10952
|
entries,
|
|
@@ -11150,7 +11150,7 @@ const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
|
|
|
11150
11150
|
const TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm); // eslint-disable-line unicorn/better-regex
|
|
11151
11151
|
const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
|
|
11152
11152
|
const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
|
|
11153
|
-
const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
|
|
11153
|
+
const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
|
|
11154
11154
|
);
|
|
11155
11155
|
const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
|
|
11156
11156
|
const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
|
|
@@ -11247,7 +11247,7 @@ const _createHooksMap = function _createHooksMap() {
|
|
|
11247
11247
|
function createDOMPurify() {
|
|
11248
11248
|
let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
|
|
11249
11249
|
const DOMPurify = root => createDOMPurify(root);
|
|
11250
|
-
DOMPurify.version = '3.2.
|
|
11250
|
+
DOMPurify.version = '3.2.6';
|
|
11251
11251
|
DOMPurify.removed = [];
|
|
11252
11252
|
if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
|
|
11253
11253
|
// Not running in a browser, provide a factory function
|
|
@@ -11486,8 +11486,8 @@ function createDOMPurify() {
|
|
|
11486
11486
|
URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
|
|
11487
11487
|
DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
|
|
11488
11488
|
FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
|
|
11489
|
-
FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};
|
|
11490
|
-
FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};
|
|
11489
|
+
FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
|
|
11490
|
+
FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
|
|
11491
11491
|
USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;
|
|
11492
11492
|
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
|
|
11493
11493
|
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
|
|
@@ -11852,7 +11852,7 @@ function createDOMPurify() {
|
|
|
11852
11852
|
allowedTags: ALLOWED_TAGS
|
|
11853
11853
|
});
|
|
11854
11854
|
/* Detect mXSS attempts abusing namespace confusion */
|
|
11855
|
-
if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\w!]/g, currentNode.textContent)) {
|
|
11855
|
+
if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\w!]/g, currentNode.textContent)) {
|
|
11856
11856
|
_forceRemove(currentNode);
|
|
11857
11857
|
return true;
|
|
11858
11858
|
}
|
|
@@ -12004,7 +12004,8 @@ function createDOMPurify() {
|
|
|
12004
12004
|
value: attrValue
|
|
12005
12005
|
} = attr;
|
|
12006
12006
|
const lcName = transformCaseFunc(name);
|
|
12007
|
-
|
|
12007
|
+
const initValue = attrValue;
|
|
12008
|
+
let value = name === 'value' ? initValue : stringTrim(initValue);
|
|
12008
12009
|
/* Execute a hook if present */
|
|
12009
12010
|
hookEvent.attrName = lcName;
|
|
12010
12011
|
hookEvent.attrValue = value;
|
|
@@ -12030,10 +12031,9 @@ function createDOMPurify() {
|
|
|
12030
12031
|
if (hookEvent.forceKeepAttr) {
|
|
12031
12032
|
continue;
|
|
12032
12033
|
}
|
|
12033
|
-
/* Remove attribute */
|
|
12034
|
-
_removeAttribute(name, currentNode);
|
|
12035
12034
|
/* Did the hooks approve of the attribute? */
|
|
12036
12035
|
if (!hookEvent.keepAttr) {
|
|
12036
|
+
_removeAttribute(name, currentNode);
|
|
12037
12037
|
continue;
|
|
12038
12038
|
}
|
|
12039
12039
|
/* Work around a security issue in jQuery 3.0 */
|
|
@@ -12050,6 +12050,7 @@ function createDOMPurify() {
|
|
|
12050
12050
|
/* Is `value` valid for this attribute? */
|
|
12051
12051
|
const lcTag = transformCaseFunc(currentNode.nodeName);
|
|
12052
12052
|
if (!_isValidAttribute(lcTag, lcName, value)) {
|
|
12053
|
+
_removeAttribute(name, currentNode);
|
|
12053
12054
|
continue;
|
|
12054
12055
|
}
|
|
12055
12056
|
/* Handle attributes that require Trusted Types */
|
|
@@ -12070,19 +12071,23 @@ function createDOMPurify() {
|
|
|
12070
12071
|
}
|
|
12071
12072
|
}
|
|
12072
12073
|
/* Handle invalid data-* attribute set by try-catching it */
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
|
|
12077
|
-
|
|
12078
|
-
|
|
12079
|
-
|
|
12080
|
-
|
|
12081
|
-
|
|
12082
|
-
|
|
12083
|
-
|
|
12074
|
+
if (value !== initValue) {
|
|
12075
|
+
try {
|
|
12076
|
+
if (namespaceURI) {
|
|
12077
|
+
currentNode.setAttributeNS(namespaceURI, name, value);
|
|
12078
|
+
} else {
|
|
12079
|
+
/* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
|
|
12080
|
+
currentNode.setAttribute(name, value);
|
|
12081
|
+
}
|
|
12082
|
+
if (_isClobbered(currentNode)) {
|
|
12083
|
+
_forceRemove(currentNode);
|
|
12084
|
+
} else {
|
|
12085
|
+
arrayPop(DOMPurify.removed);
|
|
12086
|
+
}
|
|
12087
|
+
} catch (_) {
|
|
12088
|
+
_removeAttribute(name, currentNode);
|
|
12084
12089
|
}
|
|
12085
|
-
}
|
|
12090
|
+
}
|
|
12086
12091
|
}
|
|
12087
12092
|
/* Execute a hook if present */
|
|
12088
12093
|
_executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
|
|
@@ -16903,7 +16908,7 @@ function findFeatureAfterCenter(featureList, center, direction = true) {
|
|
|
16903
16908
|
*/
|
|
16904
16909
|
|
|
16905
16910
|
const fixColor = (colorString) => {
|
|
16906
|
-
if (isString$
|
|
16911
|
+
if (isString$3(colorString)) {
|
|
16907
16912
|
return (colorString.indexOf(",") > 0 && !(colorString.startsWith("rgb(") || colorString.startsWith("rgba("))) ?
|
|
16908
16913
|
`rgb(${colorString})` : colorString
|
|
16909
16914
|
} else {
|
|
@@ -16975,7 +16980,7 @@ class TrackBase {
|
|
|
16975
16980
|
this.name = config.name || config.label;
|
|
16976
16981
|
} else if (isFile(config.url)) {
|
|
16977
16982
|
this.name = config.url.name;
|
|
16978
|
-
} else if (isString$
|
|
16983
|
+
} else if (isString$3(config.url) && !config.url.startsWith("data:")) {
|
|
16979
16984
|
this.name = getFilename$2(config.url);
|
|
16980
16985
|
}
|
|
16981
16986
|
|
|
@@ -20897,7 +20902,7 @@ class FeatureFileReader {
|
|
|
20897
20902
|
* THE SOFTWARE.
|
|
20898
20903
|
*/
|
|
20899
20904
|
|
|
20900
|
-
const isString$
|
|
20905
|
+
const isString$2 = isString$3;
|
|
20901
20906
|
|
|
20902
20907
|
|
|
20903
20908
|
class CustomServiceReader {
|
|
@@ -20936,7 +20941,7 @@ class CustomServiceReader {
|
|
|
20936
20941
|
if (data) {
|
|
20937
20942
|
if (typeof this.config.parser === "function") {
|
|
20938
20943
|
features = this.config.parser(data);
|
|
20939
|
-
} else if (isString$
|
|
20944
|
+
} else if (isString$2(data)) {
|
|
20940
20945
|
features = JSON.parse(data);
|
|
20941
20946
|
} else {
|
|
20942
20947
|
features = data;
|
|
@@ -23019,7 +23024,7 @@ class BWReader {
|
|
|
23019
23024
|
// TODO -- align all feature attribute names with UCSC, an use specific column
|
|
23020
23025
|
for (let key of Object.keys(f)) {
|
|
23021
23026
|
const v = f[key];
|
|
23022
|
-
if (isString$
|
|
23027
|
+
if (isString$3(v) && v.toLowerCase() === term.toLowerCase()) {
|
|
23023
23028
|
return true
|
|
23024
23029
|
}
|
|
23025
23030
|
}
|
|
@@ -23317,7 +23322,7 @@ class BWReader {
|
|
|
23317
23322
|
class ZoomLevelHeader {
|
|
23318
23323
|
constructor(index, byteBuffer) {
|
|
23319
23324
|
this.index = index;
|
|
23320
|
-
this.reductionLevel = byteBuffer.
|
|
23325
|
+
this.reductionLevel = byteBuffer.getUInt();
|
|
23321
23326
|
this.reserved = byteBuffer.getInt();
|
|
23322
23327
|
this.dataOffset = byteBuffer.getLong();
|
|
23323
23328
|
this.indexOffset = byteBuffer.getLong();
|
|
@@ -27643,7 +27648,7 @@ class FeatureTrack extends TrackBase {
|
|
|
27643
27648
|
fd.name &&
|
|
27644
27649
|
fd.name.toLowerCase() === "name" &&
|
|
27645
27650
|
fd.value &&
|
|
27646
|
-
isString$
|
|
27651
|
+
isString$3(fd.value) &&
|
|
27647
27652
|
!fd.value.startsWith("<")) {
|
|
27648
27653
|
const href = infoURL.replace("$$", feature.name);
|
|
27649
27654
|
fd.value = `<a target=_blank href=${href}>${fd.value}</a>`;
|
|
@@ -28287,7 +28292,7 @@ class BlatTrack extends FeatureTrack {
|
|
|
28287
28292
|
async postInit() {
|
|
28288
28293
|
if(!this.featureSource) {
|
|
28289
28294
|
// This will be the case when restoring from a session
|
|
28290
|
-
const db = this.browser.genome.
|
|
28295
|
+
const db = this.browser.genome.ucscID; // TODO -- blat specific property
|
|
28291
28296
|
const url = this.browser.config["blatServerURL"];
|
|
28292
28297
|
const features = await blat({url, userSeq: this.sequence, db});
|
|
28293
28298
|
this._features = features;
|
|
@@ -28304,7 +28309,7 @@ class BlatTrack extends FeatureTrack {
|
|
|
28304
28309
|
if (undefined === this.table) {
|
|
28305
28310
|
|
|
28306
28311
|
const rows = this._features.map(f => [
|
|
28307
|
-
f.chr,
|
|
28312
|
+
this.browser.genome.getChromosomeDisplayName(f.chr),
|
|
28308
28313
|
(f.start + 1),
|
|
28309
28314
|
f.end,
|
|
28310
28315
|
f.strand,
|
|
@@ -28379,7 +28384,7 @@ async function createBlatTrack({sequence, browser, name, title}) {
|
|
|
28379
28384
|
|
|
28380
28385
|
try {
|
|
28381
28386
|
|
|
28382
|
-
const db = browser.genome.
|
|
28387
|
+
const db = browser.genome.ucscID; // TODO -- blat specific property
|
|
28383
28388
|
const url = browser.config["blatServerURL"] || defaultBlatServer;
|
|
28384
28389
|
const features = await blat({url, userSeq: sequence, db});
|
|
28385
28390
|
|
|
@@ -30609,13 +30614,6 @@ class TrackDbHub {
|
|
|
30609
30614
|
this.trackStanzas = trackStanzas;
|
|
30610
30615
|
}
|
|
30611
30616
|
|
|
30612
|
-
findCytobandURL() {
|
|
30613
|
-
for (const t of this.trackStanzas) {
|
|
30614
|
-
if (t.name === "cytoBandIdeo" && t.hasProperty("bigDataUrl")) {
|
|
30615
|
-
return t.getProperty("bigDataUrl")
|
|
30616
|
-
}
|
|
30617
|
-
}
|
|
30618
|
-
}
|
|
30619
30617
|
|
|
30620
30618
|
getSupportedTrackCount() {
|
|
30621
30619
|
let count = 0;
|
|
@@ -30955,6 +30953,7 @@ function parseMetadata(metadata) {
|
|
|
30955
30953
|
|
|
30956
30954
|
const idMappings = new Map([
|
|
30957
30955
|
["hg38", "GCF_000001405.40"],
|
|
30956
|
+
["hg38_1kg", "GCF_000001405.40"],
|
|
30958
30957
|
["mm39", "GCF_000001635.27"],
|
|
30959
30958
|
["mm10", "GCF_000001635.26"],
|
|
30960
30959
|
["bosTau9", "GCF_002263795.1"],
|
|
@@ -30991,12 +30990,16 @@ class Hub {
|
|
|
30991
30990
|
this.genomeStanzas = genomeStanzas;
|
|
30992
30991
|
this.trackStanzas = trackStanzas;
|
|
30993
30992
|
this.groupStanzas = groupStanzas;
|
|
30993
|
+
this.cytobandStanza = null;
|
|
30994
30994
|
this.trackHubMap = new Map();
|
|
30995
30995
|
|
|
30996
30996
|
// trackStanzas will not be null if this is a "onefile" hub
|
|
30997
30997
|
if (trackStanzas) {
|
|
30998
30998
|
const genomeId = genomeStanzas[0].getProperty("genome"); // Assumption here this is a single genome hub
|
|
30999
30999
|
this.trackHubMap.set(genomeId, new TrackDbHub(trackStanzas, groupStanzas));
|
|
31000
|
+
|
|
31001
|
+
// Search for cytoband track. This supports a special but important case -- Genark assembly hubs
|
|
31002
|
+
this.cytobandStanza = this.trackStanzas.find(t => t.name === "cytoBandIdeo" && t.hasProperty("bigDataUrl")) || null;
|
|
31000
31003
|
}
|
|
31001
31004
|
}
|
|
31002
31005
|
|
|
@@ -31098,6 +31101,10 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1
|
|
|
31098
31101
|
config.twoBitBptURL = genomeStanza.getProperty("twoBitBptUrl");
|
|
31099
31102
|
}
|
|
31100
31103
|
|
|
31104
|
+
if(this.cytobandStanza){
|
|
31105
|
+
config.cytobandBbURL = this.cytobandStanza.getProperty("bigDataUrl");
|
|
31106
|
+
}
|
|
31107
|
+
|
|
31101
31108
|
if (this.hubStanza.hasProperty("longLabel")) {
|
|
31102
31109
|
config.description = this.hubStanza.getProperty("longLabel").replace("/", "\n");
|
|
31103
31110
|
} else {
|
|
@@ -31491,8 +31498,8 @@ function getHost(url) {
|
|
|
31491
31498
|
return host
|
|
31492
31499
|
}
|
|
31493
31500
|
|
|
31494
|
-
const DEFAULT_GENOMES_URL = "https://igv.org/genomes/
|
|
31495
|
-
const BACKUP_GENOMES_URL = "https://raw.githubusercontent.com/igvteam/igv-
|
|
31501
|
+
const DEFAULT_GENOMES_URL = "https://igv.org/genomes/genomes3.json";
|
|
31502
|
+
const BACKUP_GENOMES_URL = "https://raw.githubusercontent.com/igvteam/igv-data/refs/heads/main/genomes/web/genomes.json";
|
|
31496
31503
|
|
|
31497
31504
|
const GenomeUtils = {
|
|
31498
31505
|
|
|
@@ -31517,7 +31524,7 @@ const GenomeUtils = {
|
|
|
31517
31524
|
} catch (error) {
|
|
31518
31525
|
try {
|
|
31519
31526
|
console.error("Error initializing default genomes:", error);
|
|
31520
|
-
const jsonArray = await igvxhr.loadJson(BACKUP_GENOMES_URL, {timeout:
|
|
31527
|
+
const jsonArray = await igvxhr.loadJson(BACKUP_GENOMES_URL, {timeout: 10000});
|
|
31521
31528
|
processJson(jsonArray, table);
|
|
31522
31529
|
} catch (e) {
|
|
31523
31530
|
console.error("Error initializing backup genomes:", error);
|
|
@@ -31547,7 +31554,7 @@ const GenomeUtils = {
|
|
|
31547
31554
|
expandReference: async function (alert, idOrConfig) {
|
|
31548
31555
|
|
|
31549
31556
|
// idOrConfig might be a json string? I'm actually not sure how this arises.
|
|
31550
|
-
if (isString$
|
|
31557
|
+
if (isString$3(idOrConfig) && idOrConfig.startsWith("{")) {
|
|
31551
31558
|
try {
|
|
31552
31559
|
idOrConfig = JSON.parse(idOrConfig);
|
|
31553
31560
|
} catch (e) {
|
|
@@ -31556,7 +31563,7 @@ const GenomeUtils = {
|
|
|
31556
31563
|
}
|
|
31557
31564
|
|
|
31558
31565
|
let genomeID;
|
|
31559
|
-
if (isString$
|
|
31566
|
+
if (isString$3(idOrConfig)) {
|
|
31560
31567
|
genomeID = idOrConfig;
|
|
31561
31568
|
} else if (idOrConfig.genome) {
|
|
31562
31569
|
genomeID = idOrConfig.genome;
|
|
@@ -32502,7 +32509,7 @@ class TrackViewport extends Viewport {
|
|
|
32502
32509
|
let track = this.trackView.track;
|
|
32503
32510
|
const dataList = track.popupData(clickState);
|
|
32504
32511
|
|
|
32505
|
-
const popupClickHandlerResult = this.browser.fireEvent('trackclick', [track, dataList]);
|
|
32512
|
+
const popupClickHandlerResult = this.browser.fireEvent('trackclick', [track, dataList, clickState.genomicLocation]);
|
|
32506
32513
|
|
|
32507
32514
|
let content;
|
|
32508
32515
|
if (undefined === popupClickHandlerResult || true === popupClickHandlerResult) {
|
|
@@ -40992,6 +40999,9 @@ function doSortByAttributes(sampleInfo, sampleKeys) {
|
|
|
40992
40999
|
return true
|
|
40993
41000
|
}
|
|
40994
41001
|
|
|
41002
|
+
/**
|
|
41003
|
+
* Track for segmented copy number, mut, maf and shoebox files.
|
|
41004
|
+
*/
|
|
40995
41005
|
class SegTrack extends TrackBase {
|
|
40996
41006
|
|
|
40997
41007
|
#sortDirections = new Map()
|
|
@@ -41139,7 +41149,10 @@ class SegTrack extends TrackBase {
|
|
|
41139
41149
|
}, e);
|
|
41140
41150
|
}
|
|
41141
41151
|
|
|
41142
|
-
menuItems.push({
|
|
41152
|
+
menuItems.push({
|
|
41153
|
+
element: createElementWithString('<div>Set color scale threshold</div>'),
|
|
41154
|
+
dialog: dialogPresentationHandler
|
|
41155
|
+
});
|
|
41143
41156
|
}
|
|
41144
41157
|
|
|
41145
41158
|
menuItems.push('<hr/>');
|
|
@@ -41170,12 +41183,75 @@ class SegTrack extends TrackBase {
|
|
|
41170
41183
|
|
|
41171
41184
|
getSamples() {
|
|
41172
41185
|
return {
|
|
41173
|
-
names: this.
|
|
41186
|
+
names: this.filteredSampleKeys,
|
|
41174
41187
|
height: this.sampleHeight,
|
|
41175
41188
|
yOffset: 0
|
|
41176
41189
|
}
|
|
41177
41190
|
}
|
|
41178
41191
|
|
|
41192
|
+
/**
|
|
41193
|
+
* Set the sample filter object. This is used to filter samples from the set based on values over a specified
|
|
41194
|
+
* genomic region. The values compared depend on the track data type:
|
|
41195
|
+
* - "seg" and "shoebox" -- average value over the region
|
|
41196
|
+
* - "mut" and "maf" -- count of features overlapping the region
|
|
41197
|
+
*
|
|
41198
|
+
* The method is asynchronous because it may need to fetch data from the server to compute the scores.
|
|
41199
|
+
* Computed scores are stored and used to filter the sample keys on demand.
|
|
41200
|
+
*
|
|
41201
|
+
* @param filterObject
|
|
41202
|
+
* @returns {Promise<void>}
|
|
41203
|
+
*/
|
|
41204
|
+
async setSampleFilter(filterObject) {
|
|
41205
|
+
if (!filterObject) {
|
|
41206
|
+
this.config.filterObject = undefined;
|
|
41207
|
+
this.filterObject = undefined;
|
|
41208
|
+
this.trackView.repaintViews();
|
|
41209
|
+
} else {
|
|
41210
|
+
const filterObjectCopy = Object.assign({}, filterObject);
|
|
41211
|
+
this.config.filterObject = filterObjectCopy;
|
|
41212
|
+
|
|
41213
|
+
filterObject.scores = await this.computeRegionScores(filterObject);
|
|
41214
|
+
this.filterObject = filterObject;
|
|
41215
|
+
this.trackView.checkContentHeight();
|
|
41216
|
+
this.trackView.repaintViews();
|
|
41217
|
+
}
|
|
41218
|
+
// TODO - store filter object in session
|
|
41219
|
+
}
|
|
41220
|
+
|
|
41221
|
+
|
|
41222
|
+
/**
|
|
41223
|
+
* Filter function for sample keys.
|
|
41224
|
+
*
|
|
41225
|
+
* @param sampleKey
|
|
41226
|
+
* @returns {boolean}
|
|
41227
|
+
*/
|
|
41228
|
+
filter(sampleKey) {
|
|
41229
|
+
if (this.filterObject) {
|
|
41230
|
+
const filterObject = this.filterObject;
|
|
41231
|
+
const scores = filterObject.scores;
|
|
41232
|
+
const score = scores[sampleKey];
|
|
41233
|
+
|
|
41234
|
+
if (this.type === 'seg') {
|
|
41235
|
+
if (filterObject.op === '>') {
|
|
41236
|
+
return score > filterObject.value
|
|
41237
|
+
} else if (filterObject.op === '<') {
|
|
41238
|
+
return score < filterObject.value
|
|
41239
|
+
}
|
|
41240
|
+
} else if (this.type === 'mut' || this.type === 'maf') {
|
|
41241
|
+
return 'HAS' === filterObject.op ? score : !score
|
|
41242
|
+
}
|
|
41243
|
+
}
|
|
41244
|
+
// else if (this.config.sampleFilter) {
|
|
41245
|
+
// return this.config.sampleFilter(sampleKey)
|
|
41246
|
+
// }
|
|
41247
|
+
return true
|
|
41248
|
+
}
|
|
41249
|
+
|
|
41250
|
+
get filteredSampleKeys() {
|
|
41251
|
+
return this.sampleKeys.filter(sampleKey => this.filter(sampleKey))
|
|
41252
|
+
}
|
|
41253
|
+
|
|
41254
|
+
|
|
41179
41255
|
async getFeatures(chr, start, end) {
|
|
41180
41256
|
const features = await this.featureSource.getFeatures({chr, start, end});
|
|
41181
41257
|
// New segments could conceivably add new samples
|
|
@@ -41183,8 +41259,10 @@ class SegTrack extends TrackBase {
|
|
|
41183
41259
|
|
|
41184
41260
|
if (this.initialSort) {
|
|
41185
41261
|
const sort = this.initialSort;
|
|
41262
|
+
|
|
41186
41263
|
if (sort.option === undefined || sort.option.toUpperCase() === "VALUE") {
|
|
41187
|
-
|
|
41264
|
+
const sortFeatures = (sort.chr === chr && sort.start >= start && sort.end <= end) ? features : undefined;
|
|
41265
|
+
this.sortByValue(sort, sortFeatures);
|
|
41188
41266
|
} else if ("ATTRIBUTE" === sort.option.toUpperCase() && sort.attribute) {
|
|
41189
41267
|
const sortDirection = "DESC" === sort.direction ? 1 : -1;
|
|
41190
41268
|
this.sortByAttribute(sort.attribute, sortDirection);
|
|
@@ -41199,6 +41277,7 @@ class SegTrack extends TrackBase {
|
|
|
41199
41277
|
|
|
41200
41278
|
IGVGraphics.fillRect(context, 0, pixelTop, pixelWidth, pixelHeight, {'fillStyle': "rgb(255, 255, 255)"});
|
|
41201
41279
|
|
|
41280
|
+
|
|
41202
41281
|
if (features && features.length > 0) {
|
|
41203
41282
|
|
|
41204
41283
|
this.checkForLog(features);
|
|
@@ -41210,14 +41289,15 @@ class SegTrack extends TrackBase {
|
|
|
41210
41289
|
|
|
41211
41290
|
// Create a map for fast id -> row lookup
|
|
41212
41291
|
const samples = {};
|
|
41213
|
-
|
|
41292
|
+
const filteredKeys = this.filteredSampleKeys;
|
|
41293
|
+
filteredKeys.forEach(function (id, index) {
|
|
41214
41294
|
samples[id] = index;
|
|
41215
41295
|
});
|
|
41216
41296
|
|
|
41217
41297
|
let border;
|
|
41218
41298
|
switch (this.displayMode) {
|
|
41219
41299
|
case "FILL":
|
|
41220
|
-
this.sampleHeight = pixelHeight /
|
|
41300
|
+
this.sampleHeight = pixelHeight / filteredKeys.length;
|
|
41221
41301
|
border = 0;
|
|
41222
41302
|
break
|
|
41223
41303
|
|
|
@@ -41355,7 +41435,7 @@ class SegTrack extends TrackBase {
|
|
|
41355
41435
|
if (!features) return 0
|
|
41356
41436
|
const sampleHeight = ("SQUISHED" === this.displayMode) ? this.squishedRowHeight : this.expandedRowHeight;
|
|
41357
41437
|
this.updateSampleKeys(features);
|
|
41358
|
-
return this.
|
|
41438
|
+
return this.filteredSampleKeys.length * sampleHeight
|
|
41359
41439
|
}
|
|
41360
41440
|
|
|
41361
41441
|
/**
|
|
@@ -41364,16 +41444,38 @@ class SegTrack extends TrackBase {
|
|
|
41364
41444
|
async sortByValue(sort, featureList) {
|
|
41365
41445
|
|
|
41366
41446
|
const chr = sort.chr;
|
|
41447
|
+
const start = sort.position !== undefined ? sort.position - 1 : sort.start;
|
|
41448
|
+
const end = sort.end === undefined ? start + 1 : sort.end;
|
|
41449
|
+
const scores = await this.computeRegionScores({chr, start, end}, featureList);
|
|
41450
|
+
const d2 = (sort.direction === "ASC" ? 1 : -1);
|
|
41451
|
+
|
|
41452
|
+
this.sampleKeys.sort(function (a, b) {
|
|
41453
|
+
let s1 = scores[a];
|
|
41454
|
+
let s2 = scores[b];
|
|
41455
|
+
if (!s1) s1 = d2 * Number.MAX_VALUE;
|
|
41456
|
+
if (!s2) s2 = d2 * Number.MAX_VALUE;
|
|
41457
|
+
if (s1 === s2) return 0
|
|
41458
|
+
else if (s1 > s2) return d2
|
|
41459
|
+
else return d2 * -1
|
|
41460
|
+
});
|
|
41461
|
+
|
|
41462
|
+
this.config.sort = sort;
|
|
41463
|
+
this.trackView.repaintViews();
|
|
41464
|
+
}
|
|
41465
|
+
|
|
41466
|
+
|
|
41467
|
+
async computeRegionScores(filterObject, featureList) {
|
|
41468
|
+
|
|
41469
|
+
const chr = filterObject.chr;
|
|
41367
41470
|
let start, end;
|
|
41368
|
-
if (
|
|
41369
|
-
start =
|
|
41471
|
+
if (filterObject.position) {
|
|
41472
|
+
start = filterObject.position - 1;
|
|
41370
41473
|
end = start + 1;
|
|
41371
41474
|
} else {
|
|
41372
|
-
start =
|
|
41373
|
-
end =
|
|
41475
|
+
start = filterObject.start;
|
|
41476
|
+
end = filterObject.end;
|
|
41374
41477
|
}
|
|
41375
41478
|
|
|
41376
|
-
|
|
41377
41479
|
if (!featureList) {
|
|
41378
41480
|
featureList = await this.featureSource.getFeatures({chr, start, end});
|
|
41379
41481
|
}
|
|
@@ -41382,62 +41484,40 @@ class SegTrack extends TrackBase {
|
|
|
41382
41484
|
this.updateSampleKeys(featureList);
|
|
41383
41485
|
|
|
41384
41486
|
const scores = {};
|
|
41385
|
-
const
|
|
41487
|
+
const bpLength = end - start + 1;
|
|
41488
|
+
|
|
41489
|
+
const mutationTypes = filterObject.value ? new Set(filterObject.value) : undefined;
|
|
41490
|
+
|
|
41491
|
+
for (let segment of featureList) {
|
|
41492
|
+
if (segment.end < start) continue
|
|
41493
|
+
if (segment.start > end) break
|
|
41494
|
+
const sampleKey = segment.sampleKey || segment.sample;
|
|
41495
|
+
|
|
41496
|
+
if ("mut" === this.type) {
|
|
41497
|
+
if (mutationTypes) {
|
|
41498
|
+
const mutationType = segment.getAttribute("Variant_Classification");
|
|
41499
|
+
if (mutationTypes.has(mutationType)) {
|
|
41500
|
+
// Just count features overlapping region per sample
|
|
41501
|
+
scores[sampleKey] = (scores[sampleKey] || 0) + 1;
|
|
41502
|
+
}
|
|
41503
|
+
} else {
|
|
41504
|
+
// Just count features overlapping region per sample
|
|
41505
|
+
scores[sampleKey] = (scores[sampleKey] || 0) + 1;
|
|
41506
|
+
}
|
|
41507
|
+
} else {
|
|
41386
41508
|
|
|
41387
|
-
const sortSeg = () => {
|
|
41388
|
-
// Compute weighted average score for each sample
|
|
41389
|
-
const bpLength = end - start + 1;
|
|
41390
|
-
for (let segment of featureList) {
|
|
41391
|
-
if (segment.end < start) continue
|
|
41392
|
-
if (segment.start > end) break
|
|
41393
41509
|
const min = Math.max(start, segment.start);
|
|
41394
41510
|
const max = Math.min(end, segment.end);
|
|
41395
41511
|
const f = (max - min) / bpLength;
|
|
41396
|
-
|
|
41397
|
-
|
|
41398
|
-
scores[sampleKey] = s + f * segment.value;
|
|
41399
|
-
}
|
|
41400
|
-
|
|
41401
|
-
// Now sort sample names by score
|
|
41402
|
-
this.sampleKeys.sort(function (a, b) {
|
|
41403
|
-
let s1 = scores[a];
|
|
41404
|
-
let s2 = scores[b];
|
|
41405
|
-
if (!s1) s1 = d2 * Number.MAX_VALUE;
|
|
41406
|
-
if (!s2) s2 = d2 * Number.MAX_VALUE;
|
|
41407
|
-
if (s1 === s2) return 0
|
|
41408
|
-
else if (s1 > s2) return d2
|
|
41409
|
-
else return d2 * -1
|
|
41410
|
-
});
|
|
41411
|
-
};
|
|
41412
|
-
|
|
41413
|
-
const sortMut = () => {
|
|
41414
|
-
// Compute weighted average score for each sample
|
|
41415
|
-
for (let segment of featureList) {
|
|
41416
|
-
if (segment.end < start) continue
|
|
41417
|
-
if (segment.start > end) break
|
|
41418
|
-
const sampleKey = segment.sampleKey || segment.sample;
|
|
41419
|
-
if (!scores.hasOwnProperty(sampleKey) || segment.value.localeCompare(scores[sampleKey]) > 0) {
|
|
41420
|
-
scores[sampleKey] = segment.value;
|
|
41421
|
-
}
|
|
41422
|
-
}
|
|
41423
|
-
// Now sort sample names by score
|
|
41424
|
-
this.sampleKeys.sort(function (a, b) {
|
|
41425
|
-
let sa = scores[a] || "";
|
|
41426
|
-
let sb = scores[b] || "";
|
|
41427
|
-
return d2 * (sa.localeCompare(sb))
|
|
41428
|
-
});
|
|
41429
|
-
};
|
|
41430
|
-
|
|
41431
|
-
if ("mut" === this.type) {
|
|
41432
|
-
sortMut();
|
|
41433
|
-
} else {
|
|
41434
|
-
sortSeg();
|
|
41512
|
+
scores[sampleKey] = (scores[sampleKey] || 0) + f * segment.value;
|
|
41513
|
+
}
|
|
41435
41514
|
}
|
|
41436
41515
|
|
|
41437
|
-
|
|
41516
|
+
return scores
|
|
41438
41517
|
|
|
41439
41518
|
}
|
|
41440
41519
|
|
|
41520
|
+
|
|
41441
41521
|
sortByAttribute(attribute, sortDirection) {
|
|
41442
41522
|
|
|
41443
41523
|
this.sampleKeys = this.browser.sampleInfo.getSortedSampleKeysByAttribute(this.sampleKeys, attribute, sortDirection);
|
|
@@ -41506,7 +41586,7 @@ class SegTrack extends TrackBase {
|
|
|
41506
41586
|
const dirLabel = direction === "DESC" ? "descending" : "ascending";
|
|
41507
41587
|
const sortLabel = this.type === 'seg' || this.type === 'shoebox' ?
|
|
41508
41588
|
`Sort by value (${dirLabel})` :
|
|
41509
|
-
`Sort by
|
|
41589
|
+
`Sort by count (${dirLabel})`;
|
|
41510
41590
|
return {
|
|
41511
41591
|
label: sortLabel,
|
|
41512
41592
|
click: () => {
|
|
@@ -41518,7 +41598,6 @@ class SegTrack extends TrackBase {
|
|
|
41518
41598
|
end: Math.floor(genomicLocation + bpWidth)
|
|
41519
41599
|
};
|
|
41520
41600
|
sortHandler(sort);
|
|
41521
|
-
this.config.sort = sort;
|
|
41522
41601
|
}
|
|
41523
41602
|
}
|
|
41524
41603
|
})
|
|
@@ -41688,13 +41767,13 @@ class PairedAlignment {
|
|
|
41688
41767
|
}
|
|
41689
41768
|
}
|
|
41690
41769
|
|
|
41691
|
-
popupData(genomicLocation) {
|
|
41770
|
+
popupData(genomicLocation, hiddenTags, showTags) {
|
|
41692
41771
|
|
|
41693
|
-
let nameValues = this.firstAlignment.popupData(genomicLocation);
|
|
41772
|
+
let nameValues = this.firstAlignment.popupData(genomicLocation, hiddenTags, showTags);
|
|
41694
41773
|
|
|
41695
41774
|
if (this.secondAlignment) {
|
|
41696
41775
|
nameValues.push("-------------------------------");
|
|
41697
|
-
nameValues = nameValues.concat(this.secondAlignment.popupData(genomicLocation));
|
|
41776
|
+
nameValues = nameValues.concat(this.secondAlignment.popupData(genomicLocation, hiddenTags, showTags));
|
|
41698
41777
|
}
|
|
41699
41778
|
return nameValues
|
|
41700
41779
|
}
|
|
@@ -43408,7 +43487,7 @@ class BamAlignment {
|
|
|
43408
43487
|
isNegativeStrand() {
|
|
43409
43488
|
return (this.flags & READ_STRAND_FLAG$2) !== 0
|
|
43410
43489
|
}
|
|
43411
|
-
|
|
43490
|
+
|
|
43412
43491
|
isMateNegativeStrand() {
|
|
43413
43492
|
return (this.flags & MATE_STRAND_FLAG$2) !== 0
|
|
43414
43493
|
}
|
|
@@ -43456,7 +43535,7 @@ class BamAlignment {
|
|
|
43456
43535
|
return (genomicLocation >= s && genomicLocation <= (s + l))
|
|
43457
43536
|
}
|
|
43458
43537
|
|
|
43459
|
-
popupData(genomicLocation) {
|
|
43538
|
+
popupData(genomicLocation, hiddenTags, showTags) {
|
|
43460
43539
|
|
|
43461
43540
|
// if the user clicks on a base next to an insertion, show just the
|
|
43462
43541
|
// inserted bases in a popup (like in desktop IGV).
|
|
@@ -43539,15 +43618,20 @@ class BamAlignment {
|
|
|
43539
43618
|
}
|
|
43540
43619
|
}
|
|
43541
43620
|
|
|
43542
|
-
const hiddenTags = new Set(['SA', 'MD']);
|
|
43543
43621
|
nameValues.push('<hr/>');
|
|
43544
43622
|
for (let key in tagDict) {
|
|
43545
|
-
if (
|
|
43623
|
+
if (showTags?.has(key)) {
|
|
43624
|
+
nameValues.push({name: key, value: tagDict[key]});
|
|
43625
|
+
} else if (showTags) {
|
|
43626
|
+
hiddenTags.add(key);
|
|
43627
|
+
} else if (!hiddenTags.has(key)) {
|
|
43546
43628
|
nameValues.push({name: key, value: tagDict[key]});
|
|
43547
43629
|
}
|
|
43548
43630
|
}
|
|
43549
43631
|
|
|
43550
|
-
|
|
43632
|
+
if (hiddenTags && hiddenTags.size > 0) {
|
|
43633
|
+
nameValues.push({name: 'Hidden Tags', value: Array.from(hiddenTags).join(", ")});
|
|
43634
|
+
}
|
|
43551
43635
|
|
|
43552
43636
|
nameValues.push('<hr/>');
|
|
43553
43637
|
nameValues.push({name: 'Genomic Location: ', value: numberFormatter$1(1 + genomicLocation)});
|
|
@@ -43555,18 +43639,18 @@ class BamAlignment {
|
|
|
43555
43639
|
nameValues.push({name: 'Base Quality:', value: this.readBaseQualityAt(genomicLocation)});
|
|
43556
43640
|
|
|
43557
43641
|
const bmSets = this.getBaseModificationSets();
|
|
43558
|
-
if(bmSets) {
|
|
43642
|
+
if (bmSets) {
|
|
43559
43643
|
const i = this.positionToReadIndex(genomicLocation);
|
|
43560
|
-
if(undefined !== i) {
|
|
43644
|
+
if (undefined !== i) {
|
|
43561
43645
|
let found = false;
|
|
43562
43646
|
for (let bmSet of bmSets) {
|
|
43563
43647
|
if (bmSet.containsPosition(i)) {
|
|
43564
|
-
if(!found) {
|
|
43648
|
+
if (!found) {
|
|
43565
43649
|
nameValues.push('<hr/>');
|
|
43566
43650
|
nameValues.push('<b>Base modifications:</b>');
|
|
43567
43651
|
found = true;
|
|
43568
43652
|
}
|
|
43569
|
-
const lh = Math.round((100/255) * byteToUnsignedInt(bmSet.likelihoods.get(i)));
|
|
43653
|
+
const lh = Math.round((100 / 255) * byteToUnsignedInt(bmSet.likelihoods.get(i)));
|
|
43570
43654
|
nameValues.push(`${bmSet.fullName()} @ likelihood = ${lh}%`);
|
|
43571
43655
|
}
|
|
43572
43656
|
}
|
|
@@ -43656,7 +43740,7 @@ class BamAlignment {
|
|
|
43656
43740
|
const mm = this.tagDict["MM"] || this.tagDict["Mm"];
|
|
43657
43741
|
const ml = this.tagDict["ML"] || this.tagDict["Ml"];
|
|
43658
43742
|
|
|
43659
|
-
if (isString$
|
|
43743
|
+
if (isString$3(mm) && (!ml || Array.isArray(ml))) { // minimal validation, 10X uses these reserved tags for something completely different
|
|
43660
43744
|
if (mm.length === 0) {
|
|
43661
43745
|
this.baseModificationSets = EMPTY_SET;
|
|
43662
43746
|
} else {
|
|
@@ -43669,7 +43753,7 @@ class BamAlignment {
|
|
|
43669
43753
|
return this.baseModificationSets
|
|
43670
43754
|
}
|
|
43671
43755
|
|
|
43672
|
-
|
|
43756
|
+
getGroupValue(groupBy, tag, expectedPairOrientation) {
|
|
43673
43757
|
|
|
43674
43758
|
const al = this;
|
|
43675
43759
|
switch (groupBy) {
|
|
@@ -43706,7 +43790,7 @@ class BamAlignment {
|
|
|
43706
43790
|
}
|
|
43707
43791
|
}
|
|
43708
43792
|
|
|
43709
|
-
positionToReadIndex(
|
|
43793
|
+
positionToReadIndex(position) {
|
|
43710
43794
|
const block = blockAtGenomicLocation(this.blocks, position);
|
|
43711
43795
|
if (block) {
|
|
43712
43796
|
return (position - block.start) + block.seqOffset
|
|
@@ -45685,7 +45769,7 @@ function inferFileFormatFromName(fn) {
|
|
|
45685
45769
|
|
|
45686
45770
|
function inferIndexPath(url, extension) {
|
|
45687
45771
|
|
|
45688
|
-
if (isString$
|
|
45772
|
+
if (isString$3(url)) {
|
|
45689
45773
|
if (url.includes("?")) {
|
|
45690
45774
|
const idx = url.indexOf("?");
|
|
45691
45775
|
return url.substring(0, idx) + "." + extension + url.substring(idx)
|
|
@@ -45844,7 +45928,7 @@ class BamSource {
|
|
|
45844
45928
|
this.bamReader = new CramReader(config, genome, browser);
|
|
45845
45929
|
} else {
|
|
45846
45930
|
if (!this.config.indexURL && config.indexed !== false) {
|
|
45847
|
-
if (isString$
|
|
45931
|
+
if (isString$3(this.config.url)) {
|
|
45848
45932
|
const indexPath = inferIndexPath(this.config.url, "bai");
|
|
45849
45933
|
if (indexPath) {
|
|
45850
45934
|
console.warn(`Warning: no indexURL specified for ${this.config.url}. Guessing ${indexPath}`);
|
|
@@ -48156,7 +48240,7 @@ class AlignmentTrack extends TrackBase {
|
|
|
48156
48240
|
highlightColor: undefined,
|
|
48157
48241
|
minTLEN: undefined,
|
|
48158
48242
|
maxTLEN: undefined,
|
|
48159
|
-
tagColorPallete: "Set1"
|
|
48243
|
+
tagColorPallete: "Set1",
|
|
48160
48244
|
}
|
|
48161
48245
|
|
|
48162
48246
|
_colorTables = new Map()
|
|
@@ -48171,6 +48255,18 @@ class AlignmentTrack extends TrackBase {
|
|
|
48171
48255
|
this.colorTable = new ColorTable(config.tagColorTable);
|
|
48172
48256
|
}
|
|
48173
48257
|
|
|
48258
|
+
// Only one of showTags / hideTags should be specified. If both are specified showTags takes precedence.
|
|
48259
|
+
if (config.showTags && config.hideTags) {
|
|
48260
|
+
console.warn("Both showTags and hideTags specified. showTags will be used.");
|
|
48261
|
+
}
|
|
48262
|
+
if (config.showTags) {
|
|
48263
|
+
this.showTags = new Set(config.showTags);
|
|
48264
|
+
this.hiddenTags = new Set();
|
|
48265
|
+
} else {
|
|
48266
|
+
this.hiddenTags = new Set(config.hideTags || ["SA", "MD"]);
|
|
48267
|
+
}
|
|
48268
|
+
|
|
48269
|
+
|
|
48174
48270
|
// Backward compatibility overrides
|
|
48175
48271
|
if (config.largeFragmentLengthColor) this.largeTLENColor = config.largeFragmentLengthColor;
|
|
48176
48272
|
if (config.pairOrienation) this.expectedPairOrientation = config.pairOrientation;
|
|
@@ -48731,7 +48827,7 @@ class AlignmentTrack extends TrackBase {
|
|
|
48731
48827
|
|
|
48732
48828
|
popupData(clickState) {
|
|
48733
48829
|
const clickedObject = this.getClickedObject(clickState);
|
|
48734
|
-
return clickedObject
|
|
48830
|
+
return clickedObject?.popupData(clickState.genomicLocation, this.hiddenTags, this.showTags)
|
|
48735
48831
|
};
|
|
48736
48832
|
|
|
48737
48833
|
/**
|
|
@@ -48762,7 +48858,10 @@ class AlignmentTrack extends TrackBase {
|
|
|
48762
48858
|
colorByMenuItems.push({key: 'tlen', label: 'insert size (TLEN)'});
|
|
48763
48859
|
colorByMenuItems.push({key: 'unexpectedPair', label: 'pair orientation & insert size (TLEN)'});
|
|
48764
48860
|
}
|
|
48765
|
-
|
|
48861
|
+
if(this.colorBy && this.colorBy.startsWith("tag:")) {
|
|
48862
|
+
colorByMenuItems.push({key: this.colorBy, label: this.colorBy});
|
|
48863
|
+
}
|
|
48864
|
+
colorByMenuItems.push({key: 'tag', label: 'tag...'});
|
|
48766
48865
|
for (let item of colorByMenuItems) {
|
|
48767
48866
|
const selected = (this.colorBy === undefined && item.key === 'none') || this.colorBy === item.key;
|
|
48768
48867
|
menuItems.push(this.colorByCB(item, selected));
|
|
@@ -49488,14 +49587,19 @@ class AlignmentTrack extends TrackBase {
|
|
|
49488
49587
|
case "tag":
|
|
49489
49588
|
const tagValue = alignment.tags()[tag];
|
|
49490
49589
|
if (tagValue !== undefined) {
|
|
49491
|
-
|
|
49590
|
+
|
|
49591
|
+
// If the tag value can be interpreted as a color, use it
|
|
49592
|
+
if(typeof tagValue.startsWith === 'function') {
|
|
49492
49593
|
color = IGVColor.createColorStringSafe(tagValue);
|
|
49493
49594
|
}
|
|
49494
|
-
if (!this.colorTable) {
|
|
49495
|
-
this.colorTable = new PaletteColorTable(this.tagColorPallete);
|
|
49496
|
-
}
|
|
49497
|
-
color = this.colorTable.getColor(tagValue);
|
|
49498
49595
|
|
|
49596
|
+
// Tag value is not a color, use a color table
|
|
49597
|
+
if (!color) {
|
|
49598
|
+
if (!this.colorTable) {
|
|
49599
|
+
this.colorTable = new PaletteColorTable(this.tagColorPallete);
|
|
49600
|
+
}
|
|
49601
|
+
color = this.colorTable.getColor(tagValue);
|
|
49602
|
+
}
|
|
49499
49603
|
}
|
|
49500
49604
|
break
|
|
49501
49605
|
}
|
|
@@ -65712,7 +65816,7 @@ function autoscale(chr, featureArrays) {
|
|
|
65712
65816
|
* THE SOFTWARE.
|
|
65713
65817
|
*/
|
|
65714
65818
|
|
|
65715
|
-
const isString = isString$
|
|
65819
|
+
const isString$1 = isString$3;
|
|
65716
65820
|
|
|
65717
65821
|
const DEFAULT_VISIBILITY_WINDOW = 1000000;
|
|
65718
65822
|
const TOP_MARGIN = 10;
|
|
@@ -65835,7 +65939,7 @@ class VariantTrack extends TrackBase {
|
|
|
65835
65939
|
}
|
|
65836
65940
|
if (undefined === this.visibilityWindow && this.config.indexed !== false) {
|
|
65837
65941
|
const fn = isFile(this.config.url) ? this.config.url.name : this.config.url;
|
|
65838
|
-
if (isString(fn) && fn.toLowerCase().includes("gnomad")) {
|
|
65942
|
+
if (isString$1(fn) && fn.toLowerCase().includes("gnomad")) {
|
|
65839
65943
|
this.visibilityWindow = 1000; // these are known to be very dense
|
|
65840
65944
|
} else if (typeof this.featureSource.defaultVisibilityWindow === 'function') {
|
|
65841
65945
|
this.visibilityWindow = await this.featureSource.defaultVisibilityWindow();
|
|
@@ -69719,6 +69823,9 @@ const trackFunctions =
|
|
|
69719
69823
|
['image', (config, browser) => new ImageTrack(config, browser)]
|
|
69720
69824
|
]);
|
|
69721
69825
|
|
|
69826
|
+
function knownTrackTypes () {
|
|
69827
|
+
return new Set(trackFunctions.keys())
|
|
69828
|
+
}
|
|
69722
69829
|
|
|
69723
69830
|
/**
|
|
69724
69831
|
* Return a track of the given type, passing configuration and a point to the IGV "Browser" object to its constructor function*
|
|
@@ -70211,7 +70318,7 @@ function createReferenceFrameList(loci, genome, browserFlanking, minimumBases, v
|
|
|
70211
70318
|
})
|
|
70212
70319
|
}
|
|
70213
70320
|
|
|
70214
|
-
const _version = "3.
|
|
70321
|
+
const _version = "3.4.0";
|
|
70215
70322
|
function version() {
|
|
70216
70323
|
return _version
|
|
70217
70324
|
}
|
|
@@ -70262,7 +70369,7 @@ class ChromosomeSelectWidget {
|
|
|
70262
70369
|
if (this.select.value.trim().toLowerCase() === "all" || this.select.value === "*") {
|
|
70263
70370
|
if (browser.genome.wholeGenomeView) {
|
|
70264
70371
|
const wgChr = browser.genome.getChromosome("all");
|
|
70265
|
-
|
|
70372
|
+
browser.updateLoci([{chr: "all", start: 0, end: wgChr.bpLength}]);
|
|
70266
70373
|
}
|
|
70267
70374
|
} else {
|
|
70268
70375
|
const chromosome = await browser.genome.loadChromosome(this.select.value);
|
|
@@ -72067,6 +72174,26 @@ class ROIMenu {
|
|
|
72067
72174
|
}
|
|
72068
72175
|
|
|
72069
72176
|
|
|
72177
|
+
const found = this.browser.findTracks(track => typeof track.sortByValue === 'function');
|
|
72178
|
+
if (found.length > 0) {
|
|
72179
|
+
const { chr, start, end } = feature;
|
|
72180
|
+
items.push(
|
|
72181
|
+
'<hr/>',
|
|
72182
|
+
{
|
|
72183
|
+
label: 'Sort by value (ascending)',
|
|
72184
|
+
click: () => Promise.all(found.map(track => track.sortByValue({ option: 'VALUE', direction: 'ASC', chr, start, end })))
|
|
72185
|
+
});
|
|
72186
|
+
|
|
72187
|
+
items.push(
|
|
72188
|
+
'<hr/>',
|
|
72189
|
+
{
|
|
72190
|
+
label: 'Sort by value (descending)',
|
|
72191
|
+
click: () => Promise.all(found.map(track => track.sortByValue({ option: 'VALUE', direction: 'DESC', chr, start, end })))
|
|
72192
|
+
});
|
|
72193
|
+
|
|
72194
|
+
}
|
|
72195
|
+
|
|
72196
|
+
|
|
72070
72197
|
if (roiSet.isUserDefined) {
|
|
72071
72198
|
items.push(
|
|
72072
72199
|
'<hr/>',
|
|
@@ -72075,7 +72202,7 @@ class ROIMenu {
|
|
|
72075
72202
|
click: async () => {
|
|
72076
72203
|
roiSet.removeFeature(feature);
|
|
72077
72204
|
const userDefinedFeatures = await roiSet.getAllFeatures();
|
|
72078
|
-
|
|
72205
|
+
|
|
72079
72206
|
// Delete user defined ROI Set if it is empty
|
|
72080
72207
|
if (Object.keys(userDefinedFeatures).length === 0) {
|
|
72081
72208
|
roiManager.deleteUserDefinedROISet();
|
|
@@ -73248,6 +73375,189 @@ class CytobandFile {
|
|
|
73248
73375
|
|
|
73249
73376
|
}
|
|
73250
73377
|
|
|
73378
|
+
/**
|
|
73379
|
+
* Update deprecated fasta & index urls in the reference object.
|
|
73380
|
+
*/
|
|
73381
|
+
|
|
73382
|
+
const isString = (x) => {
|
|
73383
|
+
return (x && typeof x === "string") || x instanceof String
|
|
73384
|
+
};
|
|
73385
|
+
|
|
73386
|
+
/**
|
|
73387
|
+
* Replaces deprecated s3 fasta URLs with twoBitURLs. The purpose here is to rescue references from saved sessions
|
|
73388
|
+
* that contain pointers to deprectated IGV s3 buckets. These buckets will eventually be deleted
|
|
73389
|
+
*
|
|
73390
|
+
* @param reference
|
|
73391
|
+
*/
|
|
73392
|
+
function updateReference(reference) {
|
|
73393
|
+
|
|
73394
|
+
if (!(requiresUpdate(reference) && updates[reference.id])) {
|
|
73395
|
+
return
|
|
73396
|
+
}
|
|
73397
|
+
|
|
73398
|
+
const updatedReference = updates[reference.id];
|
|
73399
|
+
if (updatedReference) {
|
|
73400
|
+
delete reference.fastaURL;
|
|
73401
|
+
if (reference.indexURL) delete reference.indexURL;
|
|
73402
|
+
reference.twoBitURL = updatedReference.twoBitURL;
|
|
73403
|
+
if (updatedReference.twoBitBptURL) reference.twoBitBptURL = updatedReference.twoBitBptURL;
|
|
73404
|
+
if (updatedReference.chromSizesURL) reference.chromSizesURL = updatedReference.chromSizesURL;
|
|
73405
|
+
}
|
|
73406
|
+
}
|
|
73407
|
+
|
|
73408
|
+
function requiresUpdate(reference) {
|
|
73409
|
+
return isString(reference.fastaURL) &&
|
|
73410
|
+
(reference.fastaURL.startsWith("https://igv.org") ||
|
|
73411
|
+
["igv.org.genomes", "igv.broadinstitute.org", "igv.genepattern.org", "igvdata.broadinstitute.org",
|
|
73412
|
+
"igv-genepattern-org"].some(bucket => reference.fastaURL.includes(bucket)))
|
|
73413
|
+
}
|
|
73414
|
+
|
|
73415
|
+
const updates = {
|
|
73416
|
+
"hs1": {
|
|
73417
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/hs1/bigZips/hs1.2bit",
|
|
73418
|
+
"twoBitBptURL": "https://hgdownload.soe.ucsc.edu/goldenPath/hs1/bigZips/hs1.2bit.bpt",
|
|
73419
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/hs1/bigZips/hs1.chrom.sizes.txt"
|
|
73420
|
+
},
|
|
73421
|
+
"hg38": {
|
|
73422
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.2bit",
|
|
73423
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.chrom.sizes"
|
|
73424
|
+
},
|
|
73425
|
+
"hg19": {
|
|
73426
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/hg19/bigZips/hg19.2bit",
|
|
73427
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/hg19/bigZips/hg19.chrom.sizes"
|
|
73428
|
+
},
|
|
73429
|
+
"hg18": {
|
|
73430
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/hg18/bigZips/hg18.2bit",
|
|
73431
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/hg18/bigZips/hg18.chrom.sizes"
|
|
73432
|
+
},
|
|
73433
|
+
"mm39": {
|
|
73434
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/mm39/bigZips/mm39.2bit",
|
|
73435
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/mm39/bigZips/mm39.chrom.sizes"
|
|
73436
|
+
},
|
|
73437
|
+
"mm10": {
|
|
73438
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/mm10/bigZips/mm10.2bit",
|
|
73439
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/mm10/bigZips/mm10.chrom.sizes"
|
|
73440
|
+
},
|
|
73441
|
+
"mm9": {
|
|
73442
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/mm9/bigZips/mm9.2bit",
|
|
73443
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/mm9/bigZips/mm9.chrom.sizes"
|
|
73444
|
+
},
|
|
73445
|
+
"rn7": {
|
|
73446
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/015/227/675/GCF_015227675.2/GCF_015227675.2.2bit",
|
|
73447
|
+
"twoBitBptURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/015/227/675/GCF_015227675.2/GCF_015227675.2.2bit.bpt",
|
|
73448
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/015/227/675/GCF_015227675.2/GCF_015227675.2.chrom.sizes.txt"
|
|
73449
|
+
},
|
|
73450
|
+
"rn6": {
|
|
73451
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/001/895/GCF_000001895.5/GCF_000001895.5.2bit",
|
|
73452
|
+
"twoBitBptURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/001/895/GCF_000001895.5/GCF_000001895.5.2bit.bpt",
|
|
73453
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/001/895/GCF_000001895.5/GCF_000001895.5.chrom.sizes.txt"
|
|
73454
|
+
},
|
|
73455
|
+
"gorGor6": {
|
|
73456
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/gorGor6/bigZips/gorGor6.2bit",
|
|
73457
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/gorGor6/bigZips/gorGor6.chrom.sizes"
|
|
73458
|
+
},
|
|
73459
|
+
"gorGor4": {
|
|
73460
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/gorGor4/bigZips/gorGor4.2bit",
|
|
73461
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/gorGor4/bigZips/gorGor4.chrom.sizes"
|
|
73462
|
+
},
|
|
73463
|
+
"panTro6": {
|
|
73464
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/panTro6/bigZips/panTro6.2bit",
|
|
73465
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/panTro6/bigZips/panTro6.chrom.sizes"
|
|
73466
|
+
},
|
|
73467
|
+
"panTro5": {
|
|
73468
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/panTro5/bigZips/panTro5.2bit",
|
|
73469
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/panTro5/bigZips/panTro5.chrom.sizes"
|
|
73470
|
+
},
|
|
73471
|
+
"panTro4": {
|
|
73472
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/panTro4/bigZips/panTro4.2bit",
|
|
73473
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/panTro4/bigZips/panTro4.chrom.sizes"
|
|
73474
|
+
},
|
|
73475
|
+
"macFas5": {
|
|
73476
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/macFas5/bigZips/macFas5.2bit",
|
|
73477
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/macFas5/bigZips/macFas5.chrom.sizes"
|
|
73478
|
+
},
|
|
73479
|
+
"panPan2": {
|
|
73480
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/panPan2/bigZips/panPan2.2bit",
|
|
73481
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/panPan2/bigZips/panPan2.chrom.sizes"
|
|
73482
|
+
},
|
|
73483
|
+
"canFam6": {
|
|
73484
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/canFam6/bigZips/canFam6.2bit",
|
|
73485
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/canFam6/bigZips/canFam6.chrom.sizes"
|
|
73486
|
+
},
|
|
73487
|
+
"canFam5": {
|
|
73488
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/canFam5/bigZips/canFam5.2bit",
|
|
73489
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/canFam5/bigZips/canFam5.chrom.sizes"
|
|
73490
|
+
},
|
|
73491
|
+
"canFam4": {
|
|
73492
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/canFam4/bigZips/canFam4.2bit",
|
|
73493
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/canFam4/bigZips/canFam4.chrom.sizes"
|
|
73494
|
+
},
|
|
73495
|
+
"canFam3": {
|
|
73496
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/canFam3/bigZips/canFam3.2bit",
|
|
73497
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/canFam3/bigZips/canFam3.chrom.sizes"
|
|
73498
|
+
},
|
|
73499
|
+
"bosTau9": {
|
|
73500
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/bosTau9/bigZips/bosTau9.2bit",
|
|
73501
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/bosTau9/bigZips/bosTau9.chrom.sizes"
|
|
73502
|
+
},
|
|
73503
|
+
"bosTau8": {
|
|
73504
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/bosTau8/bigZips/bosTau8.2bit",
|
|
73505
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/bosTau8/bigZips/bosTau8.chrom.sizes"
|
|
73506
|
+
},
|
|
73507
|
+
"susScr11": {
|
|
73508
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/susScr11/bigZips/susScr11.2bit",
|
|
73509
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/susScr11/bigZips/susScr11.chrom.sizes"
|
|
73510
|
+
},
|
|
73511
|
+
"galGal6": {
|
|
73512
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/galGal6/bigZips/galGal6.2bit",
|
|
73513
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/galGal6/bigZips/galGal6.chrom.sizes"
|
|
73514
|
+
},
|
|
73515
|
+
"danRer11": {
|
|
73516
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/danRer11/bigZips/danRer11.2bit",
|
|
73517
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/danRer11/bigZips/danRer11.chrom.sizes"
|
|
73518
|
+
},
|
|
73519
|
+
"danRer10": {
|
|
73520
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/danRer10/bigZips/danRer10.2bit",
|
|
73521
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/danRer10/bigZips/danRer10.chrom.sizes"
|
|
73522
|
+
},
|
|
73523
|
+
"ce11": {
|
|
73524
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/ce11/bigZips/ce11.2bit",
|
|
73525
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/ce11/bigZips/ce11.chrom.sizes"
|
|
73526
|
+
},
|
|
73527
|
+
"dm6": {
|
|
73528
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/dm6/bigZips/dm6.2bit",
|
|
73529
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/dm6/bigZips/dm6.chrom.sizes"
|
|
73530
|
+
},
|
|
73531
|
+
"dm3": {
|
|
73532
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/dm3/bigZips/dm3.2bit",
|
|
73533
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/goldenPath/dm3/bigZips/dm3.chrom.sizes"
|
|
73534
|
+
},
|
|
73535
|
+
"sacCer3": {
|
|
73536
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/146/045/GCF_000146045.2/GCF_000146045.2.2bit",
|
|
73537
|
+
"twoBitBptURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/146/045/GCF_000146045.2/GCF_000146045.2.2bit.bpt",
|
|
73538
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/146/045/GCF_000146045.2/GCF_000146045.2.chrom.sizes.txt"
|
|
73539
|
+
},
|
|
73540
|
+
"GCF_000002945.1": {
|
|
73541
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/002/945/GCF_000002945.1/GCF_000002945.1.2bit",
|
|
73542
|
+
"twoBitBptURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/002/945/GCF_000002945.1/GCF_000002945.1.2bit.bpt",
|
|
73543
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/002/945/GCF_000002945.1/GCF_000002945.1.chrom.sizes.txt"
|
|
73544
|
+
},
|
|
73545
|
+
"GCF_009858895.2": {
|
|
73546
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/009/858/895/GCF_009858895.2/GCF_009858895.2.2bit",
|
|
73547
|
+
"twoBitBptURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/009/858/895/GCF_009858895.2/GCF_009858895.2.2bit.bpt",
|
|
73548
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/009/858/895/GCF_009858895.2/GCF_009858895.2.chrom.sizes.txt"
|
|
73549
|
+
},
|
|
73550
|
+
"tair10": {
|
|
73551
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/001/735/GCF_000001735.3/GCF_000001735.3.2bit",
|
|
73552
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/001/735/GCF_000001735.3/GCF_000001735.3.chrom.sizes.txt"
|
|
73553
|
+
},
|
|
73554
|
+
"GCA_000022165.1": {
|
|
73555
|
+
"twoBitURL": "https://hgdownload.soe.ucsc.edu/hubs/GCA/000/022/165/GCA_000022165.1/GCA_000022165.1.2bit",
|
|
73556
|
+
"twoBitBptURL": "https://hgdownload.soe.ucsc.edu/hubs/GCA/000/022/165/GCA_000022165.1/GCA_000022165.1.2bit.bpt",
|
|
73557
|
+
"chromSizesURL": "https://hgdownload.soe.ucsc.edu/hubs/GCA/000/022/165/GCA_000022165.1/GCA_000022165.1.chrom.sizes.txt"
|
|
73558
|
+
}
|
|
73559
|
+
};
|
|
73560
|
+
|
|
73251
73561
|
const ucsdIDMap = new Map([
|
|
73252
73562
|
["1kg_ref", "hg18"],
|
|
73253
73563
|
["1kg_v37", "hg19"],
|
|
@@ -73269,6 +73579,7 @@ class Genome {
|
|
|
73269
73579
|
|
|
73270
73580
|
static async createGenome(options, browser) {
|
|
73271
73581
|
|
|
73582
|
+
updateReference(options);
|
|
73272
73583
|
const genome = new Genome(options, browser);
|
|
73273
73584
|
await genome.init();
|
|
73274
73585
|
return genome
|
|
@@ -73292,7 +73603,6 @@ class Genome {
|
|
|
73292
73603
|
// Load sequence
|
|
73293
73604
|
this.sequence = await loadSequence(config, this.browser);
|
|
73294
73605
|
|
|
73295
|
-
|
|
73296
73606
|
// Load cytobands. This is optional but required to support the ideogram. Only needed for whole genome view
|
|
73297
73607
|
if(false !== config.showIdeogram && false !== config.wholeGenomeView) {
|
|
73298
73608
|
if (config.cytobandURL) {
|
|
@@ -73336,10 +73646,14 @@ class Genome {
|
|
|
73336
73646
|
} else {
|
|
73337
73647
|
this.#wgChromosomeNames = config.chromosomeOrder.split(',').map(nm => nm.trim());
|
|
73338
73648
|
}
|
|
73649
|
+
// Trim to remove non-existent chromosomes
|
|
73650
|
+
await this.chromAlias.preload(this.#wgChromosomeNames);
|
|
73651
|
+
this.#wgChromosomeNames =
|
|
73652
|
+
this.#wgChromosomeNames.map(c => this.getChromosomeName(c)).filter(c => this.chromosomes.has(c));
|
|
73339
73653
|
} else {
|
|
73340
73654
|
this.#wgChromosomeNames = trimSmallChromosomes(this.chromosomes);
|
|
73655
|
+
await this.chromAlias.preload(this.#wgChromosomeNames);
|
|
73341
73656
|
}
|
|
73342
|
-
await this.chromAlias.preload(this.#wgChromosomeNames);
|
|
73343
73657
|
}
|
|
73344
73658
|
|
|
73345
73659
|
// Optionally create the psuedo chromosome "all" to support whole genome view
|
|
@@ -73612,7 +73926,7 @@ function trimSmallChromosomes(chromosomes) {
|
|
|
73612
73926
|
function generateGenomeID(config) {
|
|
73613
73927
|
if (config.id !== undefined) {
|
|
73614
73928
|
return config.id
|
|
73615
|
-
} else if (config.fastaURL && isString$
|
|
73929
|
+
} else if (config.fastaURL && isString$3(config.fastaURL) && !config.fastaURL.startsWith("data:")) {
|
|
73616
73930
|
return config.fastaURL
|
|
73617
73931
|
} else if (config.fastaURL && config.fastaURL.name) {
|
|
73618
73932
|
return config.fastaURL.name
|
|
@@ -74345,7 +74659,7 @@ class Browser {
|
|
|
74345
74659
|
const urlOrFile = options.url || options.file;
|
|
74346
74660
|
|
|
74347
74661
|
let config;
|
|
74348
|
-
if (options.url && isString$
|
|
74662
|
+
if (options.url && isString$3(options.url) && (options.url.startsWith("blob:") || options.url.startsWith("data:"))) {
|
|
74349
74663
|
const json = Browser.uncompressSession(options.url);
|
|
74350
74664
|
config = JSON.parse(json);
|
|
74351
74665
|
} else {
|
|
@@ -74424,7 +74738,7 @@ class Browser {
|
|
|
74424
74738
|
return
|
|
74425
74739
|
}
|
|
74426
74740
|
|
|
74427
|
-
const genomeConfig = isString$
|
|
74741
|
+
const genomeConfig = isString$3(genomeOrReference) ?
|
|
74428
74742
|
await GenomeUtils.expandReference(this.alert, genomeOrReference) :
|
|
74429
74743
|
genomeOrReference;
|
|
74430
74744
|
|
|
@@ -74546,7 +74860,7 @@ class Browser {
|
|
|
74546
74860
|
}
|
|
74547
74861
|
|
|
74548
74862
|
/**
|
|
74549
|
-
* Load a reference genome object. This includes the
|
|
74863
|
+
* Load a reference genome object. This includes the sequence, and optional cytoband, but no tracks. This method
|
|
74550
74864
|
* is used by loadGenome and loadSession.
|
|
74551
74865
|
*
|
|
74552
74866
|
* @param genomeConfig
|
|
@@ -74611,7 +74925,7 @@ class Browser {
|
|
|
74611
74925
|
|
|
74612
74926
|
// Translate the generic "url" field, used by clients such as igv-webapp
|
|
74613
74927
|
if (idOrConfig.url) {
|
|
74614
|
-
if (isString$
|
|
74928
|
+
if (isString$3(idOrConfig.url) && idOrConfig.url.endsWith("/hub.txt")) {
|
|
74615
74929
|
idOrConfig.hubURL = idOrConfig.url;
|
|
74616
74930
|
delete idOrConfig.url;
|
|
74617
74931
|
} else if ("gbk" === getFileExtension(idOrConfig.url)) {
|
|
@@ -74621,11 +74935,11 @@ class Browser {
|
|
|
74621
74935
|
}
|
|
74622
74936
|
|
|
74623
74937
|
let genomeConfig;
|
|
74624
|
-
const isHubGenome = idOrConfig.hubURL || (idOrConfig.url && isString$
|
|
74938
|
+
const isHubGenome = idOrConfig.hubURL || (idOrConfig.url && isString$3(idOrConfig.url) && idOrConfig.url.endsWith("/hub.txt"));
|
|
74625
74939
|
if (isHubGenome) {
|
|
74626
74940
|
const hub = await loadHub(idOrConfig.hubURL || idOrConfig.url);
|
|
74627
74941
|
genomeConfig = hub.getGenomeConfig();
|
|
74628
|
-
} else if (isString$
|
|
74942
|
+
} else if (isString$3(idOrConfig) || !(idOrConfig.url || idOrConfig.fastaURL || idOrConfig.twoBitURL || idOrConfig.gbkURL)) {
|
|
74629
74943
|
// Either an ID, a json string, or an object missing required properties.
|
|
74630
74944
|
genomeConfig = await GenomeUtils.expandReference(this.alert, idOrConfig);
|
|
74631
74945
|
} else {
|
|
@@ -74792,7 +75106,7 @@ class Browser {
|
|
|
74792
75106
|
async #loadTrackHelper(config) {
|
|
74793
75107
|
|
|
74794
75108
|
// config might be json
|
|
74795
|
-
if (isString$
|
|
75109
|
+
if (isString$3(config)) {
|
|
74796
75110
|
config = JSON.parse(config);
|
|
74797
75111
|
}
|
|
74798
75112
|
|
|
@@ -74922,7 +75236,7 @@ class Browser {
|
|
|
74922
75236
|
|
|
74923
75237
|
// Resolve function and promise urls
|
|
74924
75238
|
let url = await resolveURL(config.url || config.fastaURL);
|
|
74925
|
-
if (isString$
|
|
75239
|
+
if (isString$3(url)) {
|
|
74926
75240
|
url = url.trim();
|
|
74927
75241
|
}
|
|
74928
75242
|
|
|
@@ -74970,7 +75284,7 @@ class Browser {
|
|
|
74970
75284
|
const featureSource = FeatureSource(config, this.genome);
|
|
74971
75285
|
config._featureSource = featureSource; // This is a temp variable, bit of a hack
|
|
74972
75286
|
const trackType = await featureSource.trackType();
|
|
74973
|
-
if (trackType) {
|
|
75287
|
+
if (trackType && knownTrackTypes().has(trackType)) {
|
|
74974
75288
|
type = trackType;
|
|
74975
75289
|
} else {
|
|
74976
75290
|
type = "annotation";
|