igv 3.5.2 → 3.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/igv.esm.js +196 -80
- package/dist/igv.esm.min.js +9 -9
- package/dist/igv.esm.min.js.map +1 -1
- package/dist/igv.js +196 -80
- package/dist/igv.min.js +9 -9
- package/dist/igv.min.js.map +1 -1
- package/package.json +2 -2
package/dist/igv.js
CHANGED
|
@@ -8708,7 +8708,7 @@
|
|
|
8708
8708
|
const response = await fetch(endPoint);
|
|
8709
8709
|
let json = await response.json();
|
|
8710
8710
|
if (json.error && json.error.code === 404) {
|
|
8711
|
-
let scope = "https://www.googleapis.com/auth/drive.
|
|
8711
|
+
let scope = "https://www.googleapis.com/auth/drive.file";
|
|
8712
8712
|
const access_token = await getAccessToken(scope);
|
|
8713
8713
|
if (access_token) {
|
|
8714
8714
|
const response = await fetch(endPoint, {
|
|
@@ -8890,6 +8890,10 @@
|
|
|
8890
8890
|
|
|
8891
8891
|
class IGVXhr {
|
|
8892
8892
|
|
|
8893
|
+
UCSC_HOST = "hgdownload.soe.ucsc.edu"
|
|
8894
|
+
UCSC_BACKUP_HOST = "genome-browser.s3.us-east-1.amazonaws.com"
|
|
8895
|
+
|
|
8896
|
+
|
|
8893
8897
|
constructor() {
|
|
8894
8898
|
this.apiKey = undefined;
|
|
8895
8899
|
this.googleThrottle = new Throttle({
|
|
@@ -8897,6 +8901,7 @@
|
|
|
8897
8901
|
});
|
|
8898
8902
|
this.RANGE_WARNING_GIVEN = false;
|
|
8899
8903
|
this.oauth = new Oauth();
|
|
8904
|
+
this.corsProxy = undefined;
|
|
8900
8905
|
}
|
|
8901
8906
|
|
|
8902
8907
|
setApiKey(key) {
|
|
@@ -8921,7 +8926,7 @@
|
|
|
8921
8926
|
* @param options
|
|
8922
8927
|
* @returns {Promise<Uint8Array>}
|
|
8923
8928
|
*/
|
|
8924
|
-
|
|
8929
|
+
async loadByteArray(url, options) {
|
|
8925
8930
|
const arraybuffer = await this.loadArrayBuffer(url, options);
|
|
8926
8931
|
let plain;
|
|
8927
8932
|
if (isgzipped(arraybuffer)) {
|
|
@@ -8966,7 +8971,7 @@
|
|
|
8966
8971
|
|
|
8967
8972
|
if (isFile(url)) {
|
|
8968
8973
|
return this._loadFileSlice(url, options)
|
|
8969
|
-
} else if (
|
|
8974
|
+
} else if (isString$3(url)) {
|
|
8970
8975
|
if (url.startsWith("data:")) {
|
|
8971
8976
|
const buffer = decodeDataURI$1(url).buffer;
|
|
8972
8977
|
if (options.range) {
|
|
@@ -8996,6 +9001,7 @@
|
|
|
8996
9001
|
|
|
8997
9002
|
const self = this;
|
|
8998
9003
|
const _url = url; // The unmodified URL, needed in case of an oAuth retry
|
|
9004
|
+
const {host} = parseUri(_url);
|
|
8999
9005
|
|
|
9000
9006
|
url = mapUrl$1(url);
|
|
9001
9007
|
|
|
@@ -9076,8 +9082,10 @@
|
|
|
9076
9082
|
|
|
9077
9083
|
xhr.onload = async function (event) {
|
|
9078
9084
|
|
|
9085
|
+
const isFileProtocol = url.toLowerCase().startsWith("file:");
|
|
9086
|
+
|
|
9079
9087
|
// when the url points to a local file, the status is 0
|
|
9080
|
-
if (xhr.status
|
|
9088
|
+
if ((xhr.status >= 200 && xhr.status <= 300) || (isFileProtocol && xhr.status === 0)) {
|
|
9081
9089
|
if ("HEAD" === options.method) {
|
|
9082
9090
|
// Support fetching specific headers. Attempting to fetch all headers can be problematic with CORS
|
|
9083
9091
|
const headers = options.requestedHeaders || ['content-length'];
|
|
@@ -9093,7 +9101,7 @@
|
|
|
9093
9101
|
// For small files a range starting at 0 can return the whole file => 200
|
|
9094
9102
|
// Provide just the slice we asked for, throw out the rest quietly
|
|
9095
9103
|
// If file is large warn user
|
|
9096
|
-
if (xhr.response.length >
|
|
9104
|
+
if (xhr.response.length > 1000000 && !self.RANGE_WARNING_GIVEN) {
|
|
9097
9105
|
alert(`Warning: Range header ignored for URL: ${url}. This can have severe performance impacts.`);
|
|
9098
9106
|
}
|
|
9099
9107
|
resolve(xhr.response.slice(range.start, range.start + range.size));
|
|
@@ -9110,20 +9118,29 @@
|
|
|
9110
9118
|
tryGoogleAuth();
|
|
9111
9119
|
|
|
9112
9120
|
} else {
|
|
9121
|
+
const error = new Error(`Error accessing resource: ${url} status: ${xhr.status}`);
|
|
9113
9122
|
if (xhr.status === 403) {
|
|
9114
9123
|
handleError("Access forbidden: " + url);
|
|
9124
|
+
} else if (host === self.UCSC_HOST) {
|
|
9125
|
+
tryUcscBackup(self.UCSC_HOST, self.UCSC_BACKUP_HOST, error);
|
|
9126
|
+
} else if (xhr.status === 0 && self.corsProxy && !options.corsProxyRetried) {
|
|
9127
|
+
tryCorsProxy(error);
|
|
9115
9128
|
} else {
|
|
9116
|
-
handleError(
|
|
9129
|
+
handleError(error);
|
|
9117
9130
|
}
|
|
9118
9131
|
}
|
|
9119
9132
|
};
|
|
9120
9133
|
|
|
9121
|
-
|
|
9122
9134
|
xhr.onerror = function (event) {
|
|
9135
|
+
const error = new Error(`Error accessing resource: ${url} status: ${xhr.status}`);
|
|
9123
9136
|
if (isGoogleURL(url) && !options.retries) {
|
|
9124
9137
|
tryGoogleAuth();
|
|
9138
|
+
} else if (host === self.UCSC_HOST) {
|
|
9139
|
+
tryUcscBackup(self.UCSC_HOST, self.UCSC_BACKUP_HOST, error);
|
|
9140
|
+
} else if (self.corsProxy && !options.corsProxyRetried) {
|
|
9141
|
+
tryCorsProxy(error);
|
|
9125
9142
|
} else {
|
|
9126
|
-
handleError(
|
|
9143
|
+
handleError(error);
|
|
9127
9144
|
}
|
|
9128
9145
|
};
|
|
9129
9146
|
|
|
@@ -9155,6 +9172,27 @@
|
|
|
9155
9172
|
}
|
|
9156
9173
|
}
|
|
9157
9174
|
|
|
9175
|
+
async function tryCorsProxy(error) {
|
|
9176
|
+
options.corsProxyRetried = true;
|
|
9177
|
+
const proxyUrl = self.corsProxy + (_url.includes("?") ? "&" : "?") + "url=" + encodeURIComponent(_url);
|
|
9178
|
+
try {
|
|
9179
|
+
const result = await self._loadURL(proxyUrl, options);
|
|
9180
|
+
resolve(result);
|
|
9181
|
+
} catch (e) {
|
|
9182
|
+
handleError(error);
|
|
9183
|
+
}
|
|
9184
|
+
}
|
|
9185
|
+
|
|
9186
|
+
async function tryUcscBackup(UCSC_HOST, UCSC_BACKUP_HOST, error) {
|
|
9187
|
+
const backupUrl = _url.replace(UCSC_HOST, UCSC_BACKUP_HOST);
|
|
9188
|
+
try {
|
|
9189
|
+
const result = await self._loadURL(backupUrl, options);
|
|
9190
|
+
resolve(result);
|
|
9191
|
+
} catch (e) {
|
|
9192
|
+
handleError(error);
|
|
9193
|
+
}
|
|
9194
|
+
}
|
|
9195
|
+
|
|
9158
9196
|
async function tryGoogleAuth() {
|
|
9159
9197
|
try {
|
|
9160
9198
|
const accessToken = await fetchGoogleAccessToken(_url);
|
|
@@ -9173,6 +9211,8 @@
|
|
|
9173
9211
|
}
|
|
9174
9212
|
}
|
|
9175
9213
|
}
|
|
9214
|
+
|
|
9215
|
+
|
|
9176
9216
|
})
|
|
9177
9217
|
|
|
9178
9218
|
}
|
|
@@ -9245,20 +9285,29 @@
|
|
|
9245
9285
|
}
|
|
9246
9286
|
|
|
9247
9287
|
/**
|
|
9248
|
-
*
|
|
9249
|
-
*
|
|
9250
|
-
*
|
|
9288
|
+
* Return the content length of the file at the given URL. This is not guaranteed to succeed, some servers
|
|
9289
|
+
* do not support or allow the content-length header.
|
|
9290
|
+
*
|
|
9251
9291
|
* @param url
|
|
9252
9292
|
* @param options
|
|
9253
9293
|
* @returns {Promise<unknown>}
|
|
9254
9294
|
*/
|
|
9255
9295
|
async getContentLength(url, options) {
|
|
9256
|
-
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
|
|
9260
|
-
|
|
9261
|
-
|
|
9296
|
+
if (isFile(url)) {
|
|
9297
|
+
return url.size
|
|
9298
|
+
} else {
|
|
9299
|
+
try {
|
|
9300
|
+
options = options || {};
|
|
9301
|
+
options.method = 'HEAD';
|
|
9302
|
+
options.requestedHeaders = ['content-length'];
|
|
9303
|
+
const headerMap = await this._loadURL(url, options);
|
|
9304
|
+
const contentLengthString = headerMap['content-length'];
|
|
9305
|
+
return contentLengthString ? Number.parseInt(contentLengthString) : 0
|
|
9306
|
+
} catch (e) {
|
|
9307
|
+
console.error(e);
|
|
9308
|
+
return -1
|
|
9309
|
+
}
|
|
9310
|
+
}
|
|
9262
9311
|
}
|
|
9263
9312
|
|
|
9264
9313
|
}
|
|
@@ -20670,6 +20719,7 @@
|
|
|
20670
20719
|
|
|
20671
20720
|
switch (config.format) {
|
|
20672
20721
|
case "vcf":
|
|
20722
|
+
case "vcftabix":
|
|
20673
20723
|
return new VcfParser(config)
|
|
20674
20724
|
case "seg" :
|
|
20675
20725
|
return new SegParser("seg")
|
|
@@ -21281,6 +21331,7 @@
|
|
|
21281
21331
|
}
|
|
21282
21332
|
}
|
|
21283
21333
|
|
|
21334
|
+
// Base class for feature sources. Subclasses must implement getFeatures().
|
|
21284
21335
|
class BaseFeatureSource {
|
|
21285
21336
|
|
|
21286
21337
|
constructor(genome) {
|
|
@@ -21342,59 +21393,10 @@
|
|
|
21342
21393
|
}
|
|
21343
21394
|
}
|
|
21344
21395
|
|
|
21345
|
-
|
|
21346
|
-
|
|
21347
|
-
|
|
21348
|
-
let idx = chromosomeNames.indexOf(chr);
|
|
21349
|
-
if (idx < 0) return // This shouldn't happen
|
|
21350
|
-
|
|
21351
|
-
// Look ahead (or behind) in 10 kb intervals, but no further than visibilityWindow
|
|
21352
|
-
const window = Math.min(10000, visibilityWindow || 10000);
|
|
21353
|
-
let queryStart = direction ? position : Math.max(position - window, 0);
|
|
21354
|
-
while (idx < chromosomeNames.length && idx >= 0) {
|
|
21355
|
-
chr = chromosomeNames[idx];
|
|
21356
|
-
const chromosome = this.genome.getChromosome(chr);
|
|
21357
|
-
const chromosomeEnd = chromosome.bpLength;
|
|
21358
|
-
while (queryStart < chromosomeEnd && queryStart >= 0) {
|
|
21359
|
-
let queryEnd = Math.min(position, queryStart + window);
|
|
21360
|
-
const featureList = await this.getFeatures({chr, start: queryStart, end: queryEnd, visibilityWindow});
|
|
21361
|
-
if (featureList) {
|
|
21362
|
-
|
|
21363
|
-
const compare = (o1, o2) => o1.start - o2.start + o1.end - o2.end;
|
|
21364
|
-
const sortedList = Array.from(featureList);
|
|
21365
|
-
sortedList.sort(compare);
|
|
21366
|
-
|
|
21367
|
-
// Search for next or previous feature relative to centers. We use a linear search because the
|
|
21368
|
-
// feature is likely to be near the first or end of the list
|
|
21369
|
-
let idx = direction ? 0 : sortedList.length - 1;
|
|
21370
|
-
while(idx >= 0 && idx < sortedList.length) {
|
|
21371
|
-
const f = sortedList[idx];
|
|
21372
|
-
const center = (f.start + f.end) / 2;
|
|
21373
|
-
if(direction) {
|
|
21374
|
-
if(center > position) return f
|
|
21375
|
-
idx++;
|
|
21376
|
-
} else {
|
|
21377
|
-
if(center < position) return f
|
|
21378
|
-
idx--;
|
|
21379
|
-
}
|
|
21380
|
-
}
|
|
21381
|
-
}
|
|
21382
|
-
queryStart = direction ? queryEnd : queryStart - window;
|
|
21383
|
-
}
|
|
21384
|
-
if (direction) {
|
|
21385
|
-
idx++;
|
|
21386
|
-
queryStart = 0;
|
|
21387
|
-
position = 0;
|
|
21388
|
-
} else {
|
|
21389
|
-
idx--;
|
|
21390
|
-
if (idx < 0) break
|
|
21391
|
-
const prevChromosome = this.genome.getChromosome(chromosomeNames[idx]);
|
|
21392
|
-
position = prevChromosome.bpLength;
|
|
21393
|
-
queryStart = position - window;
|
|
21394
|
-
}
|
|
21395
|
-
}
|
|
21396
|
+
// Subclasses must implement
|
|
21397
|
+
async getFeatures({chr, start, end, bpPerPixel, visibilityWindow}) {
|
|
21398
|
+
throw new Error("getFeatures not implemented")
|
|
21396
21399
|
}
|
|
21397
|
-
|
|
21398
21400
|
}
|
|
21399
21401
|
|
|
21400
21402
|
const GZIP_FLAG = 0x1;
|
|
@@ -26533,6 +26535,88 @@
|
|
|
26533
26535
|
}
|
|
26534
26536
|
}
|
|
26535
26537
|
|
|
26538
|
+
/**
|
|
26539
|
+
* A feature source for a "list" file. A list file is a text file with two columns, chromosome and URL. It was
|
|
26540
|
+
* created for the 1KG genotype files, which are split by chromosome, and at the moment that is the only use case.
|
|
26541
|
+
*/
|
|
26542
|
+
|
|
26543
|
+
class ListFeatureSource extends BaseFeatureSource {
|
|
26544
|
+
|
|
26545
|
+
constructor(config, genome) {
|
|
26546
|
+
super(genome);
|
|
26547
|
+
this.config = config;
|
|
26548
|
+
this.featureSourceMap = null;
|
|
26549
|
+
this.header = null;
|
|
26550
|
+
}
|
|
26551
|
+
|
|
26552
|
+
async getHeader() {
|
|
26553
|
+
|
|
26554
|
+
if (!this.header) {
|
|
26555
|
+
|
|
26556
|
+
if (!this.featureSourceMap) {
|
|
26557
|
+
await this.init();
|
|
26558
|
+
}
|
|
26559
|
+
// Return the header from the first feature source. It is assumed that all sources have a common header.
|
|
26560
|
+
const firstFS = this.featureSourceMap.values().next().value;
|
|
26561
|
+
if (firstFS && firstFS.getHeader) {
|
|
26562
|
+
this.header = firstFS.getHeader();
|
|
26563
|
+
} else {
|
|
26564
|
+
this.header = Promise.resolve(undefined);
|
|
26565
|
+
}
|
|
26566
|
+
}
|
|
26567
|
+
|
|
26568
|
+
return this.header
|
|
26569
|
+
|
|
26570
|
+
}
|
|
26571
|
+
|
|
26572
|
+
async getFeatures({chr, start, end, bpPerPixel, visibilityWindow}) {
|
|
26573
|
+
|
|
26574
|
+
if (!this.featureSourceMap) {
|
|
26575
|
+
await this.init();
|
|
26576
|
+
}
|
|
26577
|
+
const fs = this.featureSourceMap.get(chr);
|
|
26578
|
+
if (fs) {
|
|
26579
|
+
return fs.getFeatures({chr, start, end, bpPerPixel, visibilityWindow})
|
|
26580
|
+
} else {
|
|
26581
|
+
return []
|
|
26582
|
+
}
|
|
26583
|
+
}
|
|
26584
|
+
|
|
26585
|
+
async init() {
|
|
26586
|
+
this.featureSourceMap = new Map();
|
|
26587
|
+
|
|
26588
|
+
const options = buildOptions(this.config);
|
|
26589
|
+
const data = await igvxhr.loadByteArray(this.config.url, options);
|
|
26590
|
+
const dataWrapper = getDataWrapper(data);
|
|
26591
|
+
|
|
26592
|
+
let line;
|
|
26593
|
+
while ((line = dataWrapper.nextLine()) !== undefined) {
|
|
26594
|
+
const trimmed = line.trim();
|
|
26595
|
+
if (!trimmed.startsWith('#')) {
|
|
26596
|
+
const tokens = trimmed.split(/\s+/);
|
|
26597
|
+
if (tokens.length > 1) {
|
|
26598
|
+
const chr = tokens[0];
|
|
26599
|
+
const path = tokens[1];
|
|
26600
|
+
const sourceConfig = Object.assign({}, this.config);
|
|
26601
|
+
sourceConfig.url = path;
|
|
26602
|
+
if (path.endsWith(".vcf.gz")) {
|
|
26603
|
+
sourceConfig.format = "vcf";
|
|
26604
|
+
sourceConfig.indexURL = path + ".tbi";
|
|
26605
|
+
}
|
|
26606
|
+
this.featureSourceMap.set(chr, FeatureSource(sourceConfig, this.genome));
|
|
26607
|
+
}
|
|
26608
|
+
}
|
|
26609
|
+
}
|
|
26610
|
+
}
|
|
26611
|
+
|
|
26612
|
+
supportWholeGenome() {
|
|
26613
|
+
return false
|
|
26614
|
+
}
|
|
26615
|
+
}
|
|
26616
|
+
|
|
26617
|
+
// chrY https://1000genomes.s3.amazonaws.com/release/20130502/ALL.chrY.phase3_integrated_v1b.20130502.genotypes.vcf.gz
|
|
26618
|
+
// chrX https://1000genomes.s3.amazonaws.com/release/20130502/ALL.chrX.phase3_shapeit2_mvncall_integrated_v1b.20130502.genotypes.vcf.gz
|
|
26619
|
+
|
|
26536
26620
|
const bbFormats = new Set(['bigwig', 'bw', 'bigbed', 'bb', 'biginteract', 'biggenepred', 'bignarrowpeak']);
|
|
26537
26621
|
|
|
26538
26622
|
function FeatureSource(config, genome) {
|
|
@@ -26547,6 +26631,9 @@
|
|
|
26547
26631
|
return new TDFSource(config, genome)
|
|
26548
26632
|
} else if ("gbk" === format) {
|
|
26549
26633
|
return new GenbankFeatureSource(config, genome)
|
|
26634
|
+
} else if ("vcf.list" === format) {
|
|
26635
|
+
// This is a text file with two columns: <chr> <url to vcf>
|
|
26636
|
+
return new ListFeatureSource(config, genome)
|
|
26550
26637
|
} else {
|
|
26551
26638
|
return new TextFeatureSource(config, genome)
|
|
26552
26639
|
}
|
|
@@ -30409,6 +30496,19 @@
|
|
|
30409
30496
|
const filterTracks = new Set(["cytoBandIdeo", "assembly", "gap", "gapOverlap", "allGaps",
|
|
30410
30497
|
"cpgIslandExtUnmasked", "windowMasker"]);
|
|
30411
30498
|
|
|
30499
|
+
const vizModeMap = new Map([
|
|
30500
|
+
["pack", "EXPANDED"],
|
|
30501
|
+
["full", "EXPANDED"],
|
|
30502
|
+
["squish", "SQUISHED"],
|
|
30503
|
+
["dense", "COLLAPSED"]
|
|
30504
|
+
]);
|
|
30505
|
+
const typeFormatMap = new Map([
|
|
30506
|
+
["vcftabix", "vcf"],
|
|
30507
|
+
["vcfphasedtrio", "vcf"],
|
|
30508
|
+
["bigdbsnp", "bigbed"],
|
|
30509
|
+
["genepred", "refgene"]
|
|
30510
|
+
]);
|
|
30511
|
+
|
|
30412
30512
|
class TrackDbHub {
|
|
30413
30513
|
|
|
30414
30514
|
constructor(trackStanzas, groupStanzas) {
|
|
@@ -30554,14 +30654,13 @@
|
|
|
30554
30654
|
*/
|
|
30555
30655
|
#getTrackConfig(t) {
|
|
30556
30656
|
|
|
30557
|
-
const format = t.format;
|
|
30657
|
+
const format = typeFormatMap.get(t.format) || t.format;
|
|
30558
30658
|
|
|
30559
30659
|
const config = {
|
|
30560
30660
|
"id": t.getProperty("track"),
|
|
30561
30661
|
"name": t.getProperty("shortLabel"),
|
|
30562
30662
|
"format": format,
|
|
30563
|
-
"url": t.getProperty("bigDataUrl")
|
|
30564
|
-
"displayMode": t.displayMode,
|
|
30663
|
+
"url": t.getProperty("bigDataUrl")
|
|
30565
30664
|
};
|
|
30566
30665
|
|
|
30567
30666
|
if ("vcfTabix" === format) {
|
|
@@ -30611,9 +30710,14 @@
|
|
|
30611
30710
|
|
|
30612
30711
|
}
|
|
30613
30712
|
if (t.hasProperty("itemRgb")) ;
|
|
30614
|
-
if
|
|
30615
|
-
|
|
30616
|
-
|
|
30713
|
+
if(t.hasProperty("visibility")) {
|
|
30714
|
+
if ("hide" === t.getProperty("visibility")) {
|
|
30715
|
+
// TODO -- this not supported yet
|
|
30716
|
+
config.visible = false;
|
|
30717
|
+
}
|
|
30718
|
+
else {
|
|
30719
|
+
config.displayMode = vizModeMap.get(t.getProperty("visibility")) || "COLLAPSED";
|
|
30720
|
+
}
|
|
30617
30721
|
}
|
|
30618
30722
|
if (t.hasProperty("url")) {
|
|
30619
30723
|
config.infoURL = t.getProperty("url");
|
|
@@ -37794,6 +37898,8 @@
|
|
|
37794
37898
|
case "tdf":
|
|
37795
37899
|
return "wig"
|
|
37796
37900
|
case "vcf":
|
|
37901
|
+
case "vcftabix":
|
|
37902
|
+
case "vcf.list":
|
|
37797
37903
|
return "variant"
|
|
37798
37904
|
case "seg":
|
|
37799
37905
|
return "seg"
|
|
@@ -37848,7 +37954,7 @@
|
|
|
37848
37954
|
} else if ("bam" === config.type) {
|
|
37849
37955
|
config.type = "alignment";
|
|
37850
37956
|
config.format = "bam";
|
|
37851
|
-
} else if ("vcf" === config.type) {
|
|
37957
|
+
} else if ("vcf" === config.type || "vcftabix" === config.type) {
|
|
37852
37958
|
config.type = "variant";
|
|
37853
37959
|
config.format = "vcf";
|
|
37854
37960
|
} else if ("t2d" === config.type) {
|
|
@@ -38128,7 +38234,7 @@
|
|
|
38128
38234
|
const groupIndeces = NULL_GROUP !== this.groupBy ?
|
|
38129
38235
|
this.sampleKeys.map(sample => this.getGroupIndex(sample)) : undefined;
|
|
38130
38236
|
return {
|
|
38131
|
-
names: this.sampleKeys,
|
|
38237
|
+
names: this.sampleKeys || [],
|
|
38132
38238
|
height: this.sampleHeight,
|
|
38133
38239
|
yOffset: 0,
|
|
38134
38240
|
groups: this.groups,
|
|
@@ -62825,7 +62931,8 @@ ${indent}columns: ${matrix.columns}
|
|
|
62825
62931
|
}
|
|
62826
62932
|
|
|
62827
62933
|
get supportsWholeGenome() {
|
|
62828
|
-
|
|
62934
|
+
const sourceSupportsWG = typeof this.featureSource.supportsWholeGenome === 'function' && this.featureSource.supportsWholeGenome();
|
|
62935
|
+
return sourceSupportsWG || this.config.supportsWholeGenome === true
|
|
62829
62936
|
}
|
|
62830
62937
|
|
|
62831
62938
|
get color() {
|
|
@@ -62898,7 +63005,7 @@ ${indent}columns: ${matrix.columns}
|
|
|
62898
63005
|
const yOffset = TOP_MARGIN + nVariantRows * (variantHeight + vGap);
|
|
62899
63006
|
|
|
62900
63007
|
return {
|
|
62901
|
-
names: this.sampleKeys,
|
|
63008
|
+
names: this.sampleKeys || [],
|
|
62902
63009
|
yOffset,
|
|
62903
63010
|
height,
|
|
62904
63011
|
// groups: this.groups,
|
|
@@ -67029,7 +67136,7 @@ ${indent}columns: ${matrix.columns}
|
|
|
67029
67136
|
})
|
|
67030
67137
|
}
|
|
67031
67138
|
|
|
67032
|
-
const _version = "3.5.
|
|
67139
|
+
const _version = "3.5.3";
|
|
67033
67140
|
function version() {
|
|
67034
67141
|
return _version
|
|
67035
67142
|
}
|
|
@@ -74576,6 +74683,10 @@ ${indent}columns: ${matrix.columns}
|
|
|
74576
74683
|
config = JSON.parse(config);
|
|
74577
74684
|
}
|
|
74578
74685
|
|
|
74686
|
+
if(config.format && config.format.toLowerCase() === 'sampleinfo') {
|
|
74687
|
+
return this.loadSampleInfo(config)
|
|
74688
|
+
}
|
|
74689
|
+
|
|
74579
74690
|
let track;
|
|
74580
74691
|
try {
|
|
74581
74692
|
track = await this.createTrack(config);
|
|
@@ -76352,6 +76463,10 @@ ${indent}columns: ${matrix.columns}
|
|
|
76352
76463
|
return igvxhr.setOauthToken(accessToken, host)
|
|
76353
76464
|
}
|
|
76354
76465
|
|
|
76466
|
+
function setCORSProxy(proxyURL) {
|
|
76467
|
+
igvxhr.corsProxy = proxyURL;
|
|
76468
|
+
}
|
|
76469
|
+
|
|
76355
76470
|
// Backward compatibility
|
|
76356
76471
|
const oauth = igvxhr.oauth;
|
|
76357
76472
|
|
|
@@ -76368,6 +76483,7 @@ ${indent}columns: ${matrix.columns}
|
|
|
76368
76483
|
visibilityChange,
|
|
76369
76484
|
setGoogleOauthToken,
|
|
76370
76485
|
setOauthToken,
|
|
76486
|
+
setCORSProxy,
|
|
76371
76487
|
oauth,
|
|
76372
76488
|
version,
|
|
76373
76489
|
setApiKey,
|