X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=bam2bcf.c;h=6ac5dce182a2353ada163dd65bdb5ca530d59127;hb=9f118264ea012adc21a46d7c03eaad4f9ce7d4d4;hp=bd5503d7e55cef2479c1a8d12d3dc0855eab06f2;hpb=27eec65490fb3461f0af054868d9a0949e1843ed;p=samtools.git diff --git a/bam2bcf.c b/bam2bcf.c index bd5503d..6ac5dce 100644 --- a/bam2bcf.c +++ b/bam2bcf.c @@ -39,6 +39,7 @@ void bcf_call_destroy(bcf_callaux_t *bca) * negative if we are looking at an indel. */ int bcf_call_glfgen(int _n, const bam_pileup1_t *pl, int ref_base, bcf_callaux_t *bca, bcf_callret1_t *r) { + static int *var_pos = NULL, nvar_pos = 0; int i, n, ref4, is_indel, ori_depth = 0; memset(r, 0, sizeof(bcf_callret1_t)); if (ref_base >= 0) { @@ -54,7 +55,7 @@ int bcf_call_glfgen(int _n, const bam_pileup1_t *pl, int ref_base, bcf_callaux_t } // fill the bases array memset(r, 0, sizeof(bcf_callret1_t)); - for (i = n = 0; i < _n; ++i) { + for (i = n = r->n_supp = 0; i < _n; ++i) { const bam_pileup1_t *p = pl + i; int q, b, mapQ, baseQ, is_diff, min_dist, seqQ; // set base @@ -77,6 +78,7 @@ int bcf_call_glfgen(int _n, const bam_pileup1_t *pl, int ref_base, bcf_callaux_t b = p->aux>>16&0x3f; is_diff = (b != 0); } + if (is_diff) ++r->n_supp; bca->bases[n++] = q<<5 | (int)bam1_strand(p->b)<<4 | b; // collect annotations if (b < 4) r->qsum[b] += q; @@ -94,9 +96,92 @@ int bcf_call_glfgen(int _n, const bam_pileup1_t *pl, int ref_base, bcf_callaux_t r->depth = n; r->ori_depth = ori_depth; // glfgen errmod_cal(bca->e, n, 5, bca->bases, r->p); + + // Calculate the Variant Distance Bias (make it optional?) + if ( nvar_pos < _n ) { + nvar_pos = _n; + var_pos = realloc(var_pos,sizeof(int)*nvar_pos); + } + int alt_dp=0, read_len=0; + for (i=0; i<_n; i++) { + const bam_pileup1_t *p = pl + i; + if ( bam1_seqi(bam1_seq(p->b),p->qpos) == ref_base ) + continue; + + var_pos[alt_dp] = p->qpos; + if ( (bam1_cigar(p->b)[0]&BAM_CIGAR_MASK)==4 ) + var_pos[alt_dp] -= bam1_cigar(p->b)[0]>>BAM_CIGAR_SHIFT; + + alt_dp++; + read_len += p->b->core.l_qseq; + } + float mvd=0; + int j; + n=0; + for (i=0; imvd[0] = n ? mvd/n : 0; + r->mvd[1] = alt_dp; + r->mvd[2] = alt_dp ? read_len/alt_dp : 0; + return r->depth; } + +void calc_vdb(int n, const bcf_callret1_t *calls, bcf_call_t *call) +{ + // Variant distance bias. Samples merged by means of DP-weighted average. + + float weight=0, tot_prob=0; + + int i; + for (i=0; i2*mu ? 0 : sin(mvd*3.14/2/mu) / (4*mu/3.14); + } + else + { + // Scaled gaussian curve, crude approximation, but behaves well. Using fixed depth for bigger depths. + if ( dp>5 ) + dp = 5; + float sigma2 = (read_len/1.9/(dp+1)) * (read_len/1.9/(dp+1)); + float norm = 1.125*sqrt(2*3.14*sigma2); + float mu = read_len/2.9; + if ( mvd < mu ) + prob = exp(-(mvd-mu)*(mvd-mu)/2/sigma2)/norm; + else + prob = exp(-(mvd-mu)*(mvd-mu)/3.125/sigma2)/norm; + } + + //fprintf(stderr,"dp=%d mvd=%d read_len=%d -> prob=%f\n", dp,mvd,read_len,prob); + tot_prob += prob*dp; + weight += dp; + } + tot_prob = weight ? tot_prob/weight : 1; + //fprintf(stderr,"prob=%f\n", tot_prob); + call->vdb = tot_prob; +} + int bcf_call_combine(int n, const bcf_callret1_t *calls, int ref_base /*4-bit*/, bcf_call_t *call) { int ref4, i, j, qsum[4]; @@ -170,10 +255,13 @@ int bcf_call_combine(int n, const bcf_callret1_t *calls, int ref_base /*4-bit*/, call->ori_depth += calls[i].ori_depth; for (j = 0; j < 16; ++j) call->anno[j] += calls[i].anno[j]; } + + calc_vdb(n, calls, call); + return 0; } -int bcf_call2bcf(int tid, int pos, bcf_call_t *bc, bcf1_t *b, bcf_callret1_t *bcr, int is_SP, +int bcf_call2bcf(int tid, int pos, bcf_call_t *bc, bcf1_t *b, bcf_callret1_t *bcr, int fmt_flag, const bcf_callaux_t *bca, const char *ref) { extern double kt_fisher_exact(int n11, int n12, int n21, int n22, double *_left, double *_right, double *two); @@ -223,24 +311,29 @@ int bcf_call2bcf(int tid, int pos, bcf_call_t *bc, bcf1_t *b, bcf_callret1_t *bc if (i) kputc(',', &s); kputw(bc->anno[i], &s); } + if (bc->vdb != 1) + ksprintf(&s, ";VDB=%.4f", bc->vdb); kputc('\0', &s); // FMT kputs("PL", &s); - if (bcr) { - kputs(":DP", &s); - if (is_SP) kputs(":SP", &s); + if (bcr && fmt_flag) { + if (fmt_flag & B2B_FMT_DP) kputs(":DP", &s); + if (fmt_flag & B2B_FMT_DV) kputs(":DV", &s); + if (fmt_flag & B2B_FMT_SP) kputs(":SP", &s); } kputc('\0', &s); b->m_str = s.m; b->str = s.s; b->l_str = s.l; bcf_sync(b); memcpy(b->gi[0].data, bc->PL, b->gi[0].len * bc->n); - if (bcr) { - uint16_t *dp = (uint16_t*)b->gi[1].data; - uint8_t *sp = is_SP? b->gi[2].data : 0; + if (bcr && fmt_flag) { + uint16_t *dp = (fmt_flag & B2B_FMT_DP)? b->gi[1].data : 0; + uint16_t *dv = (fmt_flag & B2B_FMT_DV)? b->gi[1 + ((fmt_flag & B2B_FMT_DP) != 0)].data : 0; + int32_t *sp = (fmt_flag & B2B_FMT_SP)? b->gi[1 + ((fmt_flag & B2B_FMT_DP) != 0) + ((fmt_flag & B2B_FMT_DV) != 0)].data : 0; for (i = 0; i < bc->n; ++i) { bcf_callret1_t *p = bcr + i; - dp[i] = p->depth < 0xffff? p->depth : 0xffff; - if (is_SP) { + if (dp) dp[i] = p->depth < 0xffff? p->depth : 0xffff; + if (dv) dv[i] = p->n_supp < 0xffff? p->n_supp : 0xffff; + if (sp) { if (p->anno[0] + p->anno[1] < 2 || p->anno[2] + p->anno[3] < 2 || p->anno[0] + p->anno[2] < 2 || p->anno[1] + p->anno[3] < 2) {