]> git.donarmstrong.com Git - samtools.git/blobdiff - bam_mcns.c
added an alternative prior
[samtools.git] / bam_mcns.c
index b69ec0f0abaceb6aa0408cb61a9adc51b0626765..7859169c9ef8799b37878a6d1e19e7c1c5b8fcb0 100644 (file)
@@ -10,9 +10,24 @@ struct __mc_aux_t {
        int n, N;
        int ref, alt;
        double *q2p, *pdg; // pdg -> P(D|g)
-       int *qsum, *bcnt, rcnt[4];
+       double *alpha, *beta;
+       int *qsum, *bcnt;
 };
 
+void mc_init_prior(mc_aux_t *ma, int type, double theta)
+{
+       int i;
+       if (type == MC_PTYPE_COND2) {
+               for (i = 0; i <= 2 * ma->n; ++i)
+                       ma->alpha[i] = 2. * (i + 1) / (2 * ma->n + 1) / (2 * ma->n + 2);
+       } else {
+               double sum;
+               for (i = 0, sum = 0.; i < 2 * ma->n; ++i)
+                       sum += (ma->alpha[i] = theta / (2 * ma->n - i));
+               ma->alpha[2 * ma->n] = 1. - sum;
+       }
+}
+
 mc_aux_t *mc_init(int n) // FIXME: assuming diploid
 {
        mc_aux_t *ma;
@@ -23,8 +38,18 @@ mc_aux_t *mc_init(int n) // FIXME: assuming diploid
        ma->qsum = calloc(4 * ma->n, sizeof(int));
        ma->bcnt = calloc(4 * ma->n, sizeof(int));
        ma->pdg = calloc(3 * ma->n, sizeof(double));
+       ma->alpha = calloc(2 * ma->n + 1, sizeof(double));
+       ma->beta = calloc((2 * ma->n + 1) * 3, sizeof(double));
        for (i = 0; i <= MC_MAX_SUMQ; ++i)
                ma->q2p[i] = pow(10., -i / 10.);
+       for (i = 0; i <= 2 * ma->n; ++i) { // beta[k][g]=P(g|k/M)
+               double *bi = ma->beta + 3 * i;
+               double f = (double)i / (2 * ma->n);
+               bi[0] = (1. - f) * (1. - f);
+               bi[1] = 2 * f * (1. - f);
+               bi[2] = f * f;
+       }
+       mc_init_prior(ma, MC_PTYPE_FULL, 1e-3); // the simplest prior
        return ma;
 }
 
@@ -33,6 +58,7 @@ void mc_destroy(mc_aux_t *ma)
        if (ma) {
                free(ma->qsum); free(ma->bcnt);
                free(ma->q2p); free(ma->pdg);
+               free(ma->alpha); free(ma->beta);
                free(ma);
        }
 }
@@ -42,11 +68,9 @@ static void sum_err(int *n, const bam_pileup1_t **plp, mc_aux_t *ma)
        int i, j;
        memset(ma->qsum, 0, sizeof(int) * 4 * ma->n);
        memset(ma->bcnt, 0, sizeof(int) * 4 * ma->n);
-       memset(ma->rcnt, 0, sizeof(int) * 4);
        for (j = 0; j < ma->n; ++j) {
                int tmp, *qsum = ma->qsum + j * 4;
                int *bcnt = ma->bcnt + j * 4;
-               double r = drand48(), rr;
                for (i = tmp = 0; i < n[j]; ++i) {
                        const bam_pileup1_t *p = plp[j] + i;
                        int q, b;
@@ -60,13 +84,6 @@ static void sum_err(int *n, const bam_pileup1_t **plp, mc_aux_t *ma)
                        ++bcnt[b];
                        ++tmp;
                }
-               if (tmp) {
-                       for (i = 0, rr = 0.; i < 4; ++i) {
-                               rr += (double)bcnt[i] / tmp;
-                               if (rr >= r) break;
-                       }
-                       if (i < 4) ++ma->rcnt[i];
-               }
        }
 }
 
@@ -101,26 +118,26 @@ static void cal_pdg(mc_aux_t *ma)
                        pdg[i] = pi[i] > MC_MAX_SUMQ? MC_MAX_SUMQP : ma->q2p[pi[i]];
        }
 }
-
+// return the reference allele frequency
 double mc_freq0(int ref, int *n, const bam_pileup1_t **plp, mc_aux_t *ma, int *_ref, int *alt)
 {
-       int i, acnt[4], j;
-       double fr = -1., f0 = -1.;
+       int i, cnt;
+       double f;
        sum_err(n, plp, ma);
        set_allele(ref, ma);
        cal_pdg(ma);
-       acnt[0] = acnt[1] = acnt[2] = acnt[3] = 0;
-       for (i = 0; i < ma->n; ++i)
-               for (j = 0; j < 4; ++j)
-                       acnt[j] += ma->bcnt[i * 4 + j];
-       if (ma->rcnt[ma->ref] + ma->rcnt[ma->alt]) // never used...
-               fr = (double)ma->rcnt[ref] / (ma->rcnt[ma->ref] + ma->rcnt[ma->alt]);
-       if (acnt[ma->ref] + acnt[ma->alt])
-               f0 = (double)acnt[ref] / (acnt[ma->ref] + acnt[ma->alt]);
        *_ref = ma->ref; *alt = ma->alt;
-       return ma->n == 1 || fr < 0.? f0 : fr;
+       for (i = cnt = 0, f = 0.; i < ma->n; ++i) {
+               int *bcnt = ma->bcnt + i * 4;
+               int x = bcnt[ma->ref] + bcnt[ma->alt];
+               if (x) {
+                       ++cnt;
+                       f += (double)bcnt[ma->ref] / x;
+               }
+       }
+       return f / cnt;
 }
-
+// f0 is the reference allele frequency
 double mc_freq_iter(double f0, mc_aux_t *ma)
 {
        double f, f3[3];
@@ -138,3 +155,73 @@ double mc_freq_iter(double f0, mc_aux_t *ma)
        f /= ma->n * 2.;
        return f;
 }
+
+double mc_freq_post(mc_aux_t *ma)
+{
+       int i, k;
+       long double f = 0.;
+       for (i = 0; i < ma->n; ++i) {
+               double *pdg = ma->pdg + i * 3;
+               long double y = 0., z = 0.;
+               for (k = 0; k <= ma->n * 2; ++k) {
+                       double *bk = ma->beta + k * 3;
+/*
+                       int g;
+                       double yk = 0., zk = 0.;
+                       for (g = 0; g < 3; ++g) {
+                               yk += g * pdg[g] * bk[g];
+                               zk += pdg[g] * bk[g];
+                       }
+                       y += yk * ma->alpha[k];
+                       z += zk * ma->alpha[k];
+*/
+                       y += (pdg[1] * bk[1] + 2. * pdg[2] * bk[2]) * ma->alpha[k];
+                       z += (pdg[0] * bk[0] + pdg[1] * bk[1] + pdg[2] * bk[2]) * ma->alpha[k];
+               }
+               f += y / z;
+       }
+       return f / ma->n / 2;
+}
+
+double mc_ref_prob(mc_aux_t *ma)
+{
+       int k, i;
+       long double PD = 0., Pref = 0.;
+       for (k = 0; k <= ma->n * 2; ++k) {
+               long double x = 1.;
+               double *bk = ma->beta + k * 3;
+               for (i = 0; i < ma->n; ++i) {
+                       double *pdg = ma->pdg + i * 3;
+//                     int g; double y=0.; for (g = 0; g < 3; ++g) y += pdg[g] * bk[g];
+                       x *= pdg[0] * bk[0] + pdg[1] * bk[1] + pdg[2] * bk[2];
+               }
+               PD += x * ma->alpha[k];
+       }
+       for (k = 0; k <= ma->n * 2; ++k) {
+               long double x = 1.0;
+               for (i = 0; i < ma->n; ++i)
+                       x *= ma->pdg[i * 3 + 2] * ma->beta[k * 3 + 2];
+               Pref += x * ma->alpha[k];
+       }
+       return Pref / PD;
+}
+
+int mc_call_gt(const mc_aux_t *ma, double f0, int k)
+{
+       double sum, g[3];
+       double max, f3[3], *pdg = ma->pdg + k * 3;
+       int q, i, max_i;
+       f3[0] = (1.-f0)*(1.-f0); f3[1] = 2.*f0*(1.-f0); f3[2] = f0*f0;
+       for (i = 0, sum = 0.; i < 3; ++i)
+               sum += (g[i] = pdg[i] * f3[i]);
+       for (i = 0, max = -1., max_i = 0; i < 3; ++i) {
+               g[i] /= sum;
+               if (g[i] > max) max = g[i], max_i = i;
+       }
+//     printf("***%lg,%lg,%lg,%lg,%lg,%lg\n", g[0], g[1], g[2], pdg[0], pdg[1], pdg[2]);
+       max = 1. - max;
+       if (max < 1e-308) max = 1e-308;
+       q = (int)(-3.434 * log(max) + .499);
+       if (q > 99) q = 99;
+       return q<<2|max_i;
+}