igv 2.15.0 → 2.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/dist/igv.esm.js +689 -175
- package/dist/igv.esm.min.js +6 -6
- package/dist/igv.esm.min.js.map +1 -1
- package/dist/igv.js +689 -175
- package/dist/igv.min.js +6 -6
- package/dist/igv.min.js.map +1 -1
- package/package.json +2 -2
package/dist/igv.js
CHANGED
|
@@ -18662,6 +18662,8 @@
|
|
|
18662
18662
|
|
|
18663
18663
|
async _loadURL(url, options) {
|
|
18664
18664
|
|
|
18665
|
+
const self = this;
|
|
18666
|
+
|
|
18665
18667
|
//console.log(`${Date.now()} ${url}`)
|
|
18666
18668
|
url = mapUrl$1(url);
|
|
18667
18669
|
|
|
@@ -18751,7 +18753,7 @@
|
|
|
18751
18753
|
// For small files a range starting at 0 can return the whole file => 200
|
|
18752
18754
|
// Provide just the slice we asked for, throw out the rest quietly
|
|
18753
18755
|
// If file is large warn user
|
|
18754
|
-
if (xhr.response.length > 100000 && !
|
|
18756
|
+
if (xhr.response.length > 100000 && !self.RANGE_WARNING_GIVEN) {
|
|
18755
18757
|
alert(`Warning: Range header ignored for URL: ${url}. This can have severe performance impacts.`);
|
|
18756
18758
|
}
|
|
18757
18759
|
resolve(xhr.response.slice(range.start, range.start + range.size));
|
|
@@ -18780,8 +18782,9 @@
|
|
|
18780
18782
|
xhr.onerror = function (event) {
|
|
18781
18783
|
if (isGoogleURL(url) && !options.retries) {
|
|
18782
18784
|
tryGoogleAuth();
|
|
18785
|
+
} else {
|
|
18786
|
+
handleError("Error accessing resource: " + url + " Status: " + xhr.status);
|
|
18783
18787
|
}
|
|
18784
|
-
handleError("Error accessing resource: " + url + " Status: " + xhr.status);
|
|
18785
18788
|
};
|
|
18786
18789
|
|
|
18787
18790
|
xhr.ontimeout = function (event) {
|
|
@@ -18796,7 +18799,11 @@
|
|
|
18796
18799
|
try {
|
|
18797
18800
|
xhr.send(sendData);
|
|
18798
18801
|
} catch (e) {
|
|
18799
|
-
|
|
18802
|
+
if (isGoogleURL(url) && !options.retries) {
|
|
18803
|
+
tryGoogleAuth();
|
|
18804
|
+
} else {
|
|
18805
|
+
handleError(e);
|
|
18806
|
+
}
|
|
18800
18807
|
}
|
|
18801
18808
|
|
|
18802
18809
|
|
|
@@ -18813,7 +18820,7 @@
|
|
|
18813
18820
|
const accessToken = await fetchGoogleAccessToken(url);
|
|
18814
18821
|
options.retries = 1;
|
|
18815
18822
|
options.oauthToken = accessToken;
|
|
18816
|
-
const response = await
|
|
18823
|
+
const response = await self.load(url, options);
|
|
18817
18824
|
resolve(response);
|
|
18818
18825
|
} catch (e) {
|
|
18819
18826
|
if (e.error) {
|
|
@@ -18959,14 +18966,16 @@
|
|
|
18959
18966
|
*/
|
|
18960
18967
|
function mapUrl$1(url) {
|
|
18961
18968
|
|
|
18962
|
-
if (url.
|
|
18969
|
+
if (url.startsWith("https://www.dropbox.com")) {
|
|
18963
18970
|
return url.replace("//www.dropbox.com", "//dl.dropboxusercontent.com")
|
|
18964
|
-
} else if (url.
|
|
18971
|
+
} else if (url.startsWith("https://drive.google.com")) {
|
|
18965
18972
|
return getDriveDownloadURL(url)
|
|
18966
18973
|
} else if (url.includes("//www.broadinstitute.org/igvdata")) {
|
|
18967
18974
|
return url.replace("//www.broadinstitute.org/igvdata", "//data.broadinstitute.org/igvdata")
|
|
18968
18975
|
} else if (url.includes("//igvdata.broadinstitute.org")) {
|
|
18969
|
-
return url.replace("//igvdata.broadinstitute.org", "
|
|
18976
|
+
return url.replace("//igvdata.broadinstitute.org", "//s3.amazonaws.com/igv.broadinstitute.org")
|
|
18977
|
+
} else if (url.includes("//igv.genepattern.org")) {
|
|
18978
|
+
return url.replace("//igv.genepattern.org", "//igv-genepattern-org.s3.amazonaws.com")
|
|
18970
18979
|
} else if (url.startsWith("ftp://ftp.ncbi.nlm.nih.gov/geo")) {
|
|
18971
18980
|
return url.replace("ftp://", "https://")
|
|
18972
18981
|
} else {
|
|
@@ -23928,7 +23937,7 @@
|
|
|
23928
23937
|
}
|
|
23929
23938
|
};
|
|
23930
23939
|
|
|
23931
|
-
const _version = "2.15.
|
|
23940
|
+
const _version = "2.15.2";
|
|
23932
23941
|
function version() {
|
|
23933
23942
|
return _version
|
|
23934
23943
|
}
|
|
@@ -25765,15 +25774,15 @@
|
|
|
25765
25774
|
* @param keyValueDelim
|
|
25766
25775
|
* @returns {[]}
|
|
25767
25776
|
*/
|
|
25768
|
-
function parseAttributeString(attributeString, keyValueDelim) {
|
|
25777
|
+
function parseAttributeString(attributeString, keyValueDelim, relaxed = false) {
|
|
25769
25778
|
// parse 'attributes' string (see column 9 docs in https://github.com/The-Sequence-Ontology/Specifications/blob/master/gff3.md)
|
|
25770
25779
|
var attributes = [];
|
|
25771
25780
|
for (let kv of attributeString.split(';')) {
|
|
25772
25781
|
kv = kv.trim();
|
|
25773
25782
|
const idx = kv.indexOf(keyValueDelim);
|
|
25774
25783
|
if (idx > 0 && idx < kv.length - 1) {
|
|
25775
|
-
const key = kv.substring(0, idx);
|
|
25776
|
-
let value = stripQuotes(decodeGFFAttribute(kv.substring(idx + 1).trim()));
|
|
25784
|
+
const key = stripQuotes(decodeGFFAttribute(kv.substring(0, idx).trim(), relaxed));
|
|
25785
|
+
let value = stripQuotes(decodeGFFAttribute(kv.substring(idx + 1).trim(), relaxed));
|
|
25777
25786
|
attributes.push([key, value]);
|
|
25778
25787
|
}
|
|
25779
25788
|
}
|
|
@@ -25812,11 +25821,14 @@
|
|
|
25812
25821
|
["%2C", ","]
|
|
25813
25822
|
]);
|
|
25814
25823
|
|
|
25815
|
-
function decodeGFFAttribute(str) {
|
|
25824
|
+
function decodeGFFAttribute(str, relaxed = false) {
|
|
25816
25825
|
|
|
25817
25826
|
if (!str.includes("%")) {
|
|
25818
25827
|
return str
|
|
25819
25828
|
}
|
|
25829
|
+
if (relaxed) {
|
|
25830
|
+
return decodeURIComponent(str);
|
|
25831
|
+
}
|
|
25820
25832
|
let decoded = "";
|
|
25821
25833
|
for (let i = 0; i < str.length; i++) {
|
|
25822
25834
|
|
|
@@ -25874,7 +25886,7 @@
|
|
|
25874
25886
|
|
|
25875
25887
|
// Potentially parse name field as GFF column 9 style streng.
|
|
25876
25888
|
if (tokens[3].indexOf(';') > 0 && tokens[3].indexOf('=') > 0) {
|
|
25877
|
-
const attributeKVs = parseAttributeString(tokens[3], '=');
|
|
25889
|
+
const attributeKVs = parseAttributeString(tokens[3], '=', true);
|
|
25878
25890
|
feature.attributes = {};
|
|
25879
25891
|
for (let kv of attributeKVs) {
|
|
25880
25892
|
feature.attributes[kv[0]] = kv[1];
|
|
@@ -25922,7 +25934,25 @@
|
|
|
25922
25934
|
}
|
|
25923
25935
|
|
|
25924
25936
|
if (tokens.length > 11) {
|
|
25925
|
-
const
|
|
25937
|
+
const exonCount = parseInt(tokens[9]);
|
|
25938
|
+
// Some basic validation
|
|
25939
|
+
if (exonCount > 1000) {
|
|
25940
|
+
// unlikely
|
|
25941
|
+
return feature
|
|
25942
|
+
}
|
|
25943
|
+
|
|
25944
|
+
const exonSizes = tokens[10].replace(/,$/, '').split(',');
|
|
25945
|
+
const exonStarts = tokens[11].replace(/,$/, '').split(',');
|
|
25946
|
+
if (!(exonSizes.length === exonStarts.length && exonCount === exonSizes.length)) {
|
|
25947
|
+
return feature
|
|
25948
|
+
}
|
|
25949
|
+
|
|
25950
|
+
const exons = [];
|
|
25951
|
+
for (let i = 0; i < exonCount; i++) {
|
|
25952
|
+
const eStart = start + parseInt(exonStarts[i]);
|
|
25953
|
+
const eEnd = eStart + parseInt(exonSizes[i]);
|
|
25954
|
+
exons.push({start: eStart, end: eEnd});
|
|
25955
|
+
}
|
|
25926
25956
|
if (exons.length > 0) {
|
|
25927
25957
|
findUTRs$1(exons, feature.cdStart, feature.cdEnd);
|
|
25928
25958
|
feature.exons = exons;
|
|
@@ -25946,7 +25976,6 @@
|
|
|
25946
25976
|
}
|
|
25947
25977
|
|
|
25948
25978
|
return feature
|
|
25949
|
-
|
|
25950
25979
|
}
|
|
25951
25980
|
|
|
25952
25981
|
/**
|
|
@@ -27258,6 +27287,8 @@
|
|
|
27258
27287
|
}
|
|
27259
27288
|
tracklineConfg.autoscale = false;
|
|
27260
27289
|
tracklineConfg.dataRange = {min, max};
|
|
27290
|
+
this.viewLimitMin = min;
|
|
27291
|
+
this.viewLimitMax = max;
|
|
27261
27292
|
}
|
|
27262
27293
|
case "name":
|
|
27263
27294
|
tracklineConfg[key] = properties[key];
|
|
@@ -29156,9 +29187,9 @@
|
|
|
29156
29187
|
* @returns {boolean|boolean}
|
|
29157
29188
|
*/
|
|
29158
29189
|
function canMerge(chunk1, chunk2) {
|
|
29159
|
-
|
|
29190
|
+
chunk2.minv.block - chunk1.maxv.block;
|
|
29160
29191
|
const sizeEstimate = chunk1.maxv.block - chunk1.minv.block;
|
|
29161
|
-
return
|
|
29192
|
+
return sizeEstimate < 5000000
|
|
29162
29193
|
}
|
|
29163
29194
|
|
|
29164
29195
|
// Represents a CSI Bam or Tabix index
|
|
@@ -40781,8 +40812,8 @@
|
|
|
40781
40812
|
color = IGVColor.addAlpha(color, feature.alpha);
|
|
40782
40813
|
} else if (this.useScore && feature.score && !Number.isNaN(feature.score)) {
|
|
40783
40814
|
// UCSC useScore option, for scores between 0-1000. See https://genome.ucsc.edu/goldenPath/help/customTrack.html#TRACK
|
|
40784
|
-
const min = this.config.min ? this.config.min : 0;
|
|
40785
|
-
const max = this.config.max ? this.config.max : 1000;
|
|
40815
|
+
const min = this.config.min ? this.config.min : this.viewLimitMin ? this.viewLimitMin : 0;
|
|
40816
|
+
const max = this.config.max ? this.config.max : this.viewLimitMax ? this.viewLimitMax : 1000;
|
|
40786
40817
|
const alpha = getAlpha(min, max, feature.score);
|
|
40787
40818
|
feature.alpha = alpha; // Avoid computing again
|
|
40788
40819
|
color = IGVColor.addAlpha(color, alpha);
|
|
@@ -54151,11 +54182,13 @@
|
|
|
54151
54182
|
|
|
54152
54183
|
// console.log(h5_obj_keys)
|
|
54153
54184
|
let signal_bin = new ParseSignals(h5_obj_keys);
|
|
54154
|
-
|
|
54185
|
+
let rd_bins = signal_bin.get_rd_bins();
|
|
54186
|
+
let snp_bins = signal_bin.get_snp_bins();
|
|
54187
|
+
this.available_bins = [...new Set(rd_bins, snp_bins)];
|
|
54155
54188
|
|
|
54156
54189
|
// let bin_size = this.bin_size
|
|
54157
|
-
if(! this.
|
|
54158
|
-
bin_size = this.
|
|
54190
|
+
if(! this.available_bins.includes(bin_size)){
|
|
54191
|
+
bin_size = this.available_bins.at(-1);
|
|
54159
54192
|
}
|
|
54160
54193
|
|
|
54161
54194
|
const chr_ds = await h5_obj.get("rd_chromosomes");
|
|
@@ -54199,6 +54232,9 @@
|
|
|
54199
54232
|
let signal_baf_1 = `snp_likelihood_${chrom}_${bin_size}_mask`;
|
|
54200
54233
|
let chr_wig_bafs = await this.get_baf_signals(h5_obj, h5_obj_keys, chrom, bin_size, signal_baf_1);
|
|
54201
54234
|
|
|
54235
|
+
// let signal_baf_1 = `snp_i1_${chrom}_${bin_size}_mask`
|
|
54236
|
+
// let chr_wig_bafs = await this.get_baf_signals_v2(h5_obj, h5_obj_keys, chrom, bin_size, signal_baf_1)
|
|
54237
|
+
|
|
54202
54238
|
wigFeatures_baf1 = wigFeatures_baf1.concat(chr_wig_bafs[0]);
|
|
54203
54239
|
wigFeatures_baf2 = wigFeatures_baf2.concat(chr_wig_bafs[1]);
|
|
54204
54240
|
// this.rd_call_combined(h5_obj, h5_obj_keys, chrom, bin_size, rd_stat)
|
|
@@ -54323,6 +54359,28 @@
|
|
|
54323
54359
|
}
|
|
54324
54360
|
return [chr_wig_1, chr_wig_2]
|
|
54325
54361
|
}
|
|
54362
|
+
|
|
54363
|
+
async get_baf_signals_v2(h5_obj, h5_obj_keys, chrom, bin_size, signal_name){
|
|
54364
|
+
|
|
54365
|
+
/* return two list of dictionary*/
|
|
54366
|
+
let chr_wig_1 = [];
|
|
54367
|
+
let chr_wig_2 = [];
|
|
54368
|
+
if (h5_obj_keys.includes(signal_name)){
|
|
54369
|
+
let chrom_dataset = await h5_obj.get(signal_name);
|
|
54370
|
+
let chrom_data = await chrom_dataset.to_array(); //create_nested_array(value, shape)
|
|
54371
|
+
chrom_data.forEach((lh, bin_idx) => {
|
|
54372
|
+
if (!isNaN(lh)){
|
|
54373
|
+
chr_wig_1.push({chr:chrom, start: bin_idx*bin_size, end: (bin_idx+1) * bin_size, value: -2 * ( 0.5 - lh )});
|
|
54374
|
+
if(lh != 0.5){
|
|
54375
|
+
chr_wig_2.push({chr:chrom, start: bin_idx*bin_size, end: (bin_idx+1) * bin_size, value: -2 * ( 0.5 + lh )});
|
|
54376
|
+
}
|
|
54377
|
+
}
|
|
54378
|
+
});
|
|
54379
|
+
}
|
|
54380
|
+
console.log(chrom, chr_wig_1, chr_wig_2);
|
|
54381
|
+
return [chr_wig_1, chr_wig_2]
|
|
54382
|
+
|
|
54383
|
+
}
|
|
54326
54384
|
}
|
|
54327
54385
|
|
|
54328
54386
|
class ParseSignals{
|
|
@@ -54363,6 +54421,53 @@
|
|
|
54363
54421
|
}
|
|
54364
54422
|
}
|
|
54365
54423
|
|
|
54424
|
+
class GetFit {
|
|
54425
|
+
constructor(allBins) {
|
|
54426
|
+
this.allBins = allBins;
|
|
54427
|
+
}
|
|
54428
|
+
getValues() {
|
|
54429
|
+
const bins = Object.values(this.allBins).reduce(
|
|
54430
|
+
(binResult, bin) => { return binResult.concat(bin.filter(a => a.binScore > 0).map(a => a.binScore)) }, []);
|
|
54431
|
+
return bins
|
|
54432
|
+
}
|
|
54433
|
+
getMean(data) {
|
|
54434
|
+
return (data.reduce(function (a, b) { return a + b; }) / data.length);
|
|
54435
|
+
}
|
|
54436
|
+
fit_data() {
|
|
54437
|
+
let rd_list = this.getValues();
|
|
54438
|
+
let distParmas = getDistParams(rd_list);
|
|
54439
|
+
return distParmas
|
|
54440
|
+
}
|
|
54441
|
+
|
|
54442
|
+
histogram(data, bins) {
|
|
54443
|
+
const step = bins[1] - bins[0];
|
|
54444
|
+
const hist_bins = [];
|
|
54445
|
+
|
|
54446
|
+
data.forEach((value, index) => {
|
|
54447
|
+
bins.forEach((bin_value, bin_index) => {
|
|
54448
|
+
if (!hist_bins[bin_value]) {
|
|
54449
|
+
hist_bins[bin_value] = { count: 0 };
|
|
54450
|
+
}
|
|
54451
|
+
if (bin_value <= value && value < bin_value + step) {
|
|
54452
|
+
hist_bins[bin_value].count++;
|
|
54453
|
+
return false;
|
|
54454
|
+
}
|
|
54455
|
+
});
|
|
54456
|
+
});
|
|
54457
|
+
const dist_p = [];
|
|
54458
|
+
hist_bins.forEach((bin, index) => { dist_p.push(bin.count); });
|
|
54459
|
+
return dist_p
|
|
54460
|
+
}
|
|
54461
|
+
|
|
54462
|
+
}
|
|
54463
|
+
|
|
54464
|
+
function range_function(start, stop, step) {
|
|
54465
|
+
const data_array = Array(Math.ceil((stop - start) / step))
|
|
54466
|
+
.fill(start)
|
|
54467
|
+
.map((x, y) => x + y * step);
|
|
54468
|
+
return data_array;
|
|
54469
|
+
}
|
|
54470
|
+
|
|
54366
54471
|
function filterOutliers(someArray) {
|
|
54367
54472
|
|
|
54368
54473
|
if (someArray.length < 4)
|
|
@@ -54395,6 +54500,21 @@
|
|
|
54395
54500
|
return [mean, std]
|
|
54396
54501
|
}
|
|
54397
54502
|
|
|
54503
|
+
function linspace(a, b, n) {
|
|
54504
|
+
if (typeof n === "undefined") n = Math.max(Math.round(b - a) + 1, 1);
|
|
54505
|
+
if (n < 2) {
|
|
54506
|
+
return n === 1 ? [a] : [];
|
|
54507
|
+
}
|
|
54508
|
+
var ret = Array(n);
|
|
54509
|
+
n--;
|
|
54510
|
+
for (let i = n; i >= 0; i--) {
|
|
54511
|
+
ret[i] = (i * b + (n - i) * a) / n;
|
|
54512
|
+
}
|
|
54513
|
+
return ret;
|
|
54514
|
+
}
|
|
54515
|
+
|
|
54516
|
+
var g_utils = { range_function, getDistParams, linspace, GetFit};
|
|
54517
|
+
|
|
54398
54518
|
/**
|
|
54399
54519
|
* Evaluates the cumulative distribution function (CDF) for a Student's t distribution with degrees of freedom `v` at a value `t`.
|
|
54400
54520
|
*
|
|
@@ -54539,48 +54659,507 @@
|
|
|
54539
54659
|
return Math.log(gamma(xg))
|
|
54540
54660
|
}
|
|
54541
54661
|
|
|
54542
|
-
|
|
54662
|
+
function t_test_1_sample$1(mean, m, s, n) {
|
|
54663
|
+
if (s == 0) s = 1;
|
|
54664
|
+
var t = ((mean - m) / s) * Math.sqrt(n);
|
|
54665
|
+
var p = 1.0 - TdistributionCDF(Math.abs(t), (n - 1));
|
|
54666
|
+
return p
|
|
54667
|
+
}
|
|
54543
54668
|
|
|
54544
|
-
|
|
54545
|
-
|
|
54546
|
-
|
|
54547
|
-
|
|
54548
|
-
|
|
54549
|
-
|
|
54550
|
-
|
|
54551
|
-
|
|
54669
|
+
function t_test_2_samples$1(m1, s1, n1, m2, s2, n2) {
|
|
54670
|
+
if (s1 == 0) s1 = 1;
|
|
54671
|
+
if (s2 == 0) s2 = 1;
|
|
54672
|
+
var t = (m1 - m2) / Math.sqrt(s1 ** 2 / n1 + s2 ** 2 / n2);
|
|
54673
|
+
var df = ((s1 ** 2 / n1 + s2 ** 2 / n2) ** 2 * (n1 - 1) * (n2 - 1)) /
|
|
54674
|
+
((s1 ** 4 * (n2 - 1)) / n1 ** 2 + (s2 ** 4 * (n1 - 1)) / n2 ** 2);
|
|
54675
|
+
|
|
54676
|
+
var p = 1.0 - TdistributionCDF(Math.abs(t), parseInt(df + 0.5));
|
|
54677
|
+
|
|
54678
|
+
return p
|
|
54679
|
+
}
|
|
54680
|
+
|
|
54681
|
+
var t_dist = {TdistributionCDF, gamma, t_test_1_sample: t_test_1_sample$1, t_test_2_samples: t_test_2_samples$1};
|
|
54682
|
+
|
|
54683
|
+
class CombinedCaller{
|
|
54684
|
+
constructor(wigFeatures, binSize) {
|
|
54685
|
+
this.wigFeatures = wigFeatures;
|
|
54686
|
+
this.binSize = binSize;
|
|
54687
|
+
// let fit_obj = this.get_fit()
|
|
54688
|
+
// this.globalMean = fit_obj.globalMean
|
|
54689
|
+
// this.globalStd = fit_obj.globalStd
|
|
54552
54690
|
}
|
|
54553
|
-
|
|
54554
|
-
|
|
54691
|
+
get_fit(){
|
|
54692
|
+
var fit_info = new g_utils.GetFit(this.wigFeatures);
|
|
54693
|
+
var [globalMean, globalStd] = fit_info.fit_data();
|
|
54694
|
+
|
|
54695
|
+
return {globalMean:globalMean, globalStd:globalStd}
|
|
54696
|
+
|
|
54555
54697
|
}
|
|
54556
|
-
|
|
54557
|
-
|
|
54558
|
-
let
|
|
54559
|
-
|
|
54698
|
+
async call_2d(omin=null, mcount=null, event_type="both", max_distance=0.1, baf_threshold=0, max_copy_number=10, min_cell_fraction=0.0){
|
|
54699
|
+
|
|
54700
|
+
let fit_obj = this.get_fit();
|
|
54701
|
+
this.globalMean = fit_obj.globalMean;
|
|
54702
|
+
this.globalStd = fit_obj.globalStd;
|
|
54703
|
+
|
|
54704
|
+
let overlap_min = omin==null ? 0.05 * this.binSize / 3e9: omin ;
|
|
54705
|
+
let min_count = mcount == null ? parseInt(this.binSize / 10000) : mcount ;
|
|
54706
|
+
|
|
54707
|
+
let gstat_rd0 = [];
|
|
54708
|
+
let gstat_rd_all = [];
|
|
54709
|
+
let gstat_rd = [];
|
|
54710
|
+
let gstat_error = [];
|
|
54711
|
+
let gstat_lh = [];
|
|
54712
|
+
let gstat_n = [];
|
|
54713
|
+
|
|
54714
|
+
for (const [chr, wig] of Object.entries(this.wigFeatures)) {
|
|
54715
|
+
let segments = [];
|
|
54716
|
+
let levels = [];
|
|
54717
|
+
let likelihoods = [];
|
|
54718
|
+
|
|
54719
|
+
wig.forEach((bin, bin_idx) => {
|
|
54720
|
+
if (bin.hets_count > 4 ){
|
|
54721
|
+
|
|
54722
|
+
if( bin.dp_count > min_count ){
|
|
54723
|
+
segments.push([bin_idx]);
|
|
54724
|
+
levels.push(bin.binScore);
|
|
54725
|
+
likelihoods.push(bin.likelihood_score);
|
|
54726
|
+
delete bin.likelihood_score;
|
|
54727
|
+
|
|
54728
|
+
}
|
|
54729
|
+
}
|
|
54730
|
+
});
|
|
54731
|
+
|
|
54732
|
+
let diff_level = [];
|
|
54733
|
+
for(let i=1; i<levels.length; i++){
|
|
54734
|
+
diff_level.push(Math.abs(levels[i] - levels[i-1]));
|
|
54735
|
+
}
|
|
54736
|
+
let min_flank = [0];
|
|
54737
|
+
for(let i=1; i<diff_level.length; i++){
|
|
54738
|
+
min_flank.push(Math.min(diff_level[i-1], diff_level[i]));
|
|
54739
|
+
}
|
|
54740
|
+
min_flank.push(0);
|
|
54741
|
+
|
|
54742
|
+
let error = levels.map((x, x_idx) => {return Math.sqrt(Math.sqrt(x) ** 2 + this.globalStd ** 2 + Math.pow(min_flank[x_idx]/2, 2));});
|
|
54743
|
+
|
|
54744
|
+
let overlaps = [];
|
|
54745
|
+
|
|
54746
|
+
for(let i=0; i< segments.length-1; i++){
|
|
54747
|
+
|
|
54748
|
+
let lh_overlap = 0;
|
|
54749
|
+
try{
|
|
54750
|
+
lh_overlap = likelihood_overlap(likelihoods[i], likelihoods[i+1]);
|
|
54751
|
+
}catch{
|
|
54752
|
+
console.log("Overlap failed: ", i, likelihoods[i], segments[i+1], likelihoods[i+1]);
|
|
54753
|
+
}
|
|
54754
|
+
|
|
54755
|
+
let rd_overlap = normal_overlap_approx(levels[i], error[i], levels[i+1], error[i+1]);
|
|
54756
|
+
overlaps.push(rd_overlap * lh_overlap);
|
|
54757
|
+
|
|
54758
|
+
}
|
|
54759
|
+
|
|
54760
|
+
while(overlaps.length >0) {
|
|
54761
|
+
overlaps = overlaps.filter(num => typeof num === "number");
|
|
54762
|
+
|
|
54763
|
+
let max_overlap = arrayMax(overlaps);
|
|
54764
|
+
if(isNaN(max_overlap)){
|
|
54765
|
+
console.log('NaN value', overlaps);
|
|
54766
|
+
}
|
|
54767
|
+
if(max_overlap < overlap_min){
|
|
54768
|
+
// console.log("maxoverlap ",max_overlap, "is smaller than overlap min")
|
|
54769
|
+
break
|
|
54770
|
+
}
|
|
54771
|
+
let i = overlaps.indexOf(max_overlap);
|
|
54772
|
+
|
|
54773
|
+
let merge_level = normal_merge(levels[i], error[i], levels[i + 1], error[i + 1]);
|
|
54774
|
+
|
|
54775
|
+
let nlh;
|
|
54776
|
+
let nlh_sum;
|
|
54777
|
+
try{
|
|
54778
|
+
nlh = likelihoods[i].map((l_value, l_idx) => { return l_value * likelihoods[i+1][l_idx]});
|
|
54779
|
+
|
|
54780
|
+
nlh_sum = nlh.reduce((a, c_value) => {return a + c_value});
|
|
54781
|
+
|
|
54782
|
+
}catch{
|
|
54783
|
+
console.log(likelihoods);
|
|
54784
|
+
console.log('max_overlap:', max_overlap, i, overlaps.length);
|
|
54785
|
+
console.log('likelihood: ', i ,likelihoods[i], likelihoods[i+1]);
|
|
54786
|
+
console.log('nlh: ', nlh_sum);
|
|
54787
|
+
}
|
|
54788
|
+
// nlh_sum = nlh.reduce((a, c_value) => {return a + c_value});
|
|
54789
|
+
|
|
54790
|
+
levels[i] = merge_level.nl;
|
|
54791
|
+
error[i] = merge_level.ne;
|
|
54792
|
+
|
|
54793
|
+
likelihoods[i] = nlh.map(function(item) { return item/nlh_sum } );
|
|
54794
|
+
|
|
54795
|
+
segments[i].push(...segments[i+1]);
|
|
54796
|
+
|
|
54797
|
+
levels.splice(i + 1, 1);
|
|
54798
|
+
error.splice(i + 1, 1);
|
|
54799
|
+
segments.splice(i + 1, 1);
|
|
54800
|
+
likelihoods.splice(i + 1, 1);
|
|
54801
|
+
overlaps.splice(i, 1);
|
|
54802
|
+
|
|
54803
|
+
if(i < overlaps.length){
|
|
54804
|
+
|
|
54805
|
+
let rd_overlap = normal_overlap_approx(levels[i], error[i], levels[i+1], error[i+1]);
|
|
54806
|
+
let new_overlap = rd_overlap * likelihood_overlap(likelihoods[i], likelihoods[i + 1]);
|
|
54807
|
+
|
|
54808
|
+
overlaps[i] = new_overlap;
|
|
54809
|
+
}
|
|
54810
|
+
if(i > 0){
|
|
54811
|
+
let new_overlap = normal_overlap_approx(levels[i - 1], error[i - 1], levels[i], error[i])
|
|
54812
|
+
* likelihood_overlap(likelihoods[i - 1], likelihoods[i]);
|
|
54813
|
+
overlaps[i - 1] = new_overlap;
|
|
54814
|
+
}
|
|
54815
|
+
|
|
54816
|
+
}
|
|
54817
|
+
let ons = -1;
|
|
54818
|
+
while(true){
|
|
54819
|
+
overlaps = [];
|
|
54820
|
+
for(let i=0; i< levels.length; i++){
|
|
54821
|
+
for(let j=i; j<levels.length; j++){
|
|
54822
|
+
if(segments[j][0] - segments[i].at(-1) < max_distance * (segments[i].length + segments[j].length)){
|
|
54823
|
+
overlaps.push(normal_overlap_approx(levels[i], error[i], levels[j], error[j]) * likelihood_overlap(likelihoods[i], likelihoods[j]));
|
|
54824
|
+
}
|
|
54825
|
+
}
|
|
54826
|
+
}
|
|
54827
|
+
|
|
54828
|
+
if(overlaps.length == 0){
|
|
54829
|
+
break
|
|
54830
|
+
}
|
|
54831
|
+
let max_overlap = arrayMax(overlaps);
|
|
54832
|
+
if(max_overlap < overlap_min){
|
|
54833
|
+
break
|
|
54834
|
+
}
|
|
54835
|
+
let i = 0;
|
|
54836
|
+
let j = 1;
|
|
54837
|
+
while (i < segments.length - 1){
|
|
54838
|
+
let overlap_value = normal_overlap_approx(levels[i], error[i], levels[j], error[j]) * likelihood_overlap(likelihoods[i], likelihoods[j]);
|
|
54839
|
+
|
|
54840
|
+
if((segments[j][0] - segments[i].at(-1)) < max_distance * (segments[i].length + segments[j].length) && overlap_value == max_overlap){
|
|
54841
|
+
let merge_level = normal_merge(levels[i], error[i], levels[i + 1], error[i + 1]);
|
|
54842
|
+
|
|
54843
|
+
levels[i] = merge_level.nl;
|
|
54844
|
+
error[i] = merge_level.ne;
|
|
54845
|
+
let nlh = likelihoods[i].map((l_value, l_idx) => { return l_value * likelihoods[i+1][l_idx]});
|
|
54846
|
+
let nlh_sum = nlh.reduce((a, c_value) => {return a + c_value});
|
|
54847
|
+
likelihoods[i] = nlh.map(function(item) { return item/nlh_sum } );
|
|
54848
|
+
|
|
54849
|
+
|
|
54850
|
+
segments[i].push(...segments[i+1]);
|
|
54851
|
+
segments[i] = segments[i].sort((a,b) => a-b);
|
|
54852
|
+
|
|
54853
|
+
levels.splice(j, 1);
|
|
54854
|
+
error.splice(j, 1);
|
|
54855
|
+
segments.splice(j, 1);
|
|
54856
|
+
likelihoods.splice(j, 1);
|
|
54857
|
+
|
|
54858
|
+
if(j >= segments.length){
|
|
54859
|
+
i += 1;
|
|
54860
|
+
j = i + 1;
|
|
54861
|
+
}
|
|
54862
|
+
|
|
54863
|
+
}else {
|
|
54864
|
+
j += 1;
|
|
54865
|
+
if(j >= segments.length){
|
|
54866
|
+
i += 1;
|
|
54867
|
+
j = i + 1;
|
|
54868
|
+
}
|
|
54869
|
+
}
|
|
54870
|
+
}
|
|
54871
|
+
if(ons == segments.length){
|
|
54872
|
+
break
|
|
54873
|
+
}
|
|
54874
|
+
ons = segments.length;
|
|
54875
|
+
}
|
|
54876
|
+
// console.log('final segments', segments)
|
|
54877
|
+
|
|
54878
|
+
segments.forEach((seg_value, seg_idx) => {
|
|
54879
|
+
let baf_info = likelihood_baf_pval(likelihoods[seg_idx]);
|
|
54880
|
+
if(seg_value.length > 1){
|
|
54881
|
+
|
|
54882
|
+
seg_value.forEach((bin, bin_idx) =>{
|
|
54883
|
+
gstat_rd_all.push(wig[bin]);
|
|
54884
|
+
if(baf_info.mean <= baf_threshold){
|
|
54885
|
+
gstat_rd0.push(wig[bin]);
|
|
54886
|
+
}
|
|
54887
|
+
wig[bin].segment_score = levels[seg_idx];
|
|
54888
|
+
});
|
|
54889
|
+
gstat_rd.push(levels[seg_idx]);
|
|
54890
|
+
gstat_error.push(error[seg_idx]);
|
|
54891
|
+
gstat_lh.push(likelihoods[seg_idx]);
|
|
54892
|
+
|
|
54893
|
+
}
|
|
54894
|
+
|
|
54895
|
+
});
|
|
54896
|
+
|
|
54897
|
+
continue
|
|
54898
|
+
}
|
|
54899
|
+
|
|
54900
|
+
// Third stage for call
|
|
54901
|
+
|
|
54902
|
+
// let data = gstat_rd0.lengthn == 0 ? gstat_rd_all: gstat_rd0 ;
|
|
54903
|
+
|
|
54904
|
+
let points = parseInt(1000 * (1 - min_cell_fraction));
|
|
54905
|
+
if(points == 0){
|
|
54906
|
+
points = 1;
|
|
54907
|
+
}
|
|
54908
|
+
let x = g_utils.linspace(min_cell_fraction, 1, points);
|
|
54909
|
+
let master_lh = {};
|
|
54910
|
+
let germline_lh = {};
|
|
54911
|
+
for(let cn=10; cn > -1; cn--){
|
|
54912
|
+
for(let h1=0; h1 < (cn/2+1); h1++){
|
|
54913
|
+
let h2 = cn - h1;
|
|
54914
|
+
let mrd = x.map((v, idx) => {return 1-v +v*cn/2});
|
|
54915
|
+
let g_mrd = cn / 2;
|
|
54916
|
+
let g_mbaf;
|
|
54917
|
+
let mbaf;
|
|
54918
|
+
if(cn > 0){
|
|
54919
|
+
g_mbaf = 0.5 - (h1 / (h1 + h2));
|
|
54920
|
+
mbaf = x.map((v, idx) => {return 0.5 - (1 - v + v * h1) / (2 - 2 * v + (h1 + h2) * v)});
|
|
54921
|
+
|
|
54922
|
+
}else {
|
|
54923
|
+
g_mbaf = 0;
|
|
54924
|
+
mbaf = x.map((v, idx) => {return 0*v});
|
|
54925
|
+
}
|
|
54926
|
+
|
|
54927
|
+
for( let ei=0; ei < gstat_rd.length; ei++){
|
|
54928
|
+
|
|
54929
|
+
let g_lh = normal(g_mrd * this.globalMean, 1, gstat_rd[ei], gstat_error[ei]) * likelihood_of_baf(gstat_lh[ei], 0.5 + g_mbaf);
|
|
54930
|
+
if(ei in germline_lh){
|
|
54931
|
+
germline_lh[ei].push([cn, h1, h2, g_lh, 1.0]);
|
|
54932
|
+
}else {
|
|
54933
|
+
germline_lh[ei] = [cn, h1, h2, g_lh, 1.0];
|
|
54934
|
+
}
|
|
54935
|
+
let slh = 0;
|
|
54936
|
+
let max_lh = 0;
|
|
54937
|
+
let max_x = 0;
|
|
54938
|
+
mrd.forEach((mi, idx) => {
|
|
54939
|
+
if(!isNaN(mbaf[idx])){
|
|
54940
|
+
let tmpl = normal(mi * this.globalMean, 1, gstat_rd[ei], gstat_error[ei]) * likelihood_of_baf(gstat_lh[ei], 0.5 + mbaf[idx]);
|
|
54941
|
+
slh += tmpl;
|
|
54942
|
+
if(tmpl > max_lh){
|
|
54943
|
+
max_lh = tmpl;
|
|
54944
|
+
max_x = x[idx];
|
|
54945
|
+
}
|
|
54946
|
+
}
|
|
54947
|
+
});
|
|
54948
|
+
if(ei in master_lh){
|
|
54949
|
+
master_lh[ei].push([cn, h1, h2, slh / x.length, max_x]);
|
|
54950
|
+
}else {
|
|
54951
|
+
master_lh[ei] = [cn, h1, h2, slh / x.length, max_x];
|
|
54952
|
+
}
|
|
54953
|
+
}
|
|
54954
|
+
|
|
54955
|
+
for( let ei=0; ei < gstat_rd.length; ei++){
|
|
54956
|
+
if(event_type == "germline"){
|
|
54957
|
+
master_lh[ei].sort((a, b) => a[3] - b[3]);
|
|
54958
|
+
}
|
|
54959
|
+
else {
|
|
54960
|
+
master_lh[ei].sort((a, b) => a[3] - b[3]);
|
|
54961
|
+
if(event_type == "both"){
|
|
54962
|
+
|
|
54963
|
+
germline_lh[ei].sort((a, b) => a[3] - b[3]);
|
|
54964
|
+
if(germline_lh[ei][0][3] > master_lh[ei][0][3]){
|
|
54965
|
+
//let tmp_list = list(filter( lambda x: x[0] != germline_lh[ei][0][0] and x[1] != germline_lh[ei][0][1], master_lh[ei]))
|
|
54966
|
+
let tmp_list = master_lh[ei].filter((x) => (x[0] != germline_lh[ei][0][0]) && (x[1] <= germline_lh[ei][0][1]));
|
|
54967
|
+
// console.log('tmp_list', tmp_list)
|
|
54968
|
+
// master_lh[ei] = [germline_lh[ei][0]] + tmp_list
|
|
54969
|
+
master_lh[ei] = [germline_lh[ei][0]].push(...tmp_list);
|
|
54970
|
+
}
|
|
54971
|
+
}
|
|
54972
|
+
}
|
|
54973
|
+
}
|
|
54974
|
+
for( let ei=0; ei < gstat_rd.length; ei++){
|
|
54975
|
+
if(master_lh[ei][0][0] > 2);
|
|
54976
|
+
if(master_lh[ei][0][0] < 2);
|
|
54977
|
+
gstat_rd[ei] / this.globalMean;
|
|
54978
|
+
t_dist.t_test_1_sample(this.globalMean, gstat_rd[ei], gstat_error[ei], gstat_n[ei]);
|
|
54979
|
+
// console.log(etype)
|
|
54980
|
+
|
|
54981
|
+
}
|
|
54982
|
+
|
|
54983
|
+
|
|
54984
|
+
// break
|
|
54985
|
+
}
|
|
54986
|
+
|
|
54987
|
+
}
|
|
54988
|
+
|
|
54989
|
+
var rawbinScore = this.formatDataStructure(this.wigFeatures, 'binScore', this.globalMean);
|
|
54990
|
+
var callScore = this.formatDataStructure(this.wigFeatures, 'segment_score', this.globalMean);
|
|
54991
|
+
|
|
54992
|
+
return {binScore: rawbinScore, segment_score: callScore}
|
|
54993
|
+
|
|
54560
54994
|
}
|
|
54561
54995
|
|
|
54562
|
-
|
|
54563
|
-
const
|
|
54564
|
-
const
|
|
54996
|
+
formatDataStructure(wigFeatures, feature_column, scaling_factor = 1) {
|
|
54997
|
+
const results = [];
|
|
54998
|
+
for (const [chr, wig] of Object.entries(wigFeatures)) {
|
|
54565
54999
|
|
|
54566
|
-
|
|
54567
|
-
|
|
54568
|
-
if (
|
|
54569
|
-
|
|
55000
|
+
wig.forEach(sample => {
|
|
55001
|
+
var new_sample = { ...sample };
|
|
55002
|
+
if (scaling_factor != 1) {
|
|
55003
|
+
new_sample.value = sample[feature_column] / scaling_factor * 2;
|
|
54570
55004
|
}
|
|
54571
|
-
|
|
54572
|
-
|
|
54573
|
-
|
|
55005
|
+
results.push(new_sample);
|
|
55006
|
+
});
|
|
55007
|
+
}
|
|
55008
|
+
|
|
55009
|
+
return results
|
|
55010
|
+
}
|
|
55011
|
+
|
|
55012
|
+
formatDataStructure_BAF(feature_column, scaling_factor = 2) {
|
|
55013
|
+
const baf1 = [];
|
|
55014
|
+
const baf2 = [];
|
|
55015
|
+
for (const [chr, wig] of Object.entries(this.wigFeatures)) {
|
|
55016
|
+
|
|
55017
|
+
wig.forEach(sample => {
|
|
55018
|
+
|
|
55019
|
+
var baf1_value = { ...sample };
|
|
55020
|
+
var baf2_value = { ...sample };
|
|
55021
|
+
|
|
55022
|
+
let value = sample[feature_column];
|
|
55023
|
+
if (value != 0.5){
|
|
55024
|
+
baf2_value.value = -2 * (1 - value);
|
|
55025
|
+
baf2.push(baf2_value);
|
|
54574
55026
|
}
|
|
55027
|
+
baf1_value.value = -2 * value;
|
|
55028
|
+
baf1.push(baf1_value);
|
|
55029
|
+
|
|
54575
55030
|
});
|
|
54576
|
-
}
|
|
54577
|
-
|
|
54578
|
-
|
|
54579
|
-
return
|
|
55031
|
+
}
|
|
55032
|
+
|
|
55033
|
+
|
|
55034
|
+
return [baf1, baf2]
|
|
54580
55035
|
}
|
|
55036
|
+
}
|
|
54581
55037
|
|
|
55038
|
+
function arrayMax(arr) {
|
|
55039
|
+
return arr.reduce(function (p, v) {
|
|
55040
|
+
return ( p > v ? p : v );
|
|
55041
|
+
});
|
|
55042
|
+
}
|
|
55043
|
+
|
|
55044
|
+
/**
|
|
55045
|
+
* Normal distribution.
|
|
55046
|
+
*
|
|
55047
|
+
* @param {float} x - Variable.
|
|
55048
|
+
* @param {float} a - area
|
|
55049
|
+
* @param {float} x0 - Mean value
|
|
55050
|
+
* @param {float} sigma - Sigma
|
|
55051
|
+
* @returns {float} - Value of distribution in x.
|
|
55052
|
+
*/
|
|
55053
|
+
function normal(x, a, x0, sigma){
|
|
55054
|
+
|
|
55055
|
+
return a * Math.exp(-1* (x - x0) ** 2 / (2 * sigma ** 2)) / Math.sqrt(2 * Math.PI) / sigma
|
|
55056
|
+
|
|
55057
|
+
}
|
|
55058
|
+
|
|
55059
|
+
/**
|
|
55060
|
+
* Calculates two normal distributions overlap area.
|
|
55061
|
+
*
|
|
55062
|
+
* @param {float} m1 - Mean value of the first distribution
|
|
55063
|
+
* @param {float} s1 - Sigma of the first distribution
|
|
55064
|
+
* @param {float} m2 - Mean value for second distribution
|
|
55065
|
+
* @param {float} s2 - Sigma of the second distribution
|
|
55066
|
+
*
|
|
55067
|
+
* @returns {float} area - Area of overlap
|
|
55068
|
+
*/
|
|
55069
|
+
function normal_overlap_approx(m1, s1, m2, s2){
|
|
55070
|
+
|
|
55071
|
+
return Math.exp(-1* (m1-m2)**2/ (s1**2+s2**2))
|
|
55072
|
+
}
|
|
55073
|
+
|
|
55074
|
+
|
|
55075
|
+
/**
|
|
55076
|
+
* Returns overlap area of two likelihood functions.
|
|
55077
|
+
*
|
|
55078
|
+
* @param {*} lk1 - First likelihood function.
|
|
55079
|
+
* @param {*} lk2 - Second likelihood function.
|
|
55080
|
+
*
|
|
55081
|
+
* @returns {float} - Overlap area.
|
|
55082
|
+
*/
|
|
55083
|
+
function likelihood_overlap(likelihood_1, likelihood_2){
|
|
55084
|
+
let sum;
|
|
55085
|
+
try{
|
|
55086
|
+
sum = likelihood_1.reduce((accumulator, currentValue, currentIndex) => {return accumulator + Math.min(currentValue, likelihood_2[currentIndex])});
|
|
55087
|
+
}catch{
|
|
55088
|
+
console.log("Failed to find likelihood overlap: ", likelihood_1, likelihood_2);
|
|
55089
|
+
return 0
|
|
55090
|
+
}
|
|
55091
|
+
|
|
55092
|
+
return sum
|
|
54582
55093
|
}
|
|
54583
55094
|
|
|
55095
|
+
/**
|
|
55096
|
+
* Calculates normal distribution that is product of two given normal distributions.
|
|
55097
|
+
*
|
|
55098
|
+
* @param {float} m1 - Mean value of the first distribution
|
|
55099
|
+
* @param {float} s1 - Sigma of the first distribution
|
|
55100
|
+
* @param {float} m2 - Mean value for second distribution
|
|
55101
|
+
* @param {float} s2 - Sigma of the second distribution
|
|
55102
|
+
* @returns {Object} An object representing the first distribution
|
|
55103
|
+
* @property {float} nl - Mean value of the first distribution
|
|
55104
|
+
* @property {float} ne - Sigma of the first distribution
|
|
55105
|
+
*/
|
|
55106
|
+
function normal_merge(m1, s1, m2, s2){
|
|
55107
|
+
|
|
55108
|
+
if((s1 == 0) && (s2 == 0)){
|
|
55109
|
+
return {nl: 0.5 * (m1 + m2), ne: 0}
|
|
55110
|
+
}
|
|
55111
|
+
else {
|
|
55112
|
+
return {nl: (m1 * s2 * s2 + m2 * s1 * s1) / (s1 * s1 + s2 * s2), ne: Math.sqrt(s1 * s1 * s2 * s2 / (s1 * s1 + s2 * s2))}
|
|
55113
|
+
}
|
|
55114
|
+
}
|
|
55115
|
+
|
|
55116
|
+
/**
|
|
55117
|
+
* Calculates likelihood for given baf
|
|
55118
|
+
* @param {*} likelihood
|
|
55119
|
+
* @param {*} baf
|
|
55120
|
+
* @returns {float} likelihood value
|
|
55121
|
+
*/
|
|
55122
|
+
function likelihood_of_baf(likelihood, baf){
|
|
55123
|
+
|
|
55124
|
+
let bin = parseInt(baf * (likelihood.length - 1));
|
|
55125
|
+
let fr = baf * (likelihood.length - 1) - bin;
|
|
55126
|
+
if(bin < likelihood.length - 1){
|
|
55127
|
+
return likelihood[bin] * (1 - fr) + likelihood[bin + 1] * fr
|
|
55128
|
+
}
|
|
55129
|
+
else {
|
|
55130
|
+
return likelihood[bin]
|
|
55131
|
+
}
|
|
55132
|
+
}
|
|
55133
|
+
|
|
55134
|
+
/**
|
|
55135
|
+
*
|
|
55136
|
+
* Calculates baf level and p-value for given likelihood function.
|
|
55137
|
+
*
|
|
55138
|
+
* @param {*} likelihood
|
|
55139
|
+
* @returns {Object} An object representing BAF
|
|
55140
|
+
* @property {float} mean BAF level (difference from 1/2)
|
|
55141
|
+
* @property {float} p p-value for event different than 1/2
|
|
55142
|
+
*/
|
|
55143
|
+
function likelihood_baf_pval(likelihood) {
|
|
55144
|
+
const res = likelihood.length;
|
|
55145
|
+
const max_lh = Math.max(...likelihood);
|
|
55146
|
+
let ix = likelihood.indexOf(max_lh);
|
|
55147
|
+
if (ix > Math.floor(res / 2)) {
|
|
55148
|
+
ix = res - 1 - ix;
|
|
55149
|
+
}
|
|
55150
|
+
const b = (res / 2 - ix) / (res + 1);
|
|
55151
|
+
|
|
55152
|
+
const ix1 = Math.floor((res / 2 + ix) / 2);
|
|
55153
|
+
const ix2 = res - 1 - ix1;
|
|
55154
|
+
let p = likelihood.slice(ix1, ix2 + 1).reduce((acc, val) => acc + val, 0) / likelihood.reduce((acc, val) => acc + val, 0);
|
|
55155
|
+
if (ix === Math.floor(res / 2)) {
|
|
55156
|
+
p = 1.0;
|
|
55157
|
+
}
|
|
55158
|
+
return {mean:b, p:p};
|
|
55159
|
+
}
|
|
55160
|
+
|
|
55161
|
+
var combined_caller = {CombinedCaller};
|
|
55162
|
+
|
|
54584
55163
|
function erf(x) {
|
|
54585
55164
|
var m = 1.0, s = 1.0, sum = x * 1.0;
|
|
54586
55165
|
for (var i = 1; i < 50; i++) {
|
|
@@ -55228,6 +55807,10 @@
|
|
|
55228
55807
|
}
|
|
55229
55808
|
}
|
|
55230
55809
|
|
|
55810
|
+
|
|
55811
|
+
|
|
55812
|
+
var read_depth_caller = { Partition };
|
|
55813
|
+
|
|
55231
55814
|
class CNVpytorVCF {
|
|
55232
55815
|
constructor(allVariants, binSize) {
|
|
55233
55816
|
this.allVariants = allVariants;
|
|
@@ -55355,13 +55938,11 @@
|
|
|
55355
55938
|
readDepthMeanshift(wigFeatures) {
|
|
55356
55939
|
|
|
55357
55940
|
// Get global mean and standrad deviation
|
|
55358
|
-
var fit_info = new GetFit(wigFeatures);
|
|
55941
|
+
var fit_info = new g_utils.GetFit(wigFeatures);
|
|
55359
55942
|
var [globamMean, globalStd] = fit_info.fit_data();
|
|
55360
|
-
// console.log('Fitter', globamMean, globalStd)
|
|
55361
|
-
|
|
55362
55943
|
|
|
55363
55944
|
// Apply partition method
|
|
55364
|
-
var partition = new Partition(wigFeatures, globamMean, globalStd);
|
|
55945
|
+
var partition = new read_depth_caller.Partition(wigFeatures, globamMean, globalStd);
|
|
55365
55946
|
var partition_array = partition.meanShiftCaller();
|
|
55366
55947
|
var caller_array = partition.cnv_calling();
|
|
55367
55948
|
|
|
@@ -55392,86 +55973,10 @@
|
|
|
55392
55973
|
results.push(new_sample);
|
|
55393
55974
|
});
|
|
55394
55975
|
}
|
|
55395
|
-
// console.log(feature_column, results)
|
|
55396
55976
|
|
|
55397
55977
|
return results
|
|
55398
55978
|
}
|
|
55399
55979
|
|
|
55400
|
-
// function for baf likelihood calculations
|
|
55401
|
-
async computeBAF() {
|
|
55402
|
-
const chromosomes = Object.keys(this.allVariants);
|
|
55403
|
-
const wigFeatures = {};
|
|
55404
|
-
const results = [];
|
|
55405
|
-
|
|
55406
|
-
for (let chr of chromosomes) {
|
|
55407
|
-
const variants = this.allVariants[chr];
|
|
55408
|
-
if (variants.length === 0) continue
|
|
55409
|
-
var featureBin;
|
|
55410
|
-
for (let snp of variants) {
|
|
55411
|
-
featureBin = Math.max(Math.floor(snp.start / this.binSize), 0);
|
|
55412
|
-
|
|
55413
|
-
if (!wigFeatures[chr]) {
|
|
55414
|
-
wigFeatures[chr] = [];
|
|
55415
|
-
}
|
|
55416
|
-
if (!wigFeatures[chr][featureBin]) {
|
|
55417
|
-
if (featureBin > 0) {
|
|
55418
|
-
// calculating the BAF likelihood for previous bin
|
|
55419
|
-
let previous_featureBin = featureBin - 1;
|
|
55420
|
-
if (wigFeatures[chr][previous_featureBin]) {
|
|
55421
|
-
|
|
55422
|
-
const updated_bin = this.get_max_min_score(wigFeatures[chr][previous_featureBin]);
|
|
55423
|
-
wigFeatures[chr][previous_featureBin] = updated_bin;
|
|
55424
|
-
results.push(wigFeatures[chr][previous_featureBin]);
|
|
55425
|
-
}
|
|
55426
|
-
}
|
|
55427
|
-
wigFeatures[chr][featureBin] = {
|
|
55428
|
-
chr,
|
|
55429
|
-
start: featureBin * this.binSize,
|
|
55430
|
-
end: (featureBin + 1) * this.binSize,
|
|
55431
|
-
value: 0,
|
|
55432
|
-
count: 0,
|
|
55433
|
-
likelihood_score: [],
|
|
55434
|
-
min_score: 0,
|
|
55435
|
-
};
|
|
55436
|
-
}
|
|
55437
|
-
const calls = snp.calls[9];
|
|
55438
|
-
let genotype = calls.genotype;
|
|
55439
|
-
let ad_score = calls.info["AD"].split(',');
|
|
55440
|
-
let ad_a = ad_score[0], ad_b = ad_score[1];
|
|
55441
|
-
|
|
55442
|
-
if ((genotype[0] == 0 && genotype[1] == 1) || (genotype[0] == 1 && genotype[1] == 0)) {
|
|
55443
|
-
//apply the beta function
|
|
55444
|
-
if (wigFeatures[chr][featureBin].likelihood_score.length == 0) {
|
|
55445
|
-
wigFeatures[chr][featureBin].likelihood_score = linspace(0, 1, 200).map((value, index) => {
|
|
55446
|
-
return beta(ad_a, ad_b, value);
|
|
55447
|
-
});
|
|
55448
|
-
} else {
|
|
55449
|
-
var sum = 0;
|
|
55450
|
-
|
|
55451
|
-
wigFeatures[chr][featureBin].likelihood_score = linspace(0, 1, 200).map((value, index) => {
|
|
55452
|
-
var likelihood_value = wigFeatures[chr][featureBin].likelihood_score[index] * beta(ad_a, ad_b, value);
|
|
55453
|
-
sum = sum + likelihood_value;
|
|
55454
|
-
return likelihood_value;
|
|
55455
|
-
});
|
|
55456
|
-
|
|
55457
|
-
wigFeatures[chr][featureBin].likelihood_score = linspace(0, 1, 200).map((value, index) => {
|
|
55458
|
-
return wigFeatures[chr][featureBin].likelihood_score[index] / sum;
|
|
55459
|
-
});
|
|
55460
|
-
}
|
|
55461
|
-
wigFeatures[chr][featureBin].count++;
|
|
55462
|
-
}
|
|
55463
|
-
}
|
|
55464
|
-
|
|
55465
|
-
// last feature bin
|
|
55466
|
-
const updated_bin = this.get_max_min_score(wigFeatures[chr][featureBin]);
|
|
55467
|
-
wigFeatures[chr][featureBin] = updated_bin;
|
|
55468
|
-
results.push(wigFeatures[chr][featureBin]);
|
|
55469
|
-
}
|
|
55470
|
-
|
|
55471
|
-
const baf2_result = this.format_BAF_likelihood(wigFeatures);
|
|
55472
|
-
return [results, baf2_result]
|
|
55473
|
-
|
|
55474
|
-
}
|
|
55475
55980
|
async computeBAF_v2() {
|
|
55476
55981
|
|
|
55477
55982
|
const chromosomes = Object.keys(this.allVariants);
|
|
@@ -55526,19 +56031,19 @@
|
|
|
55526
56031
|
if ((genotype[0] == 0 && genotype[1] == 1) || (genotype[0] == 1 && genotype[1] == 0)) {
|
|
55527
56032
|
//apply the beta function
|
|
55528
56033
|
if (wigFeatures[chr][featureBin].likelihood_score.length == 0) {
|
|
55529
|
-
wigFeatures[chr][featureBin].likelihood_score = linspace(0, 1, 100).map((value, index) => {
|
|
56034
|
+
wigFeatures[chr][featureBin].likelihood_score = g_utils.linspace(0, 1, 100).map((value, index) => {
|
|
55530
56035
|
return beta(ad_a, ad_b, value);
|
|
55531
56036
|
});
|
|
55532
56037
|
} else {
|
|
55533
56038
|
var sum = 0;
|
|
55534
56039
|
|
|
55535
|
-
wigFeatures[chr][featureBin].likelihood_score = linspace(0, 1, 100).map((value, index) => {
|
|
56040
|
+
wigFeatures[chr][featureBin].likelihood_score = g_utils.linspace(0, 1, 100).map((value, index) => {
|
|
55536
56041
|
var likelihood_value = wigFeatures[chr][featureBin].likelihood_score[index] * beta(ad_a, ad_b, value);
|
|
55537
56042
|
sum = sum + likelihood_value;
|
|
55538
56043
|
return likelihood_value;
|
|
55539
56044
|
});
|
|
55540
56045
|
|
|
55541
|
-
wigFeatures[chr][featureBin].likelihood_score = linspace(0, 1, 100).map((value, index) => {
|
|
56046
|
+
wigFeatures[chr][featureBin].likelihood_score = g_utils.linspace(0, 1, 100).map((value, index) => {
|
|
55542
56047
|
return wigFeatures[chr][featureBin].likelihood_score[index] / sum;
|
|
55543
56048
|
});
|
|
55544
56049
|
}
|
|
@@ -55584,7 +56089,6 @@
|
|
|
55584
56089
|
if (sample.likelihood_score.length > 0) {
|
|
55585
56090
|
const max = Math.max(...sample.likelihood_score);
|
|
55586
56091
|
const res = sample.likelihood_score.indexOf(max);
|
|
55587
|
-
sample.likelihood_score = [];
|
|
55588
56092
|
sample.value = Math.max(res / 100, 1 - res / 100);
|
|
55589
56093
|
sample.min_score = Math.min(res / 100, 1 - res / 100);
|
|
55590
56094
|
|
|
@@ -55600,7 +56104,7 @@
|
|
|
55600
56104
|
|
|
55601
56105
|
//console.log('getAllbins', bins["value"])
|
|
55602
56106
|
|
|
55603
|
-
const fitter = new GetFit(bins);
|
|
56107
|
+
const fitter = new g_utils.GetFit(bins);
|
|
55604
56108
|
|
|
55605
56109
|
fitter.fit_data();
|
|
55606
56110
|
// dconsole.log('rd list', distParams)
|
|
@@ -55608,7 +56112,7 @@
|
|
|
55608
56112
|
return bins
|
|
55609
56113
|
}
|
|
55610
56114
|
|
|
55611
|
-
async read_rd_baf(){
|
|
56115
|
+
async read_rd_baf(caller='ReadDepth'){
|
|
55612
56116
|
|
|
55613
56117
|
const chromosomes = Object.keys(this.allVariants);
|
|
55614
56118
|
var wigFeatures = {};
|
|
@@ -55654,13 +56158,22 @@
|
|
|
55654
56158
|
}
|
|
55655
56159
|
|
|
55656
56160
|
}
|
|
55657
|
-
|
|
56161
|
+
|
|
55658
56162
|
var avgbin = this.adjust_bin_size(wigFeatures);
|
|
56163
|
+
var finalFeatureSet;
|
|
56164
|
+
if(caller == 'ReadDepth'){
|
|
56165
|
+
finalFeatureSet = this.readDepthMeanshift(avgbin);
|
|
56166
|
+
var baf = this.formatDataStructure_BAF(avgbin, 'max_likelihood');
|
|
56167
|
+
}else if(caller=='2D'){
|
|
56168
|
+
|
|
56169
|
+
let caller_obj = new combined_caller.CombinedCaller(avgbin, this.binSize);
|
|
56170
|
+
let processed_bins = await caller_obj.call_2d();
|
|
56171
|
+
|
|
56172
|
+
finalFeatureSet = [processed_bins.binScore, [], processed_bins.segment_score];
|
|
56173
|
+
|
|
56174
|
+
var baf = caller_obj.formatDataStructure_BAF('max_likelihood');
|
|
56175
|
+
}
|
|
55659
56176
|
|
|
55660
|
-
let finalFeatureSet = this.readDepthMeanshift(avgbin);
|
|
55661
|
-
|
|
55662
|
-
//var rawbinScore = this.formatDataStructure(avgbin, 'binScore', globamMean)
|
|
55663
|
-
var baf = this.formatDataStructure_BAF(avgbin, 'max_likelihood');
|
|
55664
56177
|
|
|
55665
56178
|
return [finalFeatureSet, baf]
|
|
55666
56179
|
}
|
|
@@ -55723,19 +56236,19 @@
|
|
|
55723
56236
|
|
|
55724
56237
|
wigFeatures[chr][j].hets.forEach((hets, hets_idx) => {
|
|
55725
56238
|
if(avgbin[chr][k].likelihood_score.length == 0){
|
|
55726
|
-
avgbin[chr][k].likelihood_score = linspace(0, 1, 100).map((value, index) => {
|
|
56239
|
+
avgbin[chr][k].likelihood_score = g_utils.linspace(0, 1, 100).map((value, index) => {
|
|
55727
56240
|
return beta(hets.ref, hets.alt, value);
|
|
55728
56241
|
});
|
|
55729
56242
|
}
|
|
55730
56243
|
else {
|
|
55731
56244
|
var likelihood_sum = 0;
|
|
55732
|
-
avgbin[chr][k].likelihood_score = linspace(0, 1, 100).map((value, index) => {
|
|
56245
|
+
avgbin[chr][k].likelihood_score = g_utils.linspace(0, 1, 100).map((value, index) => {
|
|
55733
56246
|
var likelihood_value = avgbin[chr][k].likelihood_score[index] * beta(hets.ref, hets.alt, value);
|
|
55734
56247
|
likelihood_sum += likelihood_value;
|
|
55735
56248
|
return likelihood_value;
|
|
55736
56249
|
});
|
|
55737
56250
|
|
|
55738
|
-
avgbin[chr][k].likelihood_score = linspace(0, 1, 100).map((value, index) => {
|
|
56251
|
+
avgbin[chr][k].likelihood_score = g_utils.linspace(0, 1, 100).map((value, index) => {
|
|
55739
56252
|
return avgbin[chr][k].likelihood_score[index] / likelihood_sum;
|
|
55740
56253
|
});
|
|
55741
56254
|
|
|
@@ -55760,19 +56273,6 @@
|
|
|
55760
56273
|
return p ** a * (1 - p) ** b + p ** b * (1 - p) ** a;
|
|
55761
56274
|
}
|
|
55762
56275
|
|
|
55763
|
-
function linspace(a, b, n) {
|
|
55764
|
-
if (typeof n === "undefined") n = Math.max(Math.round(b - a) + 1, 1);
|
|
55765
|
-
if (n < 2) {
|
|
55766
|
-
return n === 1 ? [a] : [];
|
|
55767
|
-
}
|
|
55768
|
-
var ret = Array(n);
|
|
55769
|
-
n--;
|
|
55770
|
-
for (let i = n; i >= 0; i--) {
|
|
55771
|
-
ret[i] = (i * b + (n - i) * a) / n;
|
|
55772
|
-
}
|
|
55773
|
-
return ret;
|
|
55774
|
-
}
|
|
55775
|
-
|
|
55776
56276
|
/*
|
|
55777
56277
|
* The MIT License (MIT)
|
|
55778
56278
|
*
|
|
@@ -55883,29 +56383,43 @@
|
|
|
55883
56383
|
}, Object.create(null));
|
|
55884
56384
|
|
|
55885
56385
|
const cnvpytor_obj = new CNVpytorVCF(allVariants, this.bin_size);
|
|
55886
|
-
//const wigFeatures = await cnvpytor_obj.computeReadDepth()
|
|
55887
|
-
//const bafFeatures = await cnvpytor_obj.computeBAF_v2()
|
|
55888
|
-
const dataWigs = await cnvpytor_obj.read_rd_baf();
|
|
55889
|
-
const wigFeatures = dataWigs[0];
|
|
55890
|
-
const bafFeatures = dataWigs[1];
|
|
55891
56386
|
|
|
56387
|
+
let wigFeatures;
|
|
56388
|
+
let bafFeatures;
|
|
55892
56389
|
this.wigFeatures_obj = {};
|
|
55893
|
-
this.wigFeatures_obj[this.bin_size] = {
|
|
55894
|
-
|
|
55895
|
-
|
|
55896
|
-
|
|
55897
|
-
|
|
55898
|
-
|
|
55899
|
-
|
|
55900
|
-
|
|
55901
|
-
|
|
55902
|
-
|
|
56390
|
+
this.wigFeatures_obj[this.bin_size] = {};
|
|
56391
|
+
|
|
56392
|
+
let dataWigs;
|
|
56393
|
+
if(this.config.cnv_caller == '2D'){
|
|
56394
|
+
|
|
56395
|
+
dataWigs = await cnvpytor_obj.read_rd_baf('2D');
|
|
56396
|
+
|
|
56397
|
+
wigFeatures = dataWigs[0];
|
|
56398
|
+
bafFeatures = dataWigs[1];
|
|
56399
|
+
this.wigFeatures_obj[this.bin_size]['2D'] = wigFeatures[2];
|
|
56400
|
+
|
|
56401
|
+
this.available_callers = ['2D'];
|
|
56402
|
+
}else {
|
|
56403
|
+
dataWigs = await cnvpytor_obj.read_rd_baf();
|
|
56404
|
+
wigFeatures = dataWigs[0];
|
|
56405
|
+
bafFeatures = dataWigs[1];
|
|
56406
|
+
this.wigFeatures_obj[this.bin_size]['ReadDepth'] = wigFeatures[2];
|
|
56407
|
+
this.available_callers = ['ReadDepth'];
|
|
56408
|
+
}
|
|
56409
|
+
|
|
56410
|
+
this.wigFeatures_obj[this.bin_size]['RD_Raw'] = wigFeatures[0];
|
|
56411
|
+
this.wigFeatures_obj[this.bin_size]['RD_Raw_gc_coor'] = wigFeatures[1];
|
|
56412
|
+
this.wigFeatures_obj[this.bin_size]['BAF1'] = bafFeatures[0];
|
|
56413
|
+
this.wigFeatures_obj[this.bin_size]['BAF2'] = bafFeatures[1];
|
|
56414
|
+
|
|
56415
|
+
this.available_bins = [this.bin_size];
|
|
56416
|
+
|
|
55903
56417
|
this.set_available_callers();
|
|
55904
56418
|
|
|
55905
56419
|
} else {
|
|
55906
56420
|
this.cnvpytor_obj = new HDF5Reader(this.config.url, this.bin_size);
|
|
55907
56421
|
this.wigFeatures_obj = await this.cnvpytor_obj.get_rd_signal(this.bin_size);
|
|
55908
|
-
this.
|
|
56422
|
+
this.available_bins = this.cnvpytor_obj.available_bins;
|
|
55909
56423
|
this.available_callers = this.cnvpytor_obj.callers;
|
|
55910
56424
|
this.set_available_callers();
|
|
55911
56425
|
}
|
|
@@ -56018,7 +56532,7 @@
|
|
|
56018
56532
|
|
|
56019
56533
|
items.push('<hr/>');
|
|
56020
56534
|
items.push("Bin Sizes");
|
|
56021
|
-
for (let rd_bin of this.
|
|
56535
|
+
for (let rd_bin of this.available_bins) {
|
|
56022
56536
|
const checkBox = createCheckbox(rd_bin, rd_bin === this.bin_size);
|
|
56023
56537
|
items.push({
|
|
56024
56538
|
object: $$1(checkBox),
|