igv 2.15.1 → 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 +670 -173
- package/dist/igv.esm.min.js +6 -6
- package/dist/igv.esm.min.js.map +1 -1
- package/dist/igv.js +670 -173
- package/dist/igv.min.js +6 -6
- package/dist/igv.min.js.map +1 -1
- package/package.json +2 -2
package/dist/igv.esm.js
CHANGED
|
@@ -18656,6 +18656,8 @@ class IGVXhr {
|
|
|
18656
18656
|
|
|
18657
18657
|
async _loadURL(url, options) {
|
|
18658
18658
|
|
|
18659
|
+
const self = this;
|
|
18660
|
+
|
|
18659
18661
|
//console.log(`${Date.now()} ${url}`)
|
|
18660
18662
|
url = mapUrl$1(url);
|
|
18661
18663
|
|
|
@@ -18745,7 +18747,7 @@ class IGVXhr {
|
|
|
18745
18747
|
// For small files a range starting at 0 can return the whole file => 200
|
|
18746
18748
|
// Provide just the slice we asked for, throw out the rest quietly
|
|
18747
18749
|
// If file is large warn user
|
|
18748
|
-
if (xhr.response.length > 100000 && !
|
|
18750
|
+
if (xhr.response.length > 100000 && !self.RANGE_WARNING_GIVEN) {
|
|
18749
18751
|
alert(`Warning: Range header ignored for URL: ${url}. This can have severe performance impacts.`);
|
|
18750
18752
|
}
|
|
18751
18753
|
resolve(xhr.response.slice(range.start, range.start + range.size));
|
|
@@ -18774,8 +18776,9 @@ class IGVXhr {
|
|
|
18774
18776
|
xhr.onerror = function (event) {
|
|
18775
18777
|
if (isGoogleURL(url) && !options.retries) {
|
|
18776
18778
|
tryGoogleAuth();
|
|
18779
|
+
} else {
|
|
18780
|
+
handleError("Error accessing resource: " + url + " Status: " + xhr.status);
|
|
18777
18781
|
}
|
|
18778
|
-
handleError("Error accessing resource: " + url + " Status: " + xhr.status);
|
|
18779
18782
|
};
|
|
18780
18783
|
|
|
18781
18784
|
xhr.ontimeout = function (event) {
|
|
@@ -18790,7 +18793,11 @@ class IGVXhr {
|
|
|
18790
18793
|
try {
|
|
18791
18794
|
xhr.send(sendData);
|
|
18792
18795
|
} catch (e) {
|
|
18793
|
-
|
|
18796
|
+
if (isGoogleURL(url) && !options.retries) {
|
|
18797
|
+
tryGoogleAuth();
|
|
18798
|
+
} else {
|
|
18799
|
+
handleError(e);
|
|
18800
|
+
}
|
|
18794
18801
|
}
|
|
18795
18802
|
|
|
18796
18803
|
|
|
@@ -18807,7 +18814,7 @@ class IGVXhr {
|
|
|
18807
18814
|
const accessToken = await fetchGoogleAccessToken(url);
|
|
18808
18815
|
options.retries = 1;
|
|
18809
18816
|
options.oauthToken = accessToken;
|
|
18810
|
-
const response = await
|
|
18817
|
+
const response = await self.load(url, options);
|
|
18811
18818
|
resolve(response);
|
|
18812
18819
|
} catch (e) {
|
|
18813
18820
|
if (e.error) {
|
|
@@ -18953,14 +18960,16 @@ function addTeamDrive(url) {
|
|
|
18953
18960
|
*/
|
|
18954
18961
|
function mapUrl$1(url) {
|
|
18955
18962
|
|
|
18956
|
-
if (url.
|
|
18963
|
+
if (url.startsWith("https://www.dropbox.com")) {
|
|
18957
18964
|
return url.replace("//www.dropbox.com", "//dl.dropboxusercontent.com")
|
|
18958
|
-
} else if (url.
|
|
18965
|
+
} else if (url.startsWith("https://drive.google.com")) {
|
|
18959
18966
|
return getDriveDownloadURL(url)
|
|
18960
18967
|
} else if (url.includes("//www.broadinstitute.org/igvdata")) {
|
|
18961
18968
|
return url.replace("//www.broadinstitute.org/igvdata", "//data.broadinstitute.org/igvdata")
|
|
18962
18969
|
} else if (url.includes("//igvdata.broadinstitute.org")) {
|
|
18963
|
-
return url.replace("//igvdata.broadinstitute.org", "
|
|
18970
|
+
return url.replace("//igvdata.broadinstitute.org", "//s3.amazonaws.com/igv.broadinstitute.org")
|
|
18971
|
+
} else if (url.includes("//igv.genepattern.org")) {
|
|
18972
|
+
return url.replace("//igv.genepattern.org", "//igv-genepattern-org.s3.amazonaws.com")
|
|
18964
18973
|
} else if (url.startsWith("ftp://ftp.ncbi.nlm.nih.gov/geo")) {
|
|
18965
18974
|
return url.replace("ftp://", "https://")
|
|
18966
18975
|
} else {
|
|
@@ -23922,7 +23931,7 @@ const Cytoband = function (start, end, name, typestain) {
|
|
|
23922
23931
|
}
|
|
23923
23932
|
};
|
|
23924
23933
|
|
|
23925
|
-
const _version = "2.15.
|
|
23934
|
+
const _version = "2.15.2";
|
|
23926
23935
|
function version() {
|
|
23927
23936
|
return _version
|
|
23928
23937
|
}
|
|
@@ -25759,15 +25768,15 @@ function decodeGTF(tokens, header) {
|
|
|
25759
25768
|
* @param keyValueDelim
|
|
25760
25769
|
* @returns {[]}
|
|
25761
25770
|
*/
|
|
25762
|
-
function parseAttributeString(attributeString, keyValueDelim) {
|
|
25771
|
+
function parseAttributeString(attributeString, keyValueDelim, relaxed = false) {
|
|
25763
25772
|
// parse 'attributes' string (see column 9 docs in https://github.com/The-Sequence-Ontology/Specifications/blob/master/gff3.md)
|
|
25764
25773
|
var attributes = [];
|
|
25765
25774
|
for (let kv of attributeString.split(';')) {
|
|
25766
25775
|
kv = kv.trim();
|
|
25767
25776
|
const idx = kv.indexOf(keyValueDelim);
|
|
25768
25777
|
if (idx > 0 && idx < kv.length - 1) {
|
|
25769
|
-
const key = kv.substring(0, idx);
|
|
25770
|
-
let value = stripQuotes(decodeGFFAttribute(kv.substring(idx + 1).trim()));
|
|
25778
|
+
const key = stripQuotes(decodeGFFAttribute(kv.substring(0, idx).trim(), relaxed));
|
|
25779
|
+
let value = stripQuotes(decodeGFFAttribute(kv.substring(idx + 1).trim(), relaxed));
|
|
25771
25780
|
attributes.push([key, value]);
|
|
25772
25781
|
}
|
|
25773
25782
|
}
|
|
@@ -25806,11 +25815,14 @@ const encodings = new Map([
|
|
|
25806
25815
|
["%2C", ","]
|
|
25807
25816
|
]);
|
|
25808
25817
|
|
|
25809
|
-
function decodeGFFAttribute(str) {
|
|
25818
|
+
function decodeGFFAttribute(str, relaxed = false) {
|
|
25810
25819
|
|
|
25811
25820
|
if (!str.includes("%")) {
|
|
25812
25821
|
return str
|
|
25813
25822
|
}
|
|
25823
|
+
if (relaxed) {
|
|
25824
|
+
return decodeURIComponent(str);
|
|
25825
|
+
}
|
|
25814
25826
|
let decoded = "";
|
|
25815
25827
|
for (let i = 0; i < str.length; i++) {
|
|
25816
25828
|
|
|
@@ -25868,7 +25880,7 @@ function decodeBed(tokens, header) {
|
|
|
25868
25880
|
|
|
25869
25881
|
// Potentially parse name field as GFF column 9 style streng.
|
|
25870
25882
|
if (tokens[3].indexOf(';') > 0 && tokens[3].indexOf('=') > 0) {
|
|
25871
|
-
const attributeKVs = parseAttributeString(tokens[3], '=');
|
|
25883
|
+
const attributeKVs = parseAttributeString(tokens[3], '=', true);
|
|
25872
25884
|
feature.attributes = {};
|
|
25873
25885
|
for (let kv of attributeKVs) {
|
|
25874
25886
|
feature.attributes[kv[0]] = kv[1];
|
|
@@ -27269,6 +27281,8 @@ class TrackBase {
|
|
|
27269
27281
|
}
|
|
27270
27282
|
tracklineConfg.autoscale = false;
|
|
27271
27283
|
tracklineConfg.dataRange = {min, max};
|
|
27284
|
+
this.viewLimitMin = min;
|
|
27285
|
+
this.viewLimitMax = max;
|
|
27272
27286
|
}
|
|
27273
27287
|
case "name":
|
|
27274
27288
|
tracklineConfg[key] = properties[key];
|
|
@@ -29167,9 +29181,9 @@ function optimizeChunks(chunks, lowest) {
|
|
|
29167
29181
|
* @returns {boolean|boolean}
|
|
29168
29182
|
*/
|
|
29169
29183
|
function canMerge(chunk1, chunk2) {
|
|
29170
|
-
|
|
29184
|
+
chunk2.minv.block - chunk1.maxv.block;
|
|
29171
29185
|
const sizeEstimate = chunk1.maxv.block - chunk1.minv.block;
|
|
29172
|
-
return
|
|
29186
|
+
return sizeEstimate < 5000000
|
|
29173
29187
|
}
|
|
29174
29188
|
|
|
29175
29189
|
// Represents a CSI Bam or Tabix index
|
|
@@ -40792,8 +40806,8 @@ class FeatureTrack extends TrackBase {
|
|
|
40792
40806
|
color = IGVColor.addAlpha(color, feature.alpha);
|
|
40793
40807
|
} else if (this.useScore && feature.score && !Number.isNaN(feature.score)) {
|
|
40794
40808
|
// UCSC useScore option, for scores between 0-1000. See https://genome.ucsc.edu/goldenPath/help/customTrack.html#TRACK
|
|
40795
|
-
const min = this.config.min ? this.config.min : 0;
|
|
40796
|
-
const max = this.config.max ? this.config.max : 1000;
|
|
40809
|
+
const min = this.config.min ? this.config.min : this.viewLimitMin ? this.viewLimitMin : 0;
|
|
40810
|
+
const max = this.config.max ? this.config.max : this.viewLimitMax ? this.viewLimitMax : 1000;
|
|
40797
40811
|
const alpha = getAlpha(min, max, feature.score);
|
|
40798
40812
|
feature.alpha = alpha; // Avoid computing again
|
|
40799
40813
|
color = IGVColor.addAlpha(color, alpha);
|
|
@@ -54162,11 +54176,13 @@ class HDF5Reader {
|
|
|
54162
54176
|
|
|
54163
54177
|
// console.log(h5_obj_keys)
|
|
54164
54178
|
let signal_bin = new ParseSignals(h5_obj_keys);
|
|
54165
|
-
|
|
54179
|
+
let rd_bins = signal_bin.get_rd_bins();
|
|
54180
|
+
let snp_bins = signal_bin.get_snp_bins();
|
|
54181
|
+
this.available_bins = [...new Set(rd_bins, snp_bins)];
|
|
54166
54182
|
|
|
54167
54183
|
// let bin_size = this.bin_size
|
|
54168
|
-
if(! this.
|
|
54169
|
-
bin_size = this.
|
|
54184
|
+
if(! this.available_bins.includes(bin_size)){
|
|
54185
|
+
bin_size = this.available_bins.at(-1);
|
|
54170
54186
|
}
|
|
54171
54187
|
|
|
54172
54188
|
const chr_ds = await h5_obj.get("rd_chromosomes");
|
|
@@ -54210,6 +54226,9 @@ class HDF5Reader {
|
|
|
54210
54226
|
let signal_baf_1 = `snp_likelihood_${chrom}_${bin_size}_mask`;
|
|
54211
54227
|
let chr_wig_bafs = await this.get_baf_signals(h5_obj, h5_obj_keys, chrom, bin_size, signal_baf_1);
|
|
54212
54228
|
|
|
54229
|
+
// let signal_baf_1 = `snp_i1_${chrom}_${bin_size}_mask`
|
|
54230
|
+
// let chr_wig_bafs = await this.get_baf_signals_v2(h5_obj, h5_obj_keys, chrom, bin_size, signal_baf_1)
|
|
54231
|
+
|
|
54213
54232
|
wigFeatures_baf1 = wigFeatures_baf1.concat(chr_wig_bafs[0]);
|
|
54214
54233
|
wigFeatures_baf2 = wigFeatures_baf2.concat(chr_wig_bafs[1]);
|
|
54215
54234
|
// this.rd_call_combined(h5_obj, h5_obj_keys, chrom, bin_size, rd_stat)
|
|
@@ -54334,6 +54353,28 @@ class HDF5Reader {
|
|
|
54334
54353
|
}
|
|
54335
54354
|
return [chr_wig_1, chr_wig_2]
|
|
54336
54355
|
}
|
|
54356
|
+
|
|
54357
|
+
async get_baf_signals_v2(h5_obj, h5_obj_keys, chrom, bin_size, signal_name){
|
|
54358
|
+
|
|
54359
|
+
/* return two list of dictionary*/
|
|
54360
|
+
let chr_wig_1 = [];
|
|
54361
|
+
let chr_wig_2 = [];
|
|
54362
|
+
if (h5_obj_keys.includes(signal_name)){
|
|
54363
|
+
let chrom_dataset = await h5_obj.get(signal_name);
|
|
54364
|
+
let chrom_data = await chrom_dataset.to_array(); //create_nested_array(value, shape)
|
|
54365
|
+
chrom_data.forEach((lh, bin_idx) => {
|
|
54366
|
+
if (!isNaN(lh)){
|
|
54367
|
+
chr_wig_1.push({chr:chrom, start: bin_idx*bin_size, end: (bin_idx+1) * bin_size, value: -2 * ( 0.5 - lh )});
|
|
54368
|
+
if(lh != 0.5){
|
|
54369
|
+
chr_wig_2.push({chr:chrom, start: bin_idx*bin_size, end: (bin_idx+1) * bin_size, value: -2 * ( 0.5 + lh )});
|
|
54370
|
+
}
|
|
54371
|
+
}
|
|
54372
|
+
});
|
|
54373
|
+
}
|
|
54374
|
+
console.log(chrom, chr_wig_1, chr_wig_2);
|
|
54375
|
+
return [chr_wig_1, chr_wig_2]
|
|
54376
|
+
|
|
54377
|
+
}
|
|
54337
54378
|
}
|
|
54338
54379
|
|
|
54339
54380
|
class ParseSignals{
|
|
@@ -54374,6 +54415,53 @@ class ParseSignals{
|
|
|
54374
54415
|
}
|
|
54375
54416
|
}
|
|
54376
54417
|
|
|
54418
|
+
class GetFit {
|
|
54419
|
+
constructor(allBins) {
|
|
54420
|
+
this.allBins = allBins;
|
|
54421
|
+
}
|
|
54422
|
+
getValues() {
|
|
54423
|
+
const bins = Object.values(this.allBins).reduce(
|
|
54424
|
+
(binResult, bin) => { return binResult.concat(bin.filter(a => a.binScore > 0).map(a => a.binScore)) }, []);
|
|
54425
|
+
return bins
|
|
54426
|
+
}
|
|
54427
|
+
getMean(data) {
|
|
54428
|
+
return (data.reduce(function (a, b) { return a + b; }) / data.length);
|
|
54429
|
+
}
|
|
54430
|
+
fit_data() {
|
|
54431
|
+
let rd_list = this.getValues();
|
|
54432
|
+
let distParmas = getDistParams(rd_list);
|
|
54433
|
+
return distParmas
|
|
54434
|
+
}
|
|
54435
|
+
|
|
54436
|
+
histogram(data, bins) {
|
|
54437
|
+
const step = bins[1] - bins[0];
|
|
54438
|
+
const hist_bins = [];
|
|
54439
|
+
|
|
54440
|
+
data.forEach((value, index) => {
|
|
54441
|
+
bins.forEach((bin_value, bin_index) => {
|
|
54442
|
+
if (!hist_bins[bin_value]) {
|
|
54443
|
+
hist_bins[bin_value] = { count: 0 };
|
|
54444
|
+
}
|
|
54445
|
+
if (bin_value <= value && value < bin_value + step) {
|
|
54446
|
+
hist_bins[bin_value].count++;
|
|
54447
|
+
return false;
|
|
54448
|
+
}
|
|
54449
|
+
});
|
|
54450
|
+
});
|
|
54451
|
+
const dist_p = [];
|
|
54452
|
+
hist_bins.forEach((bin, index) => { dist_p.push(bin.count); });
|
|
54453
|
+
return dist_p
|
|
54454
|
+
}
|
|
54455
|
+
|
|
54456
|
+
}
|
|
54457
|
+
|
|
54458
|
+
function range_function(start, stop, step) {
|
|
54459
|
+
const data_array = Array(Math.ceil((stop - start) / step))
|
|
54460
|
+
.fill(start)
|
|
54461
|
+
.map((x, y) => x + y * step);
|
|
54462
|
+
return data_array;
|
|
54463
|
+
}
|
|
54464
|
+
|
|
54377
54465
|
function filterOutliers(someArray) {
|
|
54378
54466
|
|
|
54379
54467
|
if (someArray.length < 4)
|
|
@@ -54406,6 +54494,21 @@ function getDistParams(bins) {
|
|
|
54406
54494
|
return [mean, std]
|
|
54407
54495
|
}
|
|
54408
54496
|
|
|
54497
|
+
function linspace(a, b, n) {
|
|
54498
|
+
if (typeof n === "undefined") n = Math.max(Math.round(b - a) + 1, 1);
|
|
54499
|
+
if (n < 2) {
|
|
54500
|
+
return n === 1 ? [a] : [];
|
|
54501
|
+
}
|
|
54502
|
+
var ret = Array(n);
|
|
54503
|
+
n--;
|
|
54504
|
+
for (let i = n; i >= 0; i--) {
|
|
54505
|
+
ret[i] = (i * b + (n - i) * a) / n;
|
|
54506
|
+
}
|
|
54507
|
+
return ret;
|
|
54508
|
+
}
|
|
54509
|
+
|
|
54510
|
+
var g_utils = { range_function, getDistParams, linspace, GetFit};
|
|
54511
|
+
|
|
54409
54512
|
/**
|
|
54410
54513
|
* Evaluates the cumulative distribution function (CDF) for a Student's t distribution with degrees of freedom `v` at a value `t`.
|
|
54411
54514
|
*
|
|
@@ -54550,48 +54653,507 @@ function lgamma(xg){
|
|
|
54550
54653
|
return Math.log(gamma(xg))
|
|
54551
54654
|
}
|
|
54552
54655
|
|
|
54553
|
-
|
|
54656
|
+
function t_test_1_sample$1(mean, m, s, n) {
|
|
54657
|
+
if (s == 0) s = 1;
|
|
54658
|
+
var t = ((mean - m) / s) * Math.sqrt(n);
|
|
54659
|
+
var p = 1.0 - TdistributionCDF(Math.abs(t), (n - 1));
|
|
54660
|
+
return p
|
|
54661
|
+
}
|
|
54554
54662
|
|
|
54555
|
-
|
|
54556
|
-
|
|
54557
|
-
|
|
54558
|
-
|
|
54559
|
-
|
|
54560
|
-
|
|
54561
|
-
|
|
54562
|
-
|
|
54663
|
+
function t_test_2_samples$1(m1, s1, n1, m2, s2, n2) {
|
|
54664
|
+
if (s1 == 0) s1 = 1;
|
|
54665
|
+
if (s2 == 0) s2 = 1;
|
|
54666
|
+
var t = (m1 - m2) / Math.sqrt(s1 ** 2 / n1 + s2 ** 2 / n2);
|
|
54667
|
+
var df = ((s1 ** 2 / n1 + s2 ** 2 / n2) ** 2 * (n1 - 1) * (n2 - 1)) /
|
|
54668
|
+
((s1 ** 4 * (n2 - 1)) / n1 ** 2 + (s2 ** 4 * (n1 - 1)) / n2 ** 2);
|
|
54669
|
+
|
|
54670
|
+
var p = 1.0 - TdistributionCDF(Math.abs(t), parseInt(df + 0.5));
|
|
54671
|
+
|
|
54672
|
+
return p
|
|
54673
|
+
}
|
|
54674
|
+
|
|
54675
|
+
var t_dist = {TdistributionCDF, gamma, t_test_1_sample: t_test_1_sample$1, t_test_2_samples: t_test_2_samples$1};
|
|
54676
|
+
|
|
54677
|
+
class CombinedCaller{
|
|
54678
|
+
constructor(wigFeatures, binSize) {
|
|
54679
|
+
this.wigFeatures = wigFeatures;
|
|
54680
|
+
this.binSize = binSize;
|
|
54681
|
+
// let fit_obj = this.get_fit()
|
|
54682
|
+
// this.globalMean = fit_obj.globalMean
|
|
54683
|
+
// this.globalStd = fit_obj.globalStd
|
|
54563
54684
|
}
|
|
54564
|
-
|
|
54565
|
-
|
|
54685
|
+
get_fit(){
|
|
54686
|
+
var fit_info = new g_utils.GetFit(this.wigFeatures);
|
|
54687
|
+
var [globalMean, globalStd] = fit_info.fit_data();
|
|
54688
|
+
|
|
54689
|
+
return {globalMean:globalMean, globalStd:globalStd}
|
|
54690
|
+
|
|
54566
54691
|
}
|
|
54567
|
-
|
|
54568
|
-
|
|
54569
|
-
let
|
|
54570
|
-
|
|
54692
|
+
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){
|
|
54693
|
+
|
|
54694
|
+
let fit_obj = this.get_fit();
|
|
54695
|
+
this.globalMean = fit_obj.globalMean;
|
|
54696
|
+
this.globalStd = fit_obj.globalStd;
|
|
54697
|
+
|
|
54698
|
+
let overlap_min = omin==null ? 0.05 * this.binSize / 3e9: omin ;
|
|
54699
|
+
let min_count = mcount == null ? parseInt(this.binSize / 10000) : mcount ;
|
|
54700
|
+
|
|
54701
|
+
let gstat_rd0 = [];
|
|
54702
|
+
let gstat_rd_all = [];
|
|
54703
|
+
let gstat_rd = [];
|
|
54704
|
+
let gstat_error = [];
|
|
54705
|
+
let gstat_lh = [];
|
|
54706
|
+
let gstat_n = [];
|
|
54707
|
+
|
|
54708
|
+
for (const [chr, wig] of Object.entries(this.wigFeatures)) {
|
|
54709
|
+
let segments = [];
|
|
54710
|
+
let levels = [];
|
|
54711
|
+
let likelihoods = [];
|
|
54712
|
+
|
|
54713
|
+
wig.forEach((bin, bin_idx) => {
|
|
54714
|
+
if (bin.hets_count > 4 ){
|
|
54715
|
+
|
|
54716
|
+
if( bin.dp_count > min_count ){
|
|
54717
|
+
segments.push([bin_idx]);
|
|
54718
|
+
levels.push(bin.binScore);
|
|
54719
|
+
likelihoods.push(bin.likelihood_score);
|
|
54720
|
+
delete bin.likelihood_score;
|
|
54721
|
+
|
|
54722
|
+
}
|
|
54723
|
+
}
|
|
54724
|
+
});
|
|
54725
|
+
|
|
54726
|
+
let diff_level = [];
|
|
54727
|
+
for(let i=1; i<levels.length; i++){
|
|
54728
|
+
diff_level.push(Math.abs(levels[i] - levels[i-1]));
|
|
54729
|
+
}
|
|
54730
|
+
let min_flank = [0];
|
|
54731
|
+
for(let i=1; i<diff_level.length; i++){
|
|
54732
|
+
min_flank.push(Math.min(diff_level[i-1], diff_level[i]));
|
|
54733
|
+
}
|
|
54734
|
+
min_flank.push(0);
|
|
54735
|
+
|
|
54736
|
+
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));});
|
|
54737
|
+
|
|
54738
|
+
let overlaps = [];
|
|
54739
|
+
|
|
54740
|
+
for(let i=0; i< segments.length-1; i++){
|
|
54741
|
+
|
|
54742
|
+
let lh_overlap = 0;
|
|
54743
|
+
try{
|
|
54744
|
+
lh_overlap = likelihood_overlap(likelihoods[i], likelihoods[i+1]);
|
|
54745
|
+
}catch{
|
|
54746
|
+
console.log("Overlap failed: ", i, likelihoods[i], segments[i+1], likelihoods[i+1]);
|
|
54747
|
+
}
|
|
54748
|
+
|
|
54749
|
+
let rd_overlap = normal_overlap_approx(levels[i], error[i], levels[i+1], error[i+1]);
|
|
54750
|
+
overlaps.push(rd_overlap * lh_overlap);
|
|
54751
|
+
|
|
54752
|
+
}
|
|
54753
|
+
|
|
54754
|
+
while(overlaps.length >0) {
|
|
54755
|
+
overlaps = overlaps.filter(num => typeof num === "number");
|
|
54756
|
+
|
|
54757
|
+
let max_overlap = arrayMax(overlaps);
|
|
54758
|
+
if(isNaN(max_overlap)){
|
|
54759
|
+
console.log('NaN value', overlaps);
|
|
54760
|
+
}
|
|
54761
|
+
if(max_overlap < overlap_min){
|
|
54762
|
+
// console.log("maxoverlap ",max_overlap, "is smaller than overlap min")
|
|
54763
|
+
break
|
|
54764
|
+
}
|
|
54765
|
+
let i = overlaps.indexOf(max_overlap);
|
|
54766
|
+
|
|
54767
|
+
let merge_level = normal_merge(levels[i], error[i], levels[i + 1], error[i + 1]);
|
|
54768
|
+
|
|
54769
|
+
let nlh;
|
|
54770
|
+
let nlh_sum;
|
|
54771
|
+
try{
|
|
54772
|
+
nlh = likelihoods[i].map((l_value, l_idx) => { return l_value * likelihoods[i+1][l_idx]});
|
|
54773
|
+
|
|
54774
|
+
nlh_sum = nlh.reduce((a, c_value) => {return a + c_value});
|
|
54775
|
+
|
|
54776
|
+
}catch{
|
|
54777
|
+
console.log(likelihoods);
|
|
54778
|
+
console.log('max_overlap:', max_overlap, i, overlaps.length);
|
|
54779
|
+
console.log('likelihood: ', i ,likelihoods[i], likelihoods[i+1]);
|
|
54780
|
+
console.log('nlh: ', nlh_sum);
|
|
54781
|
+
}
|
|
54782
|
+
// nlh_sum = nlh.reduce((a, c_value) => {return a + c_value});
|
|
54783
|
+
|
|
54784
|
+
levels[i] = merge_level.nl;
|
|
54785
|
+
error[i] = merge_level.ne;
|
|
54786
|
+
|
|
54787
|
+
likelihoods[i] = nlh.map(function(item) { return item/nlh_sum } );
|
|
54788
|
+
|
|
54789
|
+
segments[i].push(...segments[i+1]);
|
|
54790
|
+
|
|
54791
|
+
levels.splice(i + 1, 1);
|
|
54792
|
+
error.splice(i + 1, 1);
|
|
54793
|
+
segments.splice(i + 1, 1);
|
|
54794
|
+
likelihoods.splice(i + 1, 1);
|
|
54795
|
+
overlaps.splice(i, 1);
|
|
54796
|
+
|
|
54797
|
+
if(i < overlaps.length){
|
|
54798
|
+
|
|
54799
|
+
let rd_overlap = normal_overlap_approx(levels[i], error[i], levels[i+1], error[i+1]);
|
|
54800
|
+
let new_overlap = rd_overlap * likelihood_overlap(likelihoods[i], likelihoods[i + 1]);
|
|
54801
|
+
|
|
54802
|
+
overlaps[i] = new_overlap;
|
|
54803
|
+
}
|
|
54804
|
+
if(i > 0){
|
|
54805
|
+
let new_overlap = normal_overlap_approx(levels[i - 1], error[i - 1], levels[i], error[i])
|
|
54806
|
+
* likelihood_overlap(likelihoods[i - 1], likelihoods[i]);
|
|
54807
|
+
overlaps[i - 1] = new_overlap;
|
|
54808
|
+
}
|
|
54809
|
+
|
|
54810
|
+
}
|
|
54811
|
+
let ons = -1;
|
|
54812
|
+
while(true){
|
|
54813
|
+
overlaps = [];
|
|
54814
|
+
for(let i=0; i< levels.length; i++){
|
|
54815
|
+
for(let j=i; j<levels.length; j++){
|
|
54816
|
+
if(segments[j][0] - segments[i].at(-1) < max_distance * (segments[i].length + segments[j].length)){
|
|
54817
|
+
overlaps.push(normal_overlap_approx(levels[i], error[i], levels[j], error[j]) * likelihood_overlap(likelihoods[i], likelihoods[j]));
|
|
54818
|
+
}
|
|
54819
|
+
}
|
|
54820
|
+
}
|
|
54821
|
+
|
|
54822
|
+
if(overlaps.length == 0){
|
|
54823
|
+
break
|
|
54824
|
+
}
|
|
54825
|
+
let max_overlap = arrayMax(overlaps);
|
|
54826
|
+
if(max_overlap < overlap_min){
|
|
54827
|
+
break
|
|
54828
|
+
}
|
|
54829
|
+
let i = 0;
|
|
54830
|
+
let j = 1;
|
|
54831
|
+
while (i < segments.length - 1){
|
|
54832
|
+
let overlap_value = normal_overlap_approx(levels[i], error[i], levels[j], error[j]) * likelihood_overlap(likelihoods[i], likelihoods[j]);
|
|
54833
|
+
|
|
54834
|
+
if((segments[j][0] - segments[i].at(-1)) < max_distance * (segments[i].length + segments[j].length) && overlap_value == max_overlap){
|
|
54835
|
+
let merge_level = normal_merge(levels[i], error[i], levels[i + 1], error[i + 1]);
|
|
54836
|
+
|
|
54837
|
+
levels[i] = merge_level.nl;
|
|
54838
|
+
error[i] = merge_level.ne;
|
|
54839
|
+
let nlh = likelihoods[i].map((l_value, l_idx) => { return l_value * likelihoods[i+1][l_idx]});
|
|
54840
|
+
let nlh_sum = nlh.reduce((a, c_value) => {return a + c_value});
|
|
54841
|
+
likelihoods[i] = nlh.map(function(item) { return item/nlh_sum } );
|
|
54842
|
+
|
|
54843
|
+
|
|
54844
|
+
segments[i].push(...segments[i+1]);
|
|
54845
|
+
segments[i] = segments[i].sort((a,b) => a-b);
|
|
54846
|
+
|
|
54847
|
+
levels.splice(j, 1);
|
|
54848
|
+
error.splice(j, 1);
|
|
54849
|
+
segments.splice(j, 1);
|
|
54850
|
+
likelihoods.splice(j, 1);
|
|
54851
|
+
|
|
54852
|
+
if(j >= segments.length){
|
|
54853
|
+
i += 1;
|
|
54854
|
+
j = i + 1;
|
|
54855
|
+
}
|
|
54856
|
+
|
|
54857
|
+
}else {
|
|
54858
|
+
j += 1;
|
|
54859
|
+
if(j >= segments.length){
|
|
54860
|
+
i += 1;
|
|
54861
|
+
j = i + 1;
|
|
54862
|
+
}
|
|
54863
|
+
}
|
|
54864
|
+
}
|
|
54865
|
+
if(ons == segments.length){
|
|
54866
|
+
break
|
|
54867
|
+
}
|
|
54868
|
+
ons = segments.length;
|
|
54869
|
+
}
|
|
54870
|
+
// console.log('final segments', segments)
|
|
54871
|
+
|
|
54872
|
+
segments.forEach((seg_value, seg_idx) => {
|
|
54873
|
+
let baf_info = likelihood_baf_pval(likelihoods[seg_idx]);
|
|
54874
|
+
if(seg_value.length > 1){
|
|
54875
|
+
|
|
54876
|
+
seg_value.forEach((bin, bin_idx) =>{
|
|
54877
|
+
gstat_rd_all.push(wig[bin]);
|
|
54878
|
+
if(baf_info.mean <= baf_threshold){
|
|
54879
|
+
gstat_rd0.push(wig[bin]);
|
|
54880
|
+
}
|
|
54881
|
+
wig[bin].segment_score = levels[seg_idx];
|
|
54882
|
+
});
|
|
54883
|
+
gstat_rd.push(levels[seg_idx]);
|
|
54884
|
+
gstat_error.push(error[seg_idx]);
|
|
54885
|
+
gstat_lh.push(likelihoods[seg_idx]);
|
|
54886
|
+
|
|
54887
|
+
}
|
|
54888
|
+
|
|
54889
|
+
});
|
|
54890
|
+
|
|
54891
|
+
continue
|
|
54892
|
+
}
|
|
54893
|
+
|
|
54894
|
+
// Third stage for call
|
|
54895
|
+
|
|
54896
|
+
// let data = gstat_rd0.lengthn == 0 ? gstat_rd_all: gstat_rd0 ;
|
|
54897
|
+
|
|
54898
|
+
let points = parseInt(1000 * (1 - min_cell_fraction));
|
|
54899
|
+
if(points == 0){
|
|
54900
|
+
points = 1;
|
|
54901
|
+
}
|
|
54902
|
+
let x = g_utils.linspace(min_cell_fraction, 1, points);
|
|
54903
|
+
let master_lh = {};
|
|
54904
|
+
let germline_lh = {};
|
|
54905
|
+
for(let cn=10; cn > -1; cn--){
|
|
54906
|
+
for(let h1=0; h1 < (cn/2+1); h1++){
|
|
54907
|
+
let h2 = cn - h1;
|
|
54908
|
+
let mrd = x.map((v, idx) => {return 1-v +v*cn/2});
|
|
54909
|
+
let g_mrd = cn / 2;
|
|
54910
|
+
let g_mbaf;
|
|
54911
|
+
let mbaf;
|
|
54912
|
+
if(cn > 0){
|
|
54913
|
+
g_mbaf = 0.5 - (h1 / (h1 + h2));
|
|
54914
|
+
mbaf = x.map((v, idx) => {return 0.5 - (1 - v + v * h1) / (2 - 2 * v + (h1 + h2) * v)});
|
|
54915
|
+
|
|
54916
|
+
}else {
|
|
54917
|
+
g_mbaf = 0;
|
|
54918
|
+
mbaf = x.map((v, idx) => {return 0*v});
|
|
54919
|
+
}
|
|
54920
|
+
|
|
54921
|
+
for( let ei=0; ei < gstat_rd.length; ei++){
|
|
54922
|
+
|
|
54923
|
+
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);
|
|
54924
|
+
if(ei in germline_lh){
|
|
54925
|
+
germline_lh[ei].push([cn, h1, h2, g_lh, 1.0]);
|
|
54926
|
+
}else {
|
|
54927
|
+
germline_lh[ei] = [cn, h1, h2, g_lh, 1.0];
|
|
54928
|
+
}
|
|
54929
|
+
let slh = 0;
|
|
54930
|
+
let max_lh = 0;
|
|
54931
|
+
let max_x = 0;
|
|
54932
|
+
mrd.forEach((mi, idx) => {
|
|
54933
|
+
if(!isNaN(mbaf[idx])){
|
|
54934
|
+
let tmpl = normal(mi * this.globalMean, 1, gstat_rd[ei], gstat_error[ei]) * likelihood_of_baf(gstat_lh[ei], 0.5 + mbaf[idx]);
|
|
54935
|
+
slh += tmpl;
|
|
54936
|
+
if(tmpl > max_lh){
|
|
54937
|
+
max_lh = tmpl;
|
|
54938
|
+
max_x = x[idx];
|
|
54939
|
+
}
|
|
54940
|
+
}
|
|
54941
|
+
});
|
|
54942
|
+
if(ei in master_lh){
|
|
54943
|
+
master_lh[ei].push([cn, h1, h2, slh / x.length, max_x]);
|
|
54944
|
+
}else {
|
|
54945
|
+
master_lh[ei] = [cn, h1, h2, slh / x.length, max_x];
|
|
54946
|
+
}
|
|
54947
|
+
}
|
|
54948
|
+
|
|
54949
|
+
for( let ei=0; ei < gstat_rd.length; ei++){
|
|
54950
|
+
if(event_type == "germline"){
|
|
54951
|
+
master_lh[ei].sort((a, b) => a[3] - b[3]);
|
|
54952
|
+
}
|
|
54953
|
+
else {
|
|
54954
|
+
master_lh[ei].sort((a, b) => a[3] - b[3]);
|
|
54955
|
+
if(event_type == "both"){
|
|
54956
|
+
|
|
54957
|
+
germline_lh[ei].sort((a, b) => a[3] - b[3]);
|
|
54958
|
+
if(germline_lh[ei][0][3] > master_lh[ei][0][3]){
|
|
54959
|
+
//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]))
|
|
54960
|
+
let tmp_list = master_lh[ei].filter((x) => (x[0] != germline_lh[ei][0][0]) && (x[1] <= germline_lh[ei][0][1]));
|
|
54961
|
+
// console.log('tmp_list', tmp_list)
|
|
54962
|
+
// master_lh[ei] = [germline_lh[ei][0]] + tmp_list
|
|
54963
|
+
master_lh[ei] = [germline_lh[ei][0]].push(...tmp_list);
|
|
54964
|
+
}
|
|
54965
|
+
}
|
|
54966
|
+
}
|
|
54967
|
+
}
|
|
54968
|
+
for( let ei=0; ei < gstat_rd.length; ei++){
|
|
54969
|
+
if(master_lh[ei][0][0] > 2);
|
|
54970
|
+
if(master_lh[ei][0][0] < 2);
|
|
54971
|
+
gstat_rd[ei] / this.globalMean;
|
|
54972
|
+
t_dist.t_test_1_sample(this.globalMean, gstat_rd[ei], gstat_error[ei], gstat_n[ei]);
|
|
54973
|
+
// console.log(etype)
|
|
54974
|
+
|
|
54975
|
+
}
|
|
54976
|
+
|
|
54977
|
+
|
|
54978
|
+
// break
|
|
54979
|
+
}
|
|
54980
|
+
|
|
54981
|
+
}
|
|
54982
|
+
|
|
54983
|
+
var rawbinScore = this.formatDataStructure(this.wigFeatures, 'binScore', this.globalMean);
|
|
54984
|
+
var callScore = this.formatDataStructure(this.wigFeatures, 'segment_score', this.globalMean);
|
|
54985
|
+
|
|
54986
|
+
return {binScore: rawbinScore, segment_score: callScore}
|
|
54987
|
+
|
|
54571
54988
|
}
|
|
54572
54989
|
|
|
54573
|
-
|
|
54574
|
-
const
|
|
54575
|
-
const
|
|
54990
|
+
formatDataStructure(wigFeatures, feature_column, scaling_factor = 1) {
|
|
54991
|
+
const results = [];
|
|
54992
|
+
for (const [chr, wig] of Object.entries(wigFeatures)) {
|
|
54576
54993
|
|
|
54577
|
-
|
|
54578
|
-
|
|
54579
|
-
if (
|
|
54580
|
-
|
|
54994
|
+
wig.forEach(sample => {
|
|
54995
|
+
var new_sample = { ...sample };
|
|
54996
|
+
if (scaling_factor != 1) {
|
|
54997
|
+
new_sample.value = sample[feature_column] / scaling_factor * 2;
|
|
54581
54998
|
}
|
|
54582
|
-
|
|
54583
|
-
|
|
54584
|
-
|
|
54999
|
+
results.push(new_sample);
|
|
55000
|
+
});
|
|
55001
|
+
}
|
|
55002
|
+
|
|
55003
|
+
return results
|
|
55004
|
+
}
|
|
55005
|
+
|
|
55006
|
+
formatDataStructure_BAF(feature_column, scaling_factor = 2) {
|
|
55007
|
+
const baf1 = [];
|
|
55008
|
+
const baf2 = [];
|
|
55009
|
+
for (const [chr, wig] of Object.entries(this.wigFeatures)) {
|
|
55010
|
+
|
|
55011
|
+
wig.forEach(sample => {
|
|
55012
|
+
|
|
55013
|
+
var baf1_value = { ...sample };
|
|
55014
|
+
var baf2_value = { ...sample };
|
|
55015
|
+
|
|
55016
|
+
let value = sample[feature_column];
|
|
55017
|
+
if (value != 0.5){
|
|
55018
|
+
baf2_value.value = -2 * (1 - value);
|
|
55019
|
+
baf2.push(baf2_value);
|
|
54585
55020
|
}
|
|
55021
|
+
baf1_value.value = -2 * value;
|
|
55022
|
+
baf1.push(baf1_value);
|
|
55023
|
+
|
|
54586
55024
|
});
|
|
54587
|
-
}
|
|
54588
|
-
|
|
54589
|
-
|
|
54590
|
-
return
|
|
55025
|
+
}
|
|
55026
|
+
|
|
55027
|
+
|
|
55028
|
+
return [baf1, baf2]
|
|
54591
55029
|
}
|
|
55030
|
+
}
|
|
55031
|
+
|
|
55032
|
+
function arrayMax(arr) {
|
|
55033
|
+
return arr.reduce(function (p, v) {
|
|
55034
|
+
return ( p > v ? p : v );
|
|
55035
|
+
});
|
|
55036
|
+
}
|
|
55037
|
+
|
|
55038
|
+
/**
|
|
55039
|
+
* Normal distribution.
|
|
55040
|
+
*
|
|
55041
|
+
* @param {float} x - Variable.
|
|
55042
|
+
* @param {float} a - area
|
|
55043
|
+
* @param {float} x0 - Mean value
|
|
55044
|
+
* @param {float} sigma - Sigma
|
|
55045
|
+
* @returns {float} - Value of distribution in x.
|
|
55046
|
+
*/
|
|
55047
|
+
function normal(x, a, x0, sigma){
|
|
55048
|
+
|
|
55049
|
+
return a * Math.exp(-1* (x - x0) ** 2 / (2 * sigma ** 2)) / Math.sqrt(2 * Math.PI) / sigma
|
|
54592
55050
|
|
|
54593
55051
|
}
|
|
54594
55052
|
|
|
55053
|
+
/**
|
|
55054
|
+
* Calculates two normal distributions overlap area.
|
|
55055
|
+
*
|
|
55056
|
+
* @param {float} m1 - Mean value of the first distribution
|
|
55057
|
+
* @param {float} s1 - Sigma of the first distribution
|
|
55058
|
+
* @param {float} m2 - Mean value for second distribution
|
|
55059
|
+
* @param {float} s2 - Sigma of the second distribution
|
|
55060
|
+
*
|
|
55061
|
+
* @returns {float} area - Area of overlap
|
|
55062
|
+
*/
|
|
55063
|
+
function normal_overlap_approx(m1, s1, m2, s2){
|
|
55064
|
+
|
|
55065
|
+
return Math.exp(-1* (m1-m2)**2/ (s1**2+s2**2))
|
|
55066
|
+
}
|
|
55067
|
+
|
|
55068
|
+
|
|
55069
|
+
/**
|
|
55070
|
+
* Returns overlap area of two likelihood functions.
|
|
55071
|
+
*
|
|
55072
|
+
* @param {*} lk1 - First likelihood function.
|
|
55073
|
+
* @param {*} lk2 - Second likelihood function.
|
|
55074
|
+
*
|
|
55075
|
+
* @returns {float} - Overlap area.
|
|
55076
|
+
*/
|
|
55077
|
+
function likelihood_overlap(likelihood_1, likelihood_2){
|
|
55078
|
+
let sum;
|
|
55079
|
+
try{
|
|
55080
|
+
sum = likelihood_1.reduce((accumulator, currentValue, currentIndex) => {return accumulator + Math.min(currentValue, likelihood_2[currentIndex])});
|
|
55081
|
+
}catch{
|
|
55082
|
+
console.log("Failed to find likelihood overlap: ", likelihood_1, likelihood_2);
|
|
55083
|
+
return 0
|
|
55084
|
+
}
|
|
55085
|
+
|
|
55086
|
+
return sum
|
|
55087
|
+
}
|
|
55088
|
+
|
|
55089
|
+
/**
|
|
55090
|
+
* Calculates normal distribution that is product of two given normal distributions.
|
|
55091
|
+
*
|
|
55092
|
+
* @param {float} m1 - Mean value of the first distribution
|
|
55093
|
+
* @param {float} s1 - Sigma of the first distribution
|
|
55094
|
+
* @param {float} m2 - Mean value for second distribution
|
|
55095
|
+
* @param {float} s2 - Sigma of the second distribution
|
|
55096
|
+
* @returns {Object} An object representing the first distribution
|
|
55097
|
+
* @property {float} nl - Mean value of the first distribution
|
|
55098
|
+
* @property {float} ne - Sigma of the first distribution
|
|
55099
|
+
*/
|
|
55100
|
+
function normal_merge(m1, s1, m2, s2){
|
|
55101
|
+
|
|
55102
|
+
if((s1 == 0) && (s2 == 0)){
|
|
55103
|
+
return {nl: 0.5 * (m1 + m2), ne: 0}
|
|
55104
|
+
}
|
|
55105
|
+
else {
|
|
55106
|
+
return {nl: (m1 * s2 * s2 + m2 * s1 * s1) / (s1 * s1 + s2 * s2), ne: Math.sqrt(s1 * s1 * s2 * s2 / (s1 * s1 + s2 * s2))}
|
|
55107
|
+
}
|
|
55108
|
+
}
|
|
55109
|
+
|
|
55110
|
+
/**
|
|
55111
|
+
* Calculates likelihood for given baf
|
|
55112
|
+
* @param {*} likelihood
|
|
55113
|
+
* @param {*} baf
|
|
55114
|
+
* @returns {float} likelihood value
|
|
55115
|
+
*/
|
|
55116
|
+
function likelihood_of_baf(likelihood, baf){
|
|
55117
|
+
|
|
55118
|
+
let bin = parseInt(baf * (likelihood.length - 1));
|
|
55119
|
+
let fr = baf * (likelihood.length - 1) - bin;
|
|
55120
|
+
if(bin < likelihood.length - 1){
|
|
55121
|
+
return likelihood[bin] * (1 - fr) + likelihood[bin + 1] * fr
|
|
55122
|
+
}
|
|
55123
|
+
else {
|
|
55124
|
+
return likelihood[bin]
|
|
55125
|
+
}
|
|
55126
|
+
}
|
|
55127
|
+
|
|
55128
|
+
/**
|
|
55129
|
+
*
|
|
55130
|
+
* Calculates baf level and p-value for given likelihood function.
|
|
55131
|
+
*
|
|
55132
|
+
* @param {*} likelihood
|
|
55133
|
+
* @returns {Object} An object representing BAF
|
|
55134
|
+
* @property {float} mean BAF level (difference from 1/2)
|
|
55135
|
+
* @property {float} p p-value for event different than 1/2
|
|
55136
|
+
*/
|
|
55137
|
+
function likelihood_baf_pval(likelihood) {
|
|
55138
|
+
const res = likelihood.length;
|
|
55139
|
+
const max_lh = Math.max(...likelihood);
|
|
55140
|
+
let ix = likelihood.indexOf(max_lh);
|
|
55141
|
+
if (ix > Math.floor(res / 2)) {
|
|
55142
|
+
ix = res - 1 - ix;
|
|
55143
|
+
}
|
|
55144
|
+
const b = (res / 2 - ix) / (res + 1);
|
|
55145
|
+
|
|
55146
|
+
const ix1 = Math.floor((res / 2 + ix) / 2);
|
|
55147
|
+
const ix2 = res - 1 - ix1;
|
|
55148
|
+
let p = likelihood.slice(ix1, ix2 + 1).reduce((acc, val) => acc + val, 0) / likelihood.reduce((acc, val) => acc + val, 0);
|
|
55149
|
+
if (ix === Math.floor(res / 2)) {
|
|
55150
|
+
p = 1.0;
|
|
55151
|
+
}
|
|
55152
|
+
return {mean:b, p:p};
|
|
55153
|
+
}
|
|
55154
|
+
|
|
55155
|
+
var combined_caller = {CombinedCaller};
|
|
55156
|
+
|
|
54595
55157
|
function erf(x) {
|
|
54596
55158
|
var m = 1.0, s = 1.0, sum = x * 1.0;
|
|
54597
55159
|
for (var i = 1; i < 50; i++) {
|
|
@@ -55239,6 +55801,10 @@ class Partition {
|
|
|
55239
55801
|
}
|
|
55240
55802
|
}
|
|
55241
55803
|
|
|
55804
|
+
|
|
55805
|
+
|
|
55806
|
+
var read_depth_caller = { Partition };
|
|
55807
|
+
|
|
55242
55808
|
class CNVpytorVCF {
|
|
55243
55809
|
constructor(allVariants, binSize) {
|
|
55244
55810
|
this.allVariants = allVariants;
|
|
@@ -55366,13 +55932,11 @@ class CNVpytorVCF {
|
|
|
55366
55932
|
readDepthMeanshift(wigFeatures) {
|
|
55367
55933
|
|
|
55368
55934
|
// Get global mean and standrad deviation
|
|
55369
|
-
var fit_info = new GetFit(wigFeatures);
|
|
55935
|
+
var fit_info = new g_utils.GetFit(wigFeatures);
|
|
55370
55936
|
var [globamMean, globalStd] = fit_info.fit_data();
|
|
55371
|
-
// console.log('Fitter', globamMean, globalStd)
|
|
55372
|
-
|
|
55373
55937
|
|
|
55374
55938
|
// Apply partition method
|
|
55375
|
-
var partition = new Partition(wigFeatures, globamMean, globalStd);
|
|
55939
|
+
var partition = new read_depth_caller.Partition(wigFeatures, globamMean, globalStd);
|
|
55376
55940
|
var partition_array = partition.meanShiftCaller();
|
|
55377
55941
|
var caller_array = partition.cnv_calling();
|
|
55378
55942
|
|
|
@@ -55403,86 +55967,10 @@ class CNVpytorVCF {
|
|
|
55403
55967
|
results.push(new_sample);
|
|
55404
55968
|
});
|
|
55405
55969
|
}
|
|
55406
|
-
// console.log(feature_column, results)
|
|
55407
55970
|
|
|
55408
55971
|
return results
|
|
55409
55972
|
}
|
|
55410
55973
|
|
|
55411
|
-
// function for baf likelihood calculations
|
|
55412
|
-
async computeBAF() {
|
|
55413
|
-
const chromosomes = Object.keys(this.allVariants);
|
|
55414
|
-
const wigFeatures = {};
|
|
55415
|
-
const results = [];
|
|
55416
|
-
|
|
55417
|
-
for (let chr of chromosomes) {
|
|
55418
|
-
const variants = this.allVariants[chr];
|
|
55419
|
-
if (variants.length === 0) continue
|
|
55420
|
-
var featureBin;
|
|
55421
|
-
for (let snp of variants) {
|
|
55422
|
-
featureBin = Math.max(Math.floor(snp.start / this.binSize), 0);
|
|
55423
|
-
|
|
55424
|
-
if (!wigFeatures[chr]) {
|
|
55425
|
-
wigFeatures[chr] = [];
|
|
55426
|
-
}
|
|
55427
|
-
if (!wigFeatures[chr][featureBin]) {
|
|
55428
|
-
if (featureBin > 0) {
|
|
55429
|
-
// calculating the BAF likelihood for previous bin
|
|
55430
|
-
let previous_featureBin = featureBin - 1;
|
|
55431
|
-
if (wigFeatures[chr][previous_featureBin]) {
|
|
55432
|
-
|
|
55433
|
-
const updated_bin = this.get_max_min_score(wigFeatures[chr][previous_featureBin]);
|
|
55434
|
-
wigFeatures[chr][previous_featureBin] = updated_bin;
|
|
55435
|
-
results.push(wigFeatures[chr][previous_featureBin]);
|
|
55436
|
-
}
|
|
55437
|
-
}
|
|
55438
|
-
wigFeatures[chr][featureBin] = {
|
|
55439
|
-
chr,
|
|
55440
|
-
start: featureBin * this.binSize,
|
|
55441
|
-
end: (featureBin + 1) * this.binSize,
|
|
55442
|
-
value: 0,
|
|
55443
|
-
count: 0,
|
|
55444
|
-
likelihood_score: [],
|
|
55445
|
-
min_score: 0,
|
|
55446
|
-
};
|
|
55447
|
-
}
|
|
55448
|
-
const calls = snp.calls[9];
|
|
55449
|
-
let genotype = calls.genotype;
|
|
55450
|
-
let ad_score = calls.info["AD"].split(',');
|
|
55451
|
-
let ad_a = ad_score[0], ad_b = ad_score[1];
|
|
55452
|
-
|
|
55453
|
-
if ((genotype[0] == 0 && genotype[1] == 1) || (genotype[0] == 1 && genotype[1] == 0)) {
|
|
55454
|
-
//apply the beta function
|
|
55455
|
-
if (wigFeatures[chr][featureBin].likelihood_score.length == 0) {
|
|
55456
|
-
wigFeatures[chr][featureBin].likelihood_score = linspace(0, 1, 200).map((value, index) => {
|
|
55457
|
-
return beta(ad_a, ad_b, value);
|
|
55458
|
-
});
|
|
55459
|
-
} else {
|
|
55460
|
-
var sum = 0;
|
|
55461
|
-
|
|
55462
|
-
wigFeatures[chr][featureBin].likelihood_score = linspace(0, 1, 200).map((value, index) => {
|
|
55463
|
-
var likelihood_value = wigFeatures[chr][featureBin].likelihood_score[index] * beta(ad_a, ad_b, value);
|
|
55464
|
-
sum = sum + likelihood_value;
|
|
55465
|
-
return likelihood_value;
|
|
55466
|
-
});
|
|
55467
|
-
|
|
55468
|
-
wigFeatures[chr][featureBin].likelihood_score = linspace(0, 1, 200).map((value, index) => {
|
|
55469
|
-
return wigFeatures[chr][featureBin].likelihood_score[index] / sum;
|
|
55470
|
-
});
|
|
55471
|
-
}
|
|
55472
|
-
wigFeatures[chr][featureBin].count++;
|
|
55473
|
-
}
|
|
55474
|
-
}
|
|
55475
|
-
|
|
55476
|
-
// last feature bin
|
|
55477
|
-
const updated_bin = this.get_max_min_score(wigFeatures[chr][featureBin]);
|
|
55478
|
-
wigFeatures[chr][featureBin] = updated_bin;
|
|
55479
|
-
results.push(wigFeatures[chr][featureBin]);
|
|
55480
|
-
}
|
|
55481
|
-
|
|
55482
|
-
const baf2_result = this.format_BAF_likelihood(wigFeatures);
|
|
55483
|
-
return [results, baf2_result]
|
|
55484
|
-
|
|
55485
|
-
}
|
|
55486
55974
|
async computeBAF_v2() {
|
|
55487
55975
|
|
|
55488
55976
|
const chromosomes = Object.keys(this.allVariants);
|
|
@@ -55537,19 +56025,19 @@ class CNVpytorVCF {
|
|
|
55537
56025
|
if ((genotype[0] == 0 && genotype[1] == 1) || (genotype[0] == 1 && genotype[1] == 0)) {
|
|
55538
56026
|
//apply the beta function
|
|
55539
56027
|
if (wigFeatures[chr][featureBin].likelihood_score.length == 0) {
|
|
55540
|
-
wigFeatures[chr][featureBin].likelihood_score = linspace(0, 1, 100).map((value, index) => {
|
|
56028
|
+
wigFeatures[chr][featureBin].likelihood_score = g_utils.linspace(0, 1, 100).map((value, index) => {
|
|
55541
56029
|
return beta(ad_a, ad_b, value);
|
|
55542
56030
|
});
|
|
55543
56031
|
} else {
|
|
55544
56032
|
var sum = 0;
|
|
55545
56033
|
|
|
55546
|
-
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) => {
|
|
55547
56035
|
var likelihood_value = wigFeatures[chr][featureBin].likelihood_score[index] * beta(ad_a, ad_b, value);
|
|
55548
56036
|
sum = sum + likelihood_value;
|
|
55549
56037
|
return likelihood_value;
|
|
55550
56038
|
});
|
|
55551
56039
|
|
|
55552
|
-
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) => {
|
|
55553
56041
|
return wigFeatures[chr][featureBin].likelihood_score[index] / sum;
|
|
55554
56042
|
});
|
|
55555
56043
|
}
|
|
@@ -55595,7 +56083,6 @@ class CNVpytorVCF {
|
|
|
55595
56083
|
if (sample.likelihood_score.length > 0) {
|
|
55596
56084
|
const max = Math.max(...sample.likelihood_score);
|
|
55597
56085
|
const res = sample.likelihood_score.indexOf(max);
|
|
55598
|
-
sample.likelihood_score = [];
|
|
55599
56086
|
sample.value = Math.max(res / 100, 1 - res / 100);
|
|
55600
56087
|
sample.min_score = Math.min(res / 100, 1 - res / 100);
|
|
55601
56088
|
|
|
@@ -55611,7 +56098,7 @@ class CNVpytorVCF {
|
|
|
55611
56098
|
|
|
55612
56099
|
//console.log('getAllbins', bins["value"])
|
|
55613
56100
|
|
|
55614
|
-
const fitter = new GetFit(bins);
|
|
56101
|
+
const fitter = new g_utils.GetFit(bins);
|
|
55615
56102
|
|
|
55616
56103
|
fitter.fit_data();
|
|
55617
56104
|
// dconsole.log('rd list', distParams)
|
|
@@ -55619,7 +56106,7 @@ class CNVpytorVCF {
|
|
|
55619
56106
|
return bins
|
|
55620
56107
|
}
|
|
55621
56108
|
|
|
55622
|
-
async read_rd_baf(){
|
|
56109
|
+
async read_rd_baf(caller='ReadDepth'){
|
|
55623
56110
|
|
|
55624
56111
|
const chromosomes = Object.keys(this.allVariants);
|
|
55625
56112
|
var wigFeatures = {};
|
|
@@ -55665,13 +56152,22 @@ class CNVpytorVCF {
|
|
|
55665
56152
|
}
|
|
55666
56153
|
|
|
55667
56154
|
}
|
|
55668
|
-
|
|
56155
|
+
|
|
55669
56156
|
var avgbin = this.adjust_bin_size(wigFeatures);
|
|
56157
|
+
var finalFeatureSet;
|
|
56158
|
+
if(caller == 'ReadDepth'){
|
|
56159
|
+
finalFeatureSet = this.readDepthMeanshift(avgbin);
|
|
56160
|
+
var baf = this.formatDataStructure_BAF(avgbin, 'max_likelihood');
|
|
56161
|
+
}else if(caller=='2D'){
|
|
56162
|
+
|
|
56163
|
+
let caller_obj = new combined_caller.CombinedCaller(avgbin, this.binSize);
|
|
56164
|
+
let processed_bins = await caller_obj.call_2d();
|
|
56165
|
+
|
|
56166
|
+
finalFeatureSet = [processed_bins.binScore, [], processed_bins.segment_score];
|
|
56167
|
+
|
|
56168
|
+
var baf = caller_obj.formatDataStructure_BAF('max_likelihood');
|
|
56169
|
+
}
|
|
55670
56170
|
|
|
55671
|
-
let finalFeatureSet = this.readDepthMeanshift(avgbin);
|
|
55672
|
-
|
|
55673
|
-
//var rawbinScore = this.formatDataStructure(avgbin, 'binScore', globamMean)
|
|
55674
|
-
var baf = this.formatDataStructure_BAF(avgbin, 'max_likelihood');
|
|
55675
56171
|
|
|
55676
56172
|
return [finalFeatureSet, baf]
|
|
55677
56173
|
}
|
|
@@ -55734,19 +56230,19 @@ class CNVpytorVCF {
|
|
|
55734
56230
|
|
|
55735
56231
|
wigFeatures[chr][j].hets.forEach((hets, hets_idx) => {
|
|
55736
56232
|
if(avgbin[chr][k].likelihood_score.length == 0){
|
|
55737
|
-
avgbin[chr][k].likelihood_score = linspace(0, 1, 100).map((value, index) => {
|
|
56233
|
+
avgbin[chr][k].likelihood_score = g_utils.linspace(0, 1, 100).map((value, index) => {
|
|
55738
56234
|
return beta(hets.ref, hets.alt, value);
|
|
55739
56235
|
});
|
|
55740
56236
|
}
|
|
55741
56237
|
else {
|
|
55742
56238
|
var likelihood_sum = 0;
|
|
55743
|
-
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) => {
|
|
55744
56240
|
var likelihood_value = avgbin[chr][k].likelihood_score[index] * beta(hets.ref, hets.alt, value);
|
|
55745
56241
|
likelihood_sum += likelihood_value;
|
|
55746
56242
|
return likelihood_value;
|
|
55747
56243
|
});
|
|
55748
56244
|
|
|
55749
|
-
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) => {
|
|
55750
56246
|
return avgbin[chr][k].likelihood_score[index] / likelihood_sum;
|
|
55751
56247
|
});
|
|
55752
56248
|
|
|
@@ -55771,19 +56267,6 @@ function beta(a, b, p, phased = true) {
|
|
|
55771
56267
|
return p ** a * (1 - p) ** b + p ** b * (1 - p) ** a;
|
|
55772
56268
|
}
|
|
55773
56269
|
|
|
55774
|
-
function linspace(a, b, n) {
|
|
55775
|
-
if (typeof n === "undefined") n = Math.max(Math.round(b - a) + 1, 1);
|
|
55776
|
-
if (n < 2) {
|
|
55777
|
-
return n === 1 ? [a] : [];
|
|
55778
|
-
}
|
|
55779
|
-
var ret = Array(n);
|
|
55780
|
-
n--;
|
|
55781
|
-
for (let i = n; i >= 0; i--) {
|
|
55782
|
-
ret[i] = (i * b + (n - i) * a) / n;
|
|
55783
|
-
}
|
|
55784
|
-
return ret;
|
|
55785
|
-
}
|
|
55786
|
-
|
|
55787
56270
|
/*
|
|
55788
56271
|
* The MIT License (MIT)
|
|
55789
56272
|
*
|
|
@@ -55894,29 +56377,43 @@ class CNVPytorTrack extends TrackBase {
|
|
|
55894
56377
|
}, Object.create(null));
|
|
55895
56378
|
|
|
55896
56379
|
const cnvpytor_obj = new CNVpytorVCF(allVariants, this.bin_size);
|
|
55897
|
-
//const wigFeatures = await cnvpytor_obj.computeReadDepth()
|
|
55898
|
-
//const bafFeatures = await cnvpytor_obj.computeBAF_v2()
|
|
55899
|
-
const dataWigs = await cnvpytor_obj.read_rd_baf();
|
|
55900
|
-
const wigFeatures = dataWigs[0];
|
|
55901
|
-
const bafFeatures = dataWigs[1];
|
|
55902
56380
|
|
|
56381
|
+
let wigFeatures;
|
|
56382
|
+
let bafFeatures;
|
|
55903
56383
|
this.wigFeatures_obj = {};
|
|
55904
|
-
this.wigFeatures_obj[this.bin_size] = {
|
|
55905
|
-
|
|
55906
|
-
|
|
55907
|
-
|
|
55908
|
-
|
|
55909
|
-
|
|
55910
|
-
|
|
55911
|
-
|
|
55912
|
-
|
|
55913
|
-
|
|
56384
|
+
this.wigFeatures_obj[this.bin_size] = {};
|
|
56385
|
+
|
|
56386
|
+
let dataWigs;
|
|
56387
|
+
if(this.config.cnv_caller == '2D'){
|
|
56388
|
+
|
|
56389
|
+
dataWigs = await cnvpytor_obj.read_rd_baf('2D');
|
|
56390
|
+
|
|
56391
|
+
wigFeatures = dataWigs[0];
|
|
56392
|
+
bafFeatures = dataWigs[1];
|
|
56393
|
+
this.wigFeatures_obj[this.bin_size]['2D'] = wigFeatures[2];
|
|
56394
|
+
|
|
56395
|
+
this.available_callers = ['2D'];
|
|
56396
|
+
}else {
|
|
56397
|
+
dataWigs = await cnvpytor_obj.read_rd_baf();
|
|
56398
|
+
wigFeatures = dataWigs[0];
|
|
56399
|
+
bafFeatures = dataWigs[1];
|
|
56400
|
+
this.wigFeatures_obj[this.bin_size]['ReadDepth'] = wigFeatures[2];
|
|
56401
|
+
this.available_callers = ['ReadDepth'];
|
|
56402
|
+
}
|
|
56403
|
+
|
|
56404
|
+
this.wigFeatures_obj[this.bin_size]['RD_Raw'] = wigFeatures[0];
|
|
56405
|
+
this.wigFeatures_obj[this.bin_size]['RD_Raw_gc_coor'] = wigFeatures[1];
|
|
56406
|
+
this.wigFeatures_obj[this.bin_size]['BAF1'] = bafFeatures[0];
|
|
56407
|
+
this.wigFeatures_obj[this.bin_size]['BAF2'] = bafFeatures[1];
|
|
56408
|
+
|
|
56409
|
+
this.available_bins = [this.bin_size];
|
|
56410
|
+
|
|
55914
56411
|
this.set_available_callers();
|
|
55915
56412
|
|
|
55916
56413
|
} else {
|
|
55917
56414
|
this.cnvpytor_obj = new HDF5Reader(this.config.url, this.bin_size);
|
|
55918
56415
|
this.wigFeatures_obj = await this.cnvpytor_obj.get_rd_signal(this.bin_size);
|
|
55919
|
-
this.
|
|
56416
|
+
this.available_bins = this.cnvpytor_obj.available_bins;
|
|
55920
56417
|
this.available_callers = this.cnvpytor_obj.callers;
|
|
55921
56418
|
this.set_available_callers();
|
|
55922
56419
|
}
|
|
@@ -56029,7 +56526,7 @@ class CNVPytorTrack extends TrackBase {
|
|
|
56029
56526
|
|
|
56030
56527
|
items.push('<hr/>');
|
|
56031
56528
|
items.push("Bin Sizes");
|
|
56032
|
-
for (let rd_bin of this.
|
|
56529
|
+
for (let rd_bin of this.available_bins) {
|
|
56033
56530
|
const checkBox = createCheckbox(rd_bin, rd_bin === this.bin_size);
|
|
56034
56531
|
items.push({
|
|
56035
56532
|
object: $$1(checkBox),
|