igv 2.13.7 → 2.13.9
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 +431 -228
- package/dist/igv.esm.min.js +8 -8
- package/dist/igv.esm.min.js.map +1 -1
- package/dist/igv.js +443 -210
- package/dist/igv.min.js +5 -5
- package/dist/igv.min.js.map +1 -1
- package/package.json +1 -1
package/dist/igv.js
CHANGED
|
@@ -13966,7 +13966,7 @@
|
|
|
13966
13966
|
const {
|
|
13967
13967
|
Inflate,
|
|
13968
13968
|
inflate: inflate$3,
|
|
13969
|
-
inflateRaw,
|
|
13969
|
+
inflateRaw: inflateRaw$2,
|
|
13970
13970
|
ungzip: ungzip$2
|
|
13971
13971
|
} = inflate_1$1;
|
|
13972
13972
|
var Deflate_1 = Deflate;
|
|
@@ -13975,7 +13975,7 @@
|
|
|
13975
13975
|
var gzip_1 = gzip;
|
|
13976
13976
|
var Inflate_1 = Inflate;
|
|
13977
13977
|
var inflate_1 = inflate$3;
|
|
13978
|
-
var inflateRaw_1 = inflateRaw;
|
|
13978
|
+
var inflateRaw_1 = inflateRaw$2;
|
|
13979
13979
|
var ungzip_1 = ungzip$2;
|
|
13980
13980
|
var constants_1 = constants$2;
|
|
13981
13981
|
var pako = {
|
|
@@ -14008,7 +14008,7 @@
|
|
|
14008
14008
|
|
|
14009
14009
|
pako.deflateRaw;
|
|
14010
14010
|
pako.deflate;
|
|
14011
|
-
pako.inflateRaw;
|
|
14011
|
+
const inflateRaw = pako.inflateRaw;
|
|
14012
14012
|
const inflate = pako.inflate;
|
|
14013
14013
|
pako.gzip;
|
|
14014
14014
|
const FEXTRA = 4; // gzip spec F.EXTRA flag
|
|
@@ -14080,7 +14080,7 @@
|
|
|
14080
14080
|
return out;
|
|
14081
14081
|
}
|
|
14082
14082
|
}
|
|
14083
|
-
function bgzBlockSize(data) {
|
|
14083
|
+
function bgzBlockSize$1(data) {
|
|
14084
14084
|
const ba = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
|
|
14085
14085
|
const bsize = (ba[17] << 8 | ba[16]) + 1;
|
|
14086
14086
|
return bsize;
|
|
@@ -16829,10 +16829,7 @@
|
|
|
16829
16829
|
var rgb = this.hsvToRgb(this.hue, saturation, value);
|
|
16830
16830
|
return "#" + this.padHex(rgb[0].toString(16)) + this.padHex(rgb[1].toString(16)) + this.padHex(rgb[2].toString(16));
|
|
16831
16831
|
};
|
|
16832
|
-
|
|
16833
|
-
function randomColor() {
|
|
16834
|
-
return randomColorGenerator.get();
|
|
16835
|
-
}
|
|
16832
|
+
new RandomColorGenerator();
|
|
16836
16833
|
function randomRGB$1(min, max) {
|
|
16837
16834
|
min = IGVMath.clamp(min, 0, 255);
|
|
16838
16835
|
max = IGVMath.clamp(max, 0, 255);
|
|
@@ -18865,7 +18862,7 @@
|
|
|
18865
18862
|
|
|
18866
18863
|
const doAutoscale = function (features) {
|
|
18867
18864
|
var min, max;
|
|
18868
|
-
if (features.length > 0) {
|
|
18865
|
+
if (features && features.length > 0) {
|
|
18869
18866
|
min = Number.MAX_VALUE;
|
|
18870
18867
|
max = -Number.MAX_VALUE;
|
|
18871
18868
|
features.forEach(function (f) {
|
|
@@ -21939,7 +21936,7 @@
|
|
|
21939
21936
|
}
|
|
21940
21937
|
};
|
|
21941
21938
|
|
|
21942
|
-
const _version = "2.13.
|
|
21939
|
+
const _version = "2.13.9";
|
|
21943
21940
|
function version$1() {
|
|
21944
21941
|
return _version;
|
|
21945
21942
|
}
|
|
@@ -26462,12 +26459,81 @@
|
|
|
26462
26459
|
isGreaterThan(vp) {
|
|
26463
26460
|
return this.block > vp.block || this.block === vp.block && this.offset > vp.offset;
|
|
26464
26461
|
}
|
|
26462
|
+
isEqualTo(vp) {
|
|
26463
|
+
return this.block === vp.block && this.offset === vp.offset;
|
|
26464
|
+
}
|
|
26465
26465
|
print() {
|
|
26466
26466
|
return "" + this.block + ":" + this.offset;
|
|
26467
26467
|
}
|
|
26468
26468
|
}
|
|
26469
26469
|
|
|
26470
|
-
|
|
26470
|
+
function optimizeChunks(chunks, lowest) {
|
|
26471
|
+
if (chunks.length === 0) return chunks;
|
|
26472
|
+
chunks.sort(function (c0, c1) {
|
|
26473
|
+
const dif = c0.minv.block - c1.minv.block;
|
|
26474
|
+
if (dif !== 0) {
|
|
26475
|
+
return dif;
|
|
26476
|
+
} else {
|
|
26477
|
+
return c0.minv.offset - c1.minv.offset;
|
|
26478
|
+
}
|
|
26479
|
+
});
|
|
26480
|
+
if (chunks.length <= 1) {
|
|
26481
|
+
return chunks;
|
|
26482
|
+
}
|
|
26483
|
+
|
|
26484
|
+
// console.log("Before trimming " + chunks.length)
|
|
26485
|
+
// for (let c of chunks) {
|
|
26486
|
+
// console.log(`${c.minv.block} ${c.minv.offset} - ${c.maxv.block} ${c.maxv.offset}`)
|
|
26487
|
+
// }
|
|
26488
|
+
|
|
26489
|
+
if (lowest) {
|
|
26490
|
+
chunks = chunks.filter(c => c.maxv.isGreaterThan(lowest));
|
|
26491
|
+
}
|
|
26492
|
+
|
|
26493
|
+
// console.log("Before merging " + chunks.length)
|
|
26494
|
+
// for (let c of chunks) {
|
|
26495
|
+
// console.log(`${c.minv.block} ${c.minv.offset} - ${c.maxv.block} ${c.maxv.offset}`)
|
|
26496
|
+
// }
|
|
26497
|
+
|
|
26498
|
+
const mergedChunks = [];
|
|
26499
|
+
let lastChunk;
|
|
26500
|
+
for (let chunk of chunks) {
|
|
26501
|
+
if (!lastChunk) {
|
|
26502
|
+
mergedChunks.push(chunk);
|
|
26503
|
+
lastChunk = chunk;
|
|
26504
|
+
} else {
|
|
26505
|
+
if (canMerge(lastChunk, chunk)) {
|
|
26506
|
+
if (chunk.maxv.isGreaterThan(lastChunk.maxv)) {
|
|
26507
|
+
lastChunk.maxv = chunk.maxv;
|
|
26508
|
+
}
|
|
26509
|
+
} else {
|
|
26510
|
+
mergedChunks.push(chunk);
|
|
26511
|
+
lastChunk = chunk;
|
|
26512
|
+
}
|
|
26513
|
+
}
|
|
26514
|
+
}
|
|
26515
|
+
|
|
26516
|
+
// console.log("After merging " + mergedChunks.length)
|
|
26517
|
+
// for (let c of mergedChunks) {
|
|
26518
|
+
// console.log(`${c.minv.block} ${c.minv.offset} - ${c.maxv.block} ${c.maxv.offset}`)
|
|
26519
|
+
// }
|
|
26520
|
+
|
|
26521
|
+
return mergedChunks;
|
|
26522
|
+
}
|
|
26523
|
+
|
|
26524
|
+
/**
|
|
26525
|
+
* Merge 2 blocks if the file position gap between them is < 16 kb, and the total size is < ~5 mb
|
|
26526
|
+
* @param chunk1
|
|
26527
|
+
* @param chunk2
|
|
26528
|
+
* @returns {boolean|boolean}
|
|
26529
|
+
*/
|
|
26530
|
+
function canMerge(chunk1, chunk2) {
|
|
26531
|
+
const gap = chunk2.minv.block - chunk1.maxv.block;
|
|
26532
|
+
const sizeEstimate = chunk1.maxv.block - chunk1.minv.block;
|
|
26533
|
+
return gap < 65000 && sizeEstimate < 5000000;
|
|
26534
|
+
}
|
|
26535
|
+
|
|
26536
|
+
// Represents a CSI Bam or Tabix index
|
|
26471
26537
|
const CSI1_MAGIC$1 = 21582659; // CSI\1
|
|
26472
26538
|
const CSI2_MAGIC$1 = 38359875; // CSI\2
|
|
26473
26539
|
|
|
@@ -26579,7 +26645,7 @@
|
|
|
26579
26645
|
* @param max genomic end position
|
|
26580
26646
|
* @param return an array of {minv: {filePointer, offset}, {maxv: {filePointer, offset}}
|
|
26581
26647
|
*/
|
|
26582
|
-
|
|
26648
|
+
chunksForRange(refId, min, max) {
|
|
26583
26649
|
const ba = this.indices[refId];
|
|
26584
26650
|
if (!ba) {
|
|
26585
26651
|
return [];
|
|
@@ -26605,7 +26671,7 @@
|
|
|
26605
26671
|
}
|
|
26606
26672
|
}
|
|
26607
26673
|
const lowestOffset = ba.loffset[overlappingBins[0]];
|
|
26608
|
-
return optimizeChunks
|
|
26674
|
+
return optimizeChunks(chunks, lowestOffset);
|
|
26609
26675
|
}
|
|
26610
26676
|
}
|
|
26611
26677
|
|
|
@@ -26637,48 +26703,10 @@
|
|
|
26637
26703
|
return ((1 << (this.depth + 1) * 3) - 1) / 7;
|
|
26638
26704
|
}
|
|
26639
26705
|
}
|
|
26640
|
-
function optimizeChunks$1(chunks, lowest) {
|
|
26641
|
-
const mergedChunks = [];
|
|
26642
|
-
let lastChunk = null;
|
|
26643
|
-
if (chunks.length === 0) return chunks;
|
|
26644
|
-
chunks.sort(function (c0, c1) {
|
|
26645
|
-
const dif = c0.minv.block - c1.minv.block;
|
|
26646
|
-
if (dif !== 0) {
|
|
26647
|
-
return dif;
|
|
26648
|
-
} else {
|
|
26649
|
-
return c0.minv.offset - c1.minv.offset;
|
|
26650
|
-
}
|
|
26651
|
-
});
|
|
26652
|
-
chunks.forEach(function (chunk) {
|
|
26653
|
-
if (!lowest || chunk.maxv.isGreaterThan(lowest)) {
|
|
26654
|
-
if (lastChunk === null) {
|
|
26655
|
-
mergedChunks.push(chunk);
|
|
26656
|
-
lastChunk = chunk;
|
|
26657
|
-
} else {
|
|
26658
|
-
if (canMerge$1(lastChunk, chunk)) {
|
|
26659
|
-
if (chunk.maxv.isGreaterThan(lastChunk.maxv)) {
|
|
26660
|
-
lastChunk.maxv = chunk.maxv;
|
|
26661
|
-
}
|
|
26662
|
-
} else {
|
|
26663
|
-
mergedChunks.push(chunk);
|
|
26664
|
-
lastChunk = chunk;
|
|
26665
|
-
}
|
|
26666
|
-
}
|
|
26667
|
-
}
|
|
26668
|
-
});
|
|
26669
|
-
return mergedChunks;
|
|
26670
|
-
}
|
|
26671
|
-
function canMerge$1(chunk1, chunk2) {
|
|
26672
|
-
return chunk2.minv.block - chunk1.maxv.block < 65000 && chunk2.maxv.block - chunk1.minv.block < 5000000;
|
|
26673
|
-
// lastChunk.minv.block === lastChunk.maxv.block &&
|
|
26674
|
-
// lastChunk.maxv.block === chunk.minv.block &&
|
|
26675
|
-
// chunk.minv.block === chunk.maxv.block
|
|
26676
|
-
}
|
|
26677
26706
|
|
|
26678
|
-
// Represents a BAM index.
|
|
26707
|
+
// Represents a BAM or Tabix index.
|
|
26679
26708
|
const BAI_MAGIC$1 = 21578050;
|
|
26680
26709
|
const TABIX_MAGIC$1 = 21578324;
|
|
26681
|
-
const MB = 1000000;
|
|
26682
26710
|
async function parseBamIndex(arrayBuffer, genome) {
|
|
26683
26711
|
const index = new BamIndex();
|
|
26684
26712
|
await index.parse(arrayBuffer, false, genome);
|
|
@@ -26780,22 +26808,27 @@
|
|
|
26780
26808
|
}
|
|
26781
26809
|
|
|
26782
26810
|
/**
|
|
26783
|
-
* Fetch
|
|
26811
|
+
* Fetch chunks for a particular genomic range. This method is public so it can be unit-tested.
|
|
26784
26812
|
*
|
|
26785
26813
|
* @param refId the sequence dictionary index of the chromosome
|
|
26786
26814
|
* @param min genomic start position
|
|
26787
26815
|
* @param max genomic end position
|
|
26788
|
-
* @param return an array of {minv: {
|
|
26816
|
+
* @param return an array of objects representing chunks (file spans) {minv: {block, offset}, {maxv: {block, offset}}
|
|
26789
26817
|
*/
|
|
26790
|
-
|
|
26818
|
+
chunksForRange(refId, min, max) {
|
|
26791
26819
|
const bam = this;
|
|
26792
26820
|
const ba = bam.indices[refId];
|
|
26793
26821
|
if (!ba) {
|
|
26794
26822
|
return [];
|
|
26795
26823
|
} else {
|
|
26796
26824
|
const overlappingBins = reg2bins(min, max); // List of bin #s that overlap min, max
|
|
26797
|
-
const chunks = [];
|
|
26798
26825
|
|
|
26826
|
+
//console.log("bin ranges")
|
|
26827
|
+
//for(let b of overlappingBins) {
|
|
26828
|
+
// console.log(`${b[0]} - ${b[1]}`)
|
|
26829
|
+
//}
|
|
26830
|
+
|
|
26831
|
+
const chunks = [];
|
|
26799
26832
|
// Find chunks in overlapping bins. Leaf bins (< 4681) are not pruned
|
|
26800
26833
|
for (let binRange of overlappingBins) {
|
|
26801
26834
|
for (let bin = binRange[0]; bin <= binRange[1]; bin++) {
|
|
@@ -26806,8 +26839,7 @@
|
|
|
26806
26839
|
const ce = c[1];
|
|
26807
26840
|
chunks.push({
|
|
26808
26841
|
minv: cs,
|
|
26809
|
-
maxv: ce
|
|
26810
|
-
bin: bin
|
|
26842
|
+
maxv: ce
|
|
26811
26843
|
});
|
|
26812
26844
|
}
|
|
26813
26845
|
}
|
|
@@ -26816,65 +26848,20 @@
|
|
|
26816
26848
|
|
|
26817
26849
|
// Use the linear index to find minimum file position of chunks that could contain alignments in the region
|
|
26818
26850
|
const nintv = ba.linearIndex.length;
|
|
26819
|
-
let lowest
|
|
26820
|
-
const minLin = Math.min(min >> 14, nintv - 1);
|
|
26851
|
+
let lowest;
|
|
26852
|
+
const minLin = Math.min(min >> 14, nintv - 1); // i.e. min / 16384
|
|
26821
26853
|
const maxLin = Math.min(max >> 14, nintv - 1);
|
|
26822
|
-
for (let i = minLin; i
|
|
26854
|
+
for (let i = minLin; i <= maxLin; i++) {
|
|
26823
26855
|
const vp = ba.linearIndex[i];
|
|
26824
26856
|
if (vp) {
|
|
26825
|
-
|
|
26826
|
-
|
|
26827
|
-
lowest = vp;
|
|
26828
|
-
}
|
|
26857
|
+
lowest = vp; // lowest file offset that contains alignments overlapping (min, max)
|
|
26858
|
+
break;
|
|
26829
26859
|
}
|
|
26830
26860
|
}
|
|
26831
26861
|
return optimizeChunks(chunks, lowest);
|
|
26832
26862
|
}
|
|
26833
26863
|
}
|
|
26834
26864
|
}
|
|
26835
|
-
function optimizeChunks(chunks, lowest) {
|
|
26836
|
-
const mergedChunks = [];
|
|
26837
|
-
let lastChunk = null;
|
|
26838
|
-
if (chunks.length === 0) return chunks;
|
|
26839
|
-
chunks.sort(function (c0, c1) {
|
|
26840
|
-
const dif = c0.minv.block - c1.minv.block;
|
|
26841
|
-
if (dif !== 0) {
|
|
26842
|
-
return dif;
|
|
26843
|
-
} else {
|
|
26844
|
-
return c0.minv.offset - c1.minv.offset;
|
|
26845
|
-
}
|
|
26846
|
-
});
|
|
26847
|
-
chunks.forEach(function (chunk) {
|
|
26848
|
-
if (!lowest || chunk.maxv.isGreaterThan(lowest)) {
|
|
26849
|
-
if (lastChunk === null) {
|
|
26850
|
-
mergedChunks.push(chunk);
|
|
26851
|
-
lastChunk = chunk;
|
|
26852
|
-
} else {
|
|
26853
|
-
if (canMerge(lastChunk, chunk)) {
|
|
26854
|
-
if (chunk.maxv.isGreaterThan(lastChunk.maxv)) {
|
|
26855
|
-
lastChunk.maxv = chunk.maxv;
|
|
26856
|
-
}
|
|
26857
|
-
} else {
|
|
26858
|
-
mergedChunks.push(chunk);
|
|
26859
|
-
lastChunk = chunk;
|
|
26860
|
-
}
|
|
26861
|
-
}
|
|
26862
|
-
}
|
|
26863
|
-
});
|
|
26864
|
-
return mergedChunks;
|
|
26865
|
-
}
|
|
26866
|
-
|
|
26867
|
-
/**
|
|
26868
|
-
* Merge 2 blocks if the gap between them is < 1kb and the total resulting size < 100mb
|
|
26869
|
-
* @param chunk1
|
|
26870
|
-
* @param chunk2
|
|
26871
|
-
* @returns {boolean|boolean}
|
|
26872
|
-
*/
|
|
26873
|
-
function canMerge(chunk1, chunk2) {
|
|
26874
|
-
const gap = chunk2.minv.block - chunk1.maxv.block;
|
|
26875
|
-
const total = chunk2.maxv.block - chunk1.minv.block;
|
|
26876
|
-
return gap < 30000 && total < 10 * MB;
|
|
26877
|
-
}
|
|
26878
26865
|
|
|
26879
26866
|
/**
|
|
26880
26867
|
* Calculate the list of bins that overlap with region [beg, end]
|
|
@@ -27006,7 +26993,7 @@
|
|
|
27006
26993
|
* @param min genomic start position
|
|
27007
26994
|
* @param max genomic end position
|
|
27008
26995
|
*/
|
|
27009
|
-
|
|
26996
|
+
chunksForRange(queryChr, min, max) {
|
|
27010
26997
|
const chrIdx = this.chrIndex[queryChr];
|
|
27011
26998
|
if (chrIdx) {
|
|
27012
26999
|
const blocks = chrIdx.blocks;
|
|
@@ -27166,7 +27153,12 @@
|
|
|
27166
27153
|
}
|
|
27167
27154
|
}
|
|
27168
27155
|
|
|
27169
|
-
|
|
27156
|
+
/**
|
|
27157
|
+
* Class to iterate line-by-line over a BGZipped text file. This class is useful for iterating from the start of
|
|
27158
|
+
* the file. Not useful for indexed queries.
|
|
27159
|
+
*/
|
|
27160
|
+
|
|
27161
|
+
class BGZLineReader {
|
|
27170
27162
|
constructor(config) {
|
|
27171
27163
|
this.config = config;
|
|
27172
27164
|
this.filePtr = 0;
|
|
@@ -27206,7 +27198,7 @@
|
|
|
27206
27198
|
}
|
|
27207
27199
|
});
|
|
27208
27200
|
const abuffer = await igvxhr.loadArrayBuffer(this.config.url, bsizeOptions);
|
|
27209
|
-
const bufferSize = bgzBlockSize(abuffer);
|
|
27201
|
+
const bufferSize = bgzBlockSize$1(abuffer);
|
|
27210
27202
|
//console.log(`next block ${this.filePtr} ${bufferSize}`);
|
|
27211
27203
|
|
|
27212
27204
|
if (bufferSize === 0) {
|
|
@@ -27231,6 +27223,244 @@
|
|
|
27231
27223
|
}
|
|
27232
27224
|
}
|
|
27233
27225
|
|
|
27226
|
+
function concatenateArrayBuffers(arrayBuffers) {
|
|
27227
|
+
if (arrayBuffers.length === 1) {
|
|
27228
|
+
return arrayBuffers[0];
|
|
27229
|
+
}
|
|
27230
|
+
let len = 0;
|
|
27231
|
+
for (const b of arrayBuffers) {
|
|
27232
|
+
len += b.byteLength;
|
|
27233
|
+
}
|
|
27234
|
+
const c = new Uint8Array(len);
|
|
27235
|
+
let offset = 0;
|
|
27236
|
+
for (const b of arrayBuffers) {
|
|
27237
|
+
c.set(new Uint8Array(b), offset);
|
|
27238
|
+
offset += b.byteLength;
|
|
27239
|
+
}
|
|
27240
|
+
return c.buffer;
|
|
27241
|
+
}
|
|
27242
|
+
|
|
27243
|
+
/**
|
|
27244
|
+
* Return the block size for the data buffer.
|
|
27245
|
+
* @param data
|
|
27246
|
+
* @returns {number}
|
|
27247
|
+
*/
|
|
27248
|
+
const bgzBlockSize = data => {
|
|
27249
|
+
const ba = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
|
|
27250
|
+
const bsize = (ba[17] << 8 | ba[16]) + 1;
|
|
27251
|
+
return bsize;
|
|
27252
|
+
};
|
|
27253
|
+
class BGZBlockLoader {
|
|
27254
|
+
constructor(config) {
|
|
27255
|
+
this.config = config;
|
|
27256
|
+
this.cacheBlocks = false != config.cacheBlocks; // Default to true
|
|
27257
|
+
this.cache = undefined;
|
|
27258
|
+
}
|
|
27259
|
+
|
|
27260
|
+
/**
|
|
27261
|
+
* Return inflated data from startBlock through endBlock as an UInt8Array
|
|
27262
|
+
*
|
|
27263
|
+
* @param startBlock
|
|
27264
|
+
* @param endBlock
|
|
27265
|
+
* @returns {Promise<Uint8Array>}
|
|
27266
|
+
*/
|
|
27267
|
+
async getData(startBlock, endBlock) {
|
|
27268
|
+
const blocks = await this.getInflatedBlocks(startBlock, endBlock);
|
|
27269
|
+
if (blocks.length === 1) {
|
|
27270
|
+
return blocks[0];
|
|
27271
|
+
}
|
|
27272
|
+
let len = 0;
|
|
27273
|
+
for (const b of blocks) {
|
|
27274
|
+
len += b.byteLength;
|
|
27275
|
+
}
|
|
27276
|
+
const c = new Uint8Array(len);
|
|
27277
|
+
let offset = 0;
|
|
27278
|
+
for (const b of blocks) {
|
|
27279
|
+
c.set(b, offset);
|
|
27280
|
+
offset += b.byteLength;
|
|
27281
|
+
}
|
|
27282
|
+
return c;
|
|
27283
|
+
}
|
|
27284
|
+
|
|
27285
|
+
/**
|
|
27286
|
+
* Return the inflated data for the specified blocks as an array of Uint8Arrays. This method is public so
|
|
27287
|
+
* it can be unit tested. *
|
|
27288
|
+
* @param startBlock
|
|
27289
|
+
* @param endBlock
|
|
27290
|
+
* @returns {Promise<*[Uint8Array]>}
|
|
27291
|
+
*/
|
|
27292
|
+
async getInflatedBlocks(startBlock, endBlock) {
|
|
27293
|
+
if (!this.cacheBlocks) {
|
|
27294
|
+
const buffer = await this.loadBLockData(startBlock, endBlock);
|
|
27295
|
+
return inflateBlocks(buffer);
|
|
27296
|
+
} else {
|
|
27297
|
+
const c = this.cache;
|
|
27298
|
+
if (c && c.startBlock <= startBlock && c.endBlock >= endBlock) {
|
|
27299
|
+
//console.log("Complete overlap")
|
|
27300
|
+
const startOffset = startBlock - c.startBlock;
|
|
27301
|
+
const endOffset = endBlock - c.startBlock;
|
|
27302
|
+
return inflateBlocks(c.buffer, startOffset, endOffset);
|
|
27303
|
+
// Don't update cache, still valid
|
|
27304
|
+
} else {
|
|
27305
|
+
let buffer;
|
|
27306
|
+
if (!c || c.startBlock > endBlock || c.endBlock < startBlock) {
|
|
27307
|
+
// no overlap with cache
|
|
27308
|
+
buffer = await this.loadBLockData(startBlock, endBlock);
|
|
27309
|
+
} else {
|
|
27310
|
+
//console.log("Some overlap")
|
|
27311
|
+
const arrayBuffers = [];
|
|
27312
|
+
|
|
27313
|
+
// Load blocks preceding cache start, if any
|
|
27314
|
+
if (startBlock < c.startBlock) {
|
|
27315
|
+
// load first blocks
|
|
27316
|
+
const startBuffer = await this.loadBLockData(startBlock, c.startBlock, {
|
|
27317
|
+
skipEnd: true
|
|
27318
|
+
});
|
|
27319
|
+
arrayBuffers.push(startBuffer);
|
|
27320
|
+
}
|
|
27321
|
+
|
|
27322
|
+
// Slice cached buffer as needed
|
|
27323
|
+
let cachedBuffer;
|
|
27324
|
+
if (startBlock <= c.startBlock && endBlock >= c.endBlock) {
|
|
27325
|
+
cachedBuffer = c.buffer;
|
|
27326
|
+
} else {
|
|
27327
|
+
const start = Math.max(0, startBlock - c.startBlock);
|
|
27328
|
+
let end;
|
|
27329
|
+
if (endBlock >= c.endBlock) {
|
|
27330
|
+
end = c.buffer.byteLength;
|
|
27331
|
+
} else {
|
|
27332
|
+
// We need to find the byte position of the end of "endBlock"
|
|
27333
|
+
const boundaries = findBlockBoundaries(c.buffer);
|
|
27334
|
+
for (let i = 0; i < boundaries.length - 1; i++) {
|
|
27335
|
+
if (c.startBlock + boundaries[i] === endBlock) {
|
|
27336
|
+
end = boundaries[i + 1];
|
|
27337
|
+
break;
|
|
27338
|
+
}
|
|
27339
|
+
}
|
|
27340
|
+
// Do something if end not found
|
|
27341
|
+
}
|
|
27342
|
+
|
|
27343
|
+
cachedBuffer = c.buffer.slice(start, end);
|
|
27344
|
+
}
|
|
27345
|
+
arrayBuffers.push(cachedBuffer);
|
|
27346
|
+
|
|
27347
|
+
// Load end blocks, if any
|
|
27348
|
+
if (endBlock > c.endBlock) {
|
|
27349
|
+
const endBuffer = await this.loadBLockData(c.endBlock, endBlock, {
|
|
27350
|
+
skipStart: true
|
|
27351
|
+
});
|
|
27352
|
+
arrayBuffers.push(endBuffer);
|
|
27353
|
+
}
|
|
27354
|
+
buffer = concatenateArrayBuffers(arrayBuffers);
|
|
27355
|
+
}
|
|
27356
|
+
this.cache = {
|
|
27357
|
+
startBlock,
|
|
27358
|
+
endBlock,
|
|
27359
|
+
buffer
|
|
27360
|
+
};
|
|
27361
|
+
return inflateBlocks(buffer);
|
|
27362
|
+
}
|
|
27363
|
+
}
|
|
27364
|
+
}
|
|
27365
|
+
async loadBLockData(startBlock, endBlock, options) {
|
|
27366
|
+
const config = this.config;
|
|
27367
|
+
const skipStart = options && options.skipStart;
|
|
27368
|
+
const skipEnd = options && options.skipEnd;
|
|
27369
|
+
|
|
27370
|
+
// Get size of last block if not skipped
|
|
27371
|
+
let lastBlockSize = 0;
|
|
27372
|
+
if (!skipEnd) {
|
|
27373
|
+
const bsizeOptions = buildOptions(config, {
|
|
27374
|
+
range: {
|
|
27375
|
+
start: endBlock,
|
|
27376
|
+
size: 26
|
|
27377
|
+
}
|
|
27378
|
+
});
|
|
27379
|
+
const abuffer = await igvxhr.loadArrayBuffer(config.url, bsizeOptions);
|
|
27380
|
+
lastBlockSize = bgzBlockSize(abuffer);
|
|
27381
|
+
}
|
|
27382
|
+
if (skipStart) {
|
|
27383
|
+
const bsizeOptions = buildOptions(config, {
|
|
27384
|
+
range: {
|
|
27385
|
+
start: startBlock,
|
|
27386
|
+
size: 26
|
|
27387
|
+
}
|
|
27388
|
+
});
|
|
27389
|
+
const abuffer = await igvxhr.loadArrayBuffer(config.url, bsizeOptions);
|
|
27390
|
+
startBlock += bgzBlockSize(abuffer);
|
|
27391
|
+
}
|
|
27392
|
+
|
|
27393
|
+
// Load data for all blocks
|
|
27394
|
+
const loadOptions = buildOptions(config, {
|
|
27395
|
+
range: {
|
|
27396
|
+
start: startBlock,
|
|
27397
|
+
size: endBlock + lastBlockSize - startBlock
|
|
27398
|
+
}
|
|
27399
|
+
});
|
|
27400
|
+
|
|
27401
|
+
//console.log(`${this.config.name} Loaded ${startBlock} - ${endBlock + lastBlockSize} (${(endBlock + lastBlockSize - startBlock) / 1000} kb)`)
|
|
27402
|
+
|
|
27403
|
+
return igvxhr.loadArrayBuffer(config.url, loadOptions);
|
|
27404
|
+
}
|
|
27405
|
+
}
|
|
27406
|
+
function findBlockBoundaries(arrayBuffer) {
|
|
27407
|
+
const byteLengh = arrayBuffer.byteLength;
|
|
27408
|
+
let offset = 0;
|
|
27409
|
+
const blockBoundaries = [0];
|
|
27410
|
+
while (offset < byteLengh) {
|
|
27411
|
+
//console.log("Cache block " + offset)
|
|
27412
|
+
const ba = new Uint8Array(arrayBuffer, offset);
|
|
27413
|
+
const bsize = (ba[17] << 8 | ba[16]) + 1;
|
|
27414
|
+
offset += bsize;
|
|
27415
|
+
if (offset < byteLengh) {
|
|
27416
|
+
blockBoundaries.push(offset);
|
|
27417
|
+
}
|
|
27418
|
+
}
|
|
27419
|
+
return blockBoundaries;
|
|
27420
|
+
}
|
|
27421
|
+
|
|
27422
|
+
/**
|
|
27423
|
+
* Inflate compressed blocks within the data buffer*
|
|
27424
|
+
* @param data
|
|
27425
|
+
* @param startBlock - optional file location for start block. Default == 0
|
|
27426
|
+
* @param endBlock - optional file location for last block to decompress.
|
|
27427
|
+
* @returns {*[]}
|
|
27428
|
+
*/
|
|
27429
|
+
function inflateBlocks(data, startBlock, endBlock) {
|
|
27430
|
+
startBlock = startBlock || 0;
|
|
27431
|
+
const oBlockList = [];
|
|
27432
|
+
let ptr = startBlock;
|
|
27433
|
+
const lim = data.byteLength - 18;
|
|
27434
|
+
while (ptr < lim) {
|
|
27435
|
+
try {
|
|
27436
|
+
//console.log(113873 + ptr)
|
|
27437
|
+
const header = new Uint8Array(data, ptr, 18);
|
|
27438
|
+
const xlen = header[11] << 8 | header[10];
|
|
27439
|
+
const bsize = header[17] << 8 | header[16]; // Total block size, including header, minus 1
|
|
27440
|
+
const start = 12 + xlen + ptr; // Start of CDATA
|
|
27441
|
+
const bytesLeft = data.byteLength - start;
|
|
27442
|
+
const cDataSize = bsize - xlen - 18;
|
|
27443
|
+
if (bytesLeft < cDataSize || cDataSize <= 0) {
|
|
27444
|
+
// This is unexpected. Throw error?
|
|
27445
|
+
break;
|
|
27446
|
+
}
|
|
27447
|
+
const cdata = new Uint8Array(data, start, cDataSize);
|
|
27448
|
+
const unc = inflateRaw(cdata);
|
|
27449
|
+
oBlockList.push(unc);
|
|
27450
|
+
if (endBlock === ptr) {
|
|
27451
|
+
break;
|
|
27452
|
+
} else {
|
|
27453
|
+
// Advance to next block
|
|
27454
|
+
ptr += bsize + 1;
|
|
27455
|
+
}
|
|
27456
|
+
} catch (e) {
|
|
27457
|
+
console.error(e);
|
|
27458
|
+
break;
|
|
27459
|
+
}
|
|
27460
|
+
}
|
|
27461
|
+
return oBlockList;
|
|
27462
|
+
}
|
|
27463
|
+
|
|
27234
27464
|
/*
|
|
27235
27465
|
* The MIT License (MIT)
|
|
27236
27466
|
*
|
|
@@ -27332,7 +27562,8 @@
|
|
|
27332
27562
|
}
|
|
27333
27563
|
let dataWrapper;
|
|
27334
27564
|
if (index.tabix) {
|
|
27335
|
-
|
|
27565
|
+
this._blockLoader = new BGZBlockLoader(this.config);
|
|
27566
|
+
dataWrapper = new BGZLineReader(this.config);
|
|
27336
27567
|
} else {
|
|
27337
27568
|
// Tribble
|
|
27338
27569
|
const maxSize = Object.values(index.chrIndex).flatMap(chr => chr.blocks).map(block => block.max).reduce((previous, current) => Math.min(previous, current), Number.MAX_SAFE_INTEGER);
|
|
@@ -27408,46 +27639,25 @@
|
|
|
27408
27639
|
return [];
|
|
27409
27640
|
}
|
|
27410
27641
|
const genome = this.genome;
|
|
27411
|
-
const
|
|
27412
|
-
if (!
|
|
27642
|
+
const chunks = this.index.chunksForRange(refId, start, end);
|
|
27643
|
+
if (!chunks || chunks.length === 0) {
|
|
27413
27644
|
return [];
|
|
27414
27645
|
} else {
|
|
27415
27646
|
const allFeatures = [];
|
|
27416
|
-
for (let
|
|
27417
|
-
const startPos = block.minv.block;
|
|
27418
|
-
const startOffset = block.minv.offset;
|
|
27419
|
-
const endOffset = block.maxv.offset;
|
|
27420
|
-
let endPos;
|
|
27421
|
-
if (tabix) {
|
|
27422
|
-
let lastBlockSize = 0;
|
|
27423
|
-
if (endOffset > 0) {
|
|
27424
|
-
const bsizeOptions = buildOptions(config, {
|
|
27425
|
-
range: {
|
|
27426
|
-
start: block.maxv.block,
|
|
27427
|
-
size: 26
|
|
27428
|
-
}
|
|
27429
|
-
});
|
|
27430
|
-
const abuffer = await igvxhr.loadArrayBuffer(config.url, bsizeOptions);
|
|
27431
|
-
lastBlockSize = bgzBlockSize(abuffer);
|
|
27432
|
-
}
|
|
27433
|
-
endPos = block.maxv.block + lastBlockSize;
|
|
27434
|
-
} else {
|
|
27435
|
-
endPos = block.maxv.block;
|
|
27436
|
-
}
|
|
27437
|
-
const options = buildOptions(config, {
|
|
27438
|
-
range: {
|
|
27439
|
-
start: startPos,
|
|
27440
|
-
size: endPos - startPos + 1
|
|
27441
|
-
}
|
|
27442
|
-
});
|
|
27647
|
+
for (let chunk of chunks) {
|
|
27443
27648
|
let inflated;
|
|
27444
27649
|
if (tabix) {
|
|
27445
|
-
|
|
27446
|
-
inflated = unbgzf(data);
|
|
27650
|
+
inflated = await this._blockLoader.getData(chunk.minv.block, chunk.maxv.block);
|
|
27447
27651
|
} else {
|
|
27652
|
+
const options = buildOptions(config, {
|
|
27653
|
+
range: {
|
|
27654
|
+
start: chunk.minv.block,
|
|
27655
|
+
size: chunk.maxv.block - chunk.minv.block + 1
|
|
27656
|
+
}
|
|
27657
|
+
});
|
|
27448
27658
|
inflated = await igvxhr.loadString(config.url, options);
|
|
27449
27659
|
}
|
|
27450
|
-
const slicedData =
|
|
27660
|
+
const slicedData = chunk.minv.offset ? inflated.slice(chunk.minv.offset) : inflated;
|
|
27451
27661
|
const dataWrapper = getDataWrapper(slicedData);
|
|
27452
27662
|
let slicedFeatures = await parser.parseFeatures(dataWrapper);
|
|
27453
27663
|
|
|
@@ -29873,6 +30083,7 @@
|
|
|
29873
30083
|
var documentAll$2 = typeof document == 'object' && document.all;
|
|
29874
30084
|
|
|
29875
30085
|
// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
|
|
30086
|
+
// eslint-disable-next-line unicorn/no-typeof-undefined -- required for testing
|
|
29876
30087
|
var IS_HTMLDDA = typeof documentAll$2 == 'undefined' && documentAll$2 !== undefined;
|
|
29877
30088
|
var documentAll_1 = {
|
|
29878
30089
|
all: documentAll$2,
|
|
@@ -30127,10 +30338,10 @@
|
|
|
30127
30338
|
(module.exports = function (key, value) {
|
|
30128
30339
|
return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {});
|
|
30129
30340
|
})('versions', []).push({
|
|
30130
|
-
version: '3.
|
|
30341
|
+
version: '3.27.1',
|
|
30131
30342
|
mode: 'global',
|
|
30132
30343
|
copyright: '© 2014-2022 Denis Pushkarev (zloirock.ru)',
|
|
30133
|
-
license: 'https://github.com/zloirock/core-js/blob/v3.
|
|
30344
|
+
license: 'https://github.com/zloirock/core-js/blob/v3.27.1/LICENSE',
|
|
30134
30345
|
source: 'https://github.com/zloirock/core-js'
|
|
30135
30346
|
});
|
|
30136
30347
|
});
|
|
@@ -33368,6 +33579,7 @@
|
|
|
33368
33579
|
this.bamPath = config.url;
|
|
33369
33580
|
this.baiPath = config.indexURL;
|
|
33370
33581
|
BamUtils.setReaderDefaults(this, config);
|
|
33582
|
+
this._blockLoader = new BGZBlockLoader(config);
|
|
33371
33583
|
}
|
|
33372
33584
|
async readAlignments(chr, bpStart, bpEnd) {
|
|
33373
33585
|
const chrToIndex = await this.getChrIndex();
|
|
@@ -33378,37 +33590,14 @@
|
|
|
33378
33590
|
return alignmentContainer;
|
|
33379
33591
|
} else {
|
|
33380
33592
|
const bamIndex = await this.getIndex();
|
|
33381
|
-
const chunks = bamIndex.
|
|
33593
|
+
const chunks = bamIndex.chunksForRange(chrId, bpStart, bpEnd);
|
|
33382
33594
|
if (!chunks || chunks.length === 0) {
|
|
33383
33595
|
return alignmentContainer;
|
|
33384
33596
|
}
|
|
33385
33597
|
for (let c of chunks) {
|
|
33386
|
-
|
|
33387
|
-
if (c.maxv.offset === 0) {
|
|
33388
|
-
lastBlockSize = 0; // Don't need to read the last block.
|
|
33389
|
-
} else {
|
|
33390
|
-
const bsizeOptions = buildOptions(this.config, {
|
|
33391
|
-
range: {
|
|
33392
|
-
start: c.maxv.block,
|
|
33393
|
-
size: 26
|
|
33394
|
-
}
|
|
33395
|
-
});
|
|
33396
|
-
const abuffer = await igvxhr.loadArrayBuffer(this.bamPath, bsizeOptions);
|
|
33397
|
-
lastBlockSize = bgzBlockSize(abuffer);
|
|
33398
|
-
}
|
|
33399
|
-
const fetchMin = c.minv.block;
|
|
33400
|
-
const fetchMax = c.maxv.block + lastBlockSize;
|
|
33401
|
-
const range = {
|
|
33402
|
-
start: fetchMin,
|
|
33403
|
-
size: fetchMax - fetchMin + 1
|
|
33404
|
-
};
|
|
33405
|
-
const compressed = await igvxhr.loadArrayBuffer(this.bamPath, buildOptions(this.config, {
|
|
33406
|
-
range: range
|
|
33407
|
-
}));
|
|
33408
|
-
var ba = unbgzf(compressed); //new Uint8Array(BGZip.unbgzf(compressed)); //, c.maxv.block - c.minv.block + 1));
|
|
33598
|
+
const ba = await this._blockLoader.getData(c.minv.block, c.maxv.block);
|
|
33409
33599
|
const done = BamUtils.decodeBamRecords(ba, c.minv.offset, alignmentContainer, this.indexToChr, chrId, bpStart, bpEnd, this.filter);
|
|
33410
33600
|
if (done) {
|
|
33411
|
-
// console.log(`Loaded ${counter} chunks out of ${chunks.length}`);
|
|
33412
33601
|
break;
|
|
33413
33602
|
}
|
|
33414
33603
|
}
|
|
@@ -33429,7 +33618,7 @@
|
|
|
33429
33618
|
}
|
|
33430
33619
|
});
|
|
33431
33620
|
const abuffer = await igvxhr.loadArrayBuffer(this.bamPath, bsizeOptions);
|
|
33432
|
-
const bsize = bgzBlockSize(abuffer);
|
|
33621
|
+
const bsize = bgzBlockSize$1(abuffer);
|
|
33433
33622
|
len = index.firstBlockPosition + bsize; // Insure we get the complete compressed block containing the header
|
|
33434
33623
|
} else {
|
|
33435
33624
|
len = 64000;
|
|
@@ -33967,7 +34156,7 @@
|
|
|
33967
34156
|
var clear = global$1.clearImmediate;
|
|
33968
34157
|
var process$1 = global$1.process;
|
|
33969
34158
|
var Dispatch = global$1.Dispatch;
|
|
33970
|
-
var Function$
|
|
34159
|
+
var Function$2 = global$1.Function;
|
|
33971
34160
|
var MessageChannel$1 = global$1.MessageChannel;
|
|
33972
34161
|
var String$1 = global$1.String;
|
|
33973
34162
|
var counter = 0;
|
|
@@ -34002,7 +34191,7 @@
|
|
|
34002
34191
|
if (!set || !clear) {
|
|
34003
34192
|
set = function setImmediate(handler) {
|
|
34004
34193
|
validateArgumentsLength(arguments.length, 1);
|
|
34005
|
-
var fn = isCallable(handler) ? handler : Function$
|
|
34194
|
+
var fn = isCallable(handler) ? handler : Function$2(handler);
|
|
34006
34195
|
var args = arraySlice(arguments, 1);
|
|
34007
34196
|
queue[++counter] = function () {
|
|
34008
34197
|
functionApply(fn, undefined, args);
|
|
@@ -34068,7 +34257,36 @@
|
|
|
34068
34257
|
clearImmediate: clearImmediate
|
|
34069
34258
|
});
|
|
34070
34259
|
|
|
34071
|
-
|
|
34260
|
+
/* global Bun -- Deno case */
|
|
34261
|
+
var engineIsBun = typeof Bun == 'function' && Bun && typeof Bun.version == 'string';
|
|
34262
|
+
|
|
34263
|
+
var Function$1 = global$1.Function;
|
|
34264
|
+
// dirty IE9- and Bun 0.3.0- checks
|
|
34265
|
+
var WRAP = /MSIE .\./.test(engineUserAgent) || engineIsBun && function () {
|
|
34266
|
+
var version = global$1.Bun.version.split('.');
|
|
34267
|
+
return version.length < 3 || version[0] == 0 && (version[1] < 3 || version[1] == 3 && version[2] == 0);
|
|
34268
|
+
}();
|
|
34269
|
+
|
|
34270
|
+
// IE9- / Bun 0.3.0- setTimeout / setInterval / setImmediate additional parameters fix
|
|
34271
|
+
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers
|
|
34272
|
+
// https://github.com/oven-sh/bun/issues/1633
|
|
34273
|
+
var schedulersFix = function (scheduler, hasTimeArg) {
|
|
34274
|
+
var firstParamIndex = hasTimeArg ? 2 : 1;
|
|
34275
|
+
return WRAP ? function (handler, timeout /* , ...arguments */) {
|
|
34276
|
+
var boundArgs = validateArgumentsLength(arguments.length, 1) > firstParamIndex;
|
|
34277
|
+
var fn = isCallable(handler) ? handler : Function$1(handler);
|
|
34278
|
+
var params = boundArgs ? arraySlice(arguments, firstParamIndex) : [];
|
|
34279
|
+
var callback = boundArgs ? function () {
|
|
34280
|
+
functionApply(fn, this, params);
|
|
34281
|
+
} : fn;
|
|
34282
|
+
return hasTimeArg ? scheduler(callback, timeout) : scheduler(callback);
|
|
34283
|
+
} : scheduler;
|
|
34284
|
+
};
|
|
34285
|
+
|
|
34286
|
+
var setTask = task.set;
|
|
34287
|
+
|
|
34288
|
+
// https://github.com/oven-sh/bun/issues/1633
|
|
34289
|
+
var setImmediate = global$1.setImmediate ? schedulersFix(setTask, false) : setTask;
|
|
34072
34290
|
|
|
34073
34291
|
// `setImmediate` method
|
|
34074
34292
|
// http://w3c.github.io/setImmediate/#si-setImmediate
|
|
@@ -50411,7 +50629,9 @@
|
|
|
50411
50629
|
hoverText(clickState) {
|
|
50412
50630
|
if (true === this.showCoverage && clickState.y >= this.coverageTrack.top && clickState.y < this.coverageTrack.height) {
|
|
50413
50631
|
const clickedObject = this.coverageTrack.getClickedObject(clickState);
|
|
50414
|
-
|
|
50632
|
+
if (clickedObject) {
|
|
50633
|
+
return clickedObject.hoverText();
|
|
50634
|
+
}
|
|
50415
50635
|
}
|
|
50416
50636
|
}
|
|
50417
50637
|
menuItemList() {
|
|
@@ -52753,7 +52973,14 @@
|
|
|
52753
52973
|
value: max
|
|
52754
52974
|
}];
|
|
52755
52975
|
} else {
|
|
52756
|
-
|
|
52976
|
+
const viewFeatures = FeatureUtils.findOverlapping(visibleViewport.featureCache.features, start, end);
|
|
52977
|
+
if (!allFeatures) {
|
|
52978
|
+
allFeatures = viewFeatures;
|
|
52979
|
+
} else {
|
|
52980
|
+
for (let f of viewFeatures) {
|
|
52981
|
+
allFeatures.push(f);
|
|
52982
|
+
}
|
|
52983
|
+
}
|
|
52757
52984
|
}
|
|
52758
52985
|
}
|
|
52759
52986
|
}
|
|
@@ -56669,21 +56896,16 @@
|
|
|
56669
56896
|
* Colors used for coding omosomes
|
|
56670
56897
|
*/
|
|
56671
56898
|
|
|
56672
|
-
const
|
|
56899
|
+
const GWASColors = {
|
|
56673
56900
|
"X": "rgb(204, 153, 0)",
|
|
56674
56901
|
"Y": "rgb(153, 204, 0)",
|
|
56675
56902
|
"Un": "darkGray)",
|
|
56676
56903
|
"1": "rgb(80, 80, 255)",
|
|
56677
|
-
//"1": Color.red);
|
|
56678
|
-
"I": "rgb(139, 155, 187)",
|
|
56679
56904
|
"2": "rgb(206, 61, 50)",
|
|
56680
|
-
"II": "rgb(206, 61, 50)",
|
|
56681
56905
|
"2a": "rgb(210, 65, 55)",
|
|
56682
56906
|
"2b": "rgb(215, 70, 60)",
|
|
56683
56907
|
"3": "rgb(116, 155, 88)",
|
|
56684
|
-
"III": "rgb(116, 155, 88)",
|
|
56685
56908
|
"4": "rgb(240, 230, 133)",
|
|
56686
|
-
"IV": "rgb(240, 230, 133)",
|
|
56687
56909
|
"5": "rgb(70, 105, 131)",
|
|
56688
56910
|
"6": "rgb(186, 99, 56)",
|
|
56689
56911
|
"7": "rgb(93, 177, 221)",
|
|
@@ -56731,9 +56953,25 @@
|
|
|
56731
56953
|
};
|
|
56732
56954
|
|
|
56733
56955
|
// aliasing
|
|
56734
|
-
for (let key of Object.keys(
|
|
56956
|
+
for (let key of Object.keys(GWASColors)) {
|
|
56735
56957
|
const altName = "chr" + key;
|
|
56736
|
-
|
|
56958
|
+
GWASColors[altName] = GWASColors[key];
|
|
56959
|
+
}
|
|
56960
|
+
|
|
56961
|
+
// romanizing
|
|
56962
|
+
for (let a = 1; a <= 48; a++) {
|
|
56963
|
+
if (a === 10) continue; // Don't overide "X"
|
|
56964
|
+
const roman = romanize(a);
|
|
56965
|
+
GWASColors[roman] = GWASColors[a.toString()];
|
|
56966
|
+
}
|
|
56967
|
+
function romanize(num) {
|
|
56968
|
+
if (!+num) return false;
|
|
56969
|
+
var digits = String(+num).split('');
|
|
56970
|
+
var key = ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM', '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC', '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'];
|
|
56971
|
+
var roman = '',
|
|
56972
|
+
i = 3;
|
|
56973
|
+
while (i--) roman = (key[+digits.pop() + i * 10] || '') + roman;
|
|
56974
|
+
return Array(+digits.join('') + 1).join('M') + roman;
|
|
56737
56975
|
}
|
|
56738
56976
|
|
|
56739
56977
|
/*
|
|
@@ -56781,12 +57019,18 @@
|
|
|
56781
57019
|
this.divider = config.divider || "rgb(225,225,225)";
|
|
56782
57020
|
this.dotSize = config.dotSize || 3;
|
|
56783
57021
|
this.popoverWindow = config.popoverWindow === undefined ? DEFAULT_POPOVER_WINDOW : config.popoverWindow;
|
|
56784
|
-
|
|
56785
|
-
|
|
57022
|
+
|
|
57023
|
+
// Color settings
|
|
57024
|
+
if (this.useChrColors) {
|
|
57025
|
+
this.colorScale = new ColorTable(config.colorTable || GWASColors);
|
|
57026
|
+
} else if (config.color) {
|
|
57027
|
+
this.colorScale = new ConstantColorScale(config.color);
|
|
57028
|
+
} else {
|
|
57029
|
+
this.colorScale = new BinnedColorScale(config.colorScale || {
|
|
56786
57030
|
thresholds: [5e-8, 5e-4, 0.5],
|
|
56787
57031
|
colors: ["rgb(255,50,50)", "rgb(251,100,100)", "rgb(251,170,170)", "rgb(227,238,249)"]
|
|
56788
|
-
})
|
|
56789
|
-
}
|
|
57032
|
+
});
|
|
57033
|
+
}
|
|
56790
57034
|
this.featureSource = FeatureSource(config, this.browser.genome);
|
|
56791
57035
|
}
|
|
56792
57036
|
async postInit() {
|
|
@@ -56849,18 +57093,16 @@
|
|
|
56849
57093
|
const pos = variant.start;
|
|
56850
57094
|
if (pos < bpStart) continue;
|
|
56851
57095
|
if (pos > bpEnd) break;
|
|
56852
|
-
const colorScale = this.getColorScale(variant._f ? variant._f.chr : variant.chr);
|
|
56853
|
-
let color;
|
|
56854
57096
|
let val;
|
|
56855
57097
|
if (this.posteriorProbability) {
|
|
56856
57098
|
val = variant[this.valueProperty];
|
|
56857
|
-
color = colorScale.getColor(val);
|
|
56858
57099
|
} else {
|
|
56859
57100
|
const pvalue = variant[this.valueProperty];
|
|
56860
57101
|
if (!pvalue) continue;
|
|
56861
57102
|
val = -Math.log10(pvalue);
|
|
56862
|
-
color = colorScale.getColor(val);
|
|
56863
57103
|
}
|
|
57104
|
+
const colorKey = this.useChrColors ? variant._f ? variant._f.chr : variant.chr : val;
|
|
57105
|
+
const color = this.colorScale.getColor(colorKey);
|
|
56864
57106
|
const yScale = (this.dataRange.max - this.dataRange.min) / pixelHeight;
|
|
56865
57107
|
const px = Math.round((pos - bpStart) / bpPerPixel);
|
|
56866
57108
|
const py = Math.max(this.dotSize, pixelHeight - Math.round((val - this.dataRange.min) / yScale));
|
|
@@ -56876,19 +57118,6 @@
|
|
|
56876
57118
|
}
|
|
56877
57119
|
}
|
|
56878
57120
|
}
|
|
56879
|
-
getColorScale(chr) {
|
|
56880
|
-
if (this.useChrColors) {
|
|
56881
|
-
let cs = this.colorScales[chr];
|
|
56882
|
-
if (!cs) {
|
|
56883
|
-
const color = Colors[chr] || randomColor();
|
|
56884
|
-
cs = new ConstantColorScale(color);
|
|
56885
|
-
this.colorScales[chr] = cs;
|
|
56886
|
-
}
|
|
56887
|
-
return cs;
|
|
56888
|
-
} else {
|
|
56889
|
-
return this.colorScales("*");
|
|
56890
|
-
}
|
|
56891
|
-
}
|
|
56892
57121
|
paintAxis(ctx, pixelWidth, pixelHeight) {
|
|
56893
57122
|
IGVGraphics.fillRect(ctx, 0, 0, pixelWidth, pixelHeight, {
|
|
56894
57123
|
'fillStyle': "rgb(255, 255, 255)"
|
|
@@ -57001,11 +57230,15 @@
|
|
|
57001
57230
|
} else {
|
|
57002
57231
|
// No features -- pick something reasonable for PPAs and p-values
|
|
57003
57232
|
if (this.posteriorProbability) {
|
|
57004
|
-
this.dataRange
|
|
57005
|
-
|
|
57233
|
+
this.dataRange = {
|
|
57234
|
+
min: this.config.min || 0,
|
|
57235
|
+
max: this.config.max || 1
|
|
57236
|
+
};
|
|
57006
57237
|
} else {
|
|
57007
|
-
this.dataRange
|
|
57008
|
-
|
|
57238
|
+
this.dataRange = {
|
|
57239
|
+
min: this.config.max || 25,
|
|
57240
|
+
max: this.config.min || 0
|
|
57241
|
+
};
|
|
57009
57242
|
}
|
|
57010
57243
|
}
|
|
57011
57244
|
return this.dataRange;
|