Ejemplo n.º 1
0
 def test_exact_fixation_probability(self):
     s = 0.03
     N_diploid = 3
     N_haploid = N_diploid * 2
     # Define a transition matrix with boundary conditions.
     # This approach is nice because the computationally intensive part
     # is just finding the equilibrium distribution of a process,
     # and you also get the conditional equilibrium distribution
     # of the dimorphic states.
     P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
     P[0, 0] = 0
     P[0, 1] = 1
     P[N_haploid, N_haploid] = 0
     P[N_haploid, 1] = 1
     v = MatrixUtil.get_stationary_distribution(P)
     fpa = v[-1] / (v[0] + v[-1])
     # Define a transition matrix with boundary conditions.
     # This approach is nice because it gives fixation probabilities
     # conditional on each possible initial allele frequency.
     P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
     A = P - np.eye(N_haploid + 1)
     b = np.zeros(N_haploid + 1)
     A[0, 0] = 1
     A[N_haploid, N_haploid] = 1
     b[0] = 0
     b[N_haploid] = 1
     x = linalg.solve(A, b)
     fpb = x[1]
     # Compare the transition probabilities.
     #print fpa
     #print get_pfix_approx(N_diploid, s)
     self.assertTrue(np.allclose(fpa, fpb))
Ejemplo n.º 2
0
 def test_exact_fixation_probability(self):
     s = 0.03
     N_diploid = 3
     N_haploid = N_diploid * 2
     # Define a transition matrix with boundary conditions.
     # This approach is nice because the computationally intensive part
     # is just finding the equilibrium distribution of a process,
     # and you also get the conditional equilibrium distribution
     # of the dimorphic states.
     P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
     P[0, 0] = 0
     P[0, 1] = 1
     P[N_haploid, N_haploid] = 0
     P[N_haploid, 1] = 1
     v = MatrixUtil.get_stationary_distribution(P)
     fpa = v[-1] / (v[0] + v[-1])
     # Define a transition matrix with boundary conditions.
     # This approach is nice because it gives fixation probabilities
     # conditional on each possible initial allele frequency.
     P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
     A = P - np.eye(N_haploid + 1)
     b = np.zeros(N_haploid + 1)
     A[0, 0] = 1
     A[N_haploid, N_haploid] = 1
     b[0] = 0
     b[N_haploid] = 1
     x = linalg.solve(A, b)
     fpb = x[1]
     # Compare the transition probabilities.
     #print fpa
     #print get_pfix_approx(N_diploid, s)
     self.assertTrue(np.allclose(fpa, fpb))
Ejemplo n.º 3
0
 def test_expected_generations_until_absorption_no_selection(self):
     s = 0
     N_diploid = 100
     N_haploid = N_diploid * 2
     # Define a transition matrix with boundary conditions.
     # This approach is nice because the computationally intensive part
     # is just finding the equilibrium distribution of a process,
     # and you also get the conditional equilibrium distribution
     # of the dimorphic states.
     P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
     P[0, 0] = 0
     P[0, 1] = 1
     P[N_haploid, N_haploid] = 0
     P[N_haploid, 1] = 1
     v = MatrixUtil.get_stationary_distribution(P)
     fpa = v[-1] / (v[0] + v[-1])
     # Use the Kimura approximation to get the expected
     # number of generations until absorption for a neutral allele.
     p = 1 / float(N_haploid)
     #p_fixation = v[-1] / (v[0] + v[-1])
     #p_loss = v[0] / (v[0] + v[-1])
     # expected number of generations until fixation excluding loss
     t1 = -(1/p)*2*N_haploid*(1-p)*math.log(1-p)
     # expected number of generations until loss excluding fixation
     p_fixation = get_pfix_approx(N_diploid, s)
     p_loss = 1 - p_fixation
     t0 = -2*N_haploid*(p/(1-p))*math.log(p)
     t = p_loss * t0 + p_fixation * t1
Ejemplo n.º 4
0
 def test_expected_generations_until_absorption_no_selection(self):
     s = 0
     N_diploid = 100
     N_haploid = N_diploid * 2
     # Define a transition matrix with boundary conditions.
     # This approach is nice because the computationally intensive part
     # is just finding the equilibrium distribution of a process,
     # and you also get the conditional equilibrium distribution
     # of the dimorphic states.
     P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
     P[0, 0] = 0
     P[0, 1] = 1
     P[N_haploid, N_haploid] = 0
     P[N_haploid, 1] = 1
     v = MatrixUtil.get_stationary_distribution(P)
     fpa = v[-1] / (v[0] + v[-1])
     # Use the Kimura approximation to get the expected
     # number of generations until absorption for a neutral allele.
     p = 1 / float(N_haploid)
     #p_fixation = v[-1] / (v[0] + v[-1])
     #p_loss = v[0] / (v[0] + v[-1])
     # expected number of generations until fixation excluding loss
     t1 = -(1 / p) * 2 * N_haploid * (1 - p) * math.log(1 - p)
     # expected number of generations until loss excluding fixation
     p_fixation = get_pfix_approx(N_diploid, s)
     p_loss = 1 - p_fixation
     t0 = -2 * N_haploid * (p / (1 - p)) * math.log(p)
     t = p_loss * t0 + p_fixation * t1
Ejemplo n.º 5
0
def solve(N_haploid, s):
    """
    @param N_haploid: population
    @param s: selection
    @return: vector of probabilities
    """
    if N_haploid % 2:
        raise ValueError('expected an even haploid population')
    N_diploid = N_haploid / 2
    #fB = 1.0 + s
    #fb = 1.0
    # compute the transition matrix 
    P = np.exp(wfengine.create_genic_diallelic(N_diploid, s*2))
    # define some boundary conditions
    #P[0, 0] = 0
    #P[0, 1] = 1
    #P[N_diploid, N_diploid] = 0
    #P[N_diploid, 1] = 1
    #
    # Put the puzzle into the form Ax=b
    # so that it can be solved by a generic linear solver.
    A = P - np.eye(N_haploid + 1)
    b = np.zeros(N_haploid + 1)
    # Adjust the matrix to disambiguate absorbing states.
    A[0, 0] = 1
    A[N_haploid, N_haploid] = 1
    b[0] = 0
    b[N_haploid] = 1
    x = linalg.solve(A, b)
    # Return the probability of fixation of the B allele.
    return x
Ejemplo n.º 6
0
def get_t1_exact(N_diploid):
    """
    @param N_diploid: number of diploid individuals in the population
    @return: a sequence of expected fixation times
    """
    s = 0
    N_haploid = N_diploid * 2
    P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
    # Create a transition matrix modified so that it is conditional
    # on eventual fixation.
    x = kimura.get_fixation_probabilities(P)
    A = (P * x)[1:, 1:]
    for i in range(N_haploid):
        A[i] /= np.sum(A[i])
    A[-1, -1] = 0
    A[-1, 0] = 1
    # Now use this conditional transition matrix
    # to set up a system of equations that will give
    # the expected number of generations until fixation
    # conditioned upon eventual fixation
    B = A - np.eye(N_haploid)
    b = -np.ones(N_haploid)
    B[-1] = np.zeros(N_haploid)
    B[-1, -1] = 1
    b[-1] = 0
    y = linalg.solve(B, b)
    return y.tolist()
Ejemplo n.º 7
0
def get_t1_exact(N_diploid):
    """
    @param N_diploid: number of diploid individuals in the population
    @return: a sequence of expected fixation times
    """
    s = 0
    N_haploid = N_diploid * 2
    P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
    # Create a transition matrix modified so that it is conditional
    # on eventual fixation.
    x = kimura.get_fixation_probabilities(P)
    A = (P * x)[1:, 1:]
    for i in range(N_haploid):
        A[i] /= np.sum(A[i])
    A[-1, -1] = 0
    A[-1, 0] = 1
    # Now use this conditional transition matrix
    # to set up a system of equations that will give
    # the expected number of generations until fixation
    # conditioned upon eventual fixation
    B = A - np.eye(N_haploid)
    b = -np.ones(N_haploid)
    B[-1] = np.zeros(N_haploid)
    B[-1, -1] = 1
    b[-1] = 0
    y = linalg.solve(B, b)
    return y.tolist()
Ejemplo n.º 8
0
 def test_time_until_fixation_no_selection(self):
     s = 0
     N_diploid = 100
     N_haploid = N_diploid * 2
     print 'diploid population:', N_diploid
     P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
     # Create a transition matrix modified so that it is conditional
     # on eventual fixation.
     x = get_fixation_probabilities(P)
     print 'fixation probabilities:'
     print x
     A = (P * x)[1:, 1:]
     for i in range(N_haploid):
         A[i] /= np.sum(A[i])
     A[-1, -1] = 0
     A[-1, 0] = 1
     #
     #v = MatrixUtil.get_stationary_distribution(A)
     ## condition on a single mutation having already happened
     #v[0] -= v[-1]
     #v /= np.sum(v)
     #print 'expected generations until fixed, given eventual fixation:', (
             #(1 - v[-1]) / (v[-1]))
     #
     # Now use this conditional transition matrix
     # to set up a system of equations that will give
     # the expected number of generations until fixation
     # conditioned upon eventual fixation
     #
     B = A - np.eye(N_haploid)
     b = -np.ones(N_haploid)
     B[-1] = np.zeros(N_haploid)
     B[-1, -1] = 1
     b[-1] = 0
     y = linalg.solve(B, b)
     print 'expected time until fixation given some number of alleles:'
     print y
     #
     # Get the expected time until fixation given eventual fixation
     # when the population begins with proportion p mutants.
     #p = 5.0 * (1 / float(N_haploid))
     p = 0.1
     t0 = -2*N_haploid*(p/(1-p))*math.log(p)
     t1 = -(1/p)*2*N_haploid*(1-p)*math.log(1-p)
     print 'kimura initial p =', p
     print 'kimura expected to fixation:', t1
     print 'kimura expected to loss:', t0
     """
Ejemplo n.º 9
0
 def test_time_until_fixation_no_selection(self):
     s = 0
     N_diploid = 100
     N_haploid = N_diploid * 2
     print 'diploid population:', N_diploid
     P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
     # Create a transition matrix modified so that it is conditional
     # on eventual fixation.
     x = get_fixation_probabilities(P)
     print 'fixation probabilities:'
     print x
     A = (P * x)[1:, 1:]
     for i in range(N_haploid):
         A[i] /= np.sum(A[i])
     A[-1, -1] = 0
     A[-1, 0] = 1
     #
     #v = MatrixUtil.get_stationary_distribution(A)
     ## condition on a single mutation having already happened
     #v[0] -= v[-1]
     #v /= np.sum(v)
     #print 'expected generations until fixed, given eventual fixation:', (
     #(1 - v[-1]) / (v[-1]))
     #
     # Now use this conditional transition matrix
     # to set up a system of equations that will give
     # the expected number of generations until fixation
     # conditioned upon eventual fixation
     #
     B = A - np.eye(N_haploid)
     b = -np.ones(N_haploid)
     B[-1] = np.zeros(N_haploid)
     B[-1, -1] = 1
     b[-1] = 0
     y = linalg.solve(B, b)
     print 'expected time until fixation given some number of alleles:'
     print y
     #
     # Get the expected time until fixation given eventual fixation
     # when the population begins with proportion p mutants.
     #p = 5.0 * (1 / float(N_haploid))
     p = 0.1
     t0 = -2 * N_haploid * (p / (1 - p)) * math.log(p)
     t1 = -(1 / p) * 2 * N_haploid * (1 - p) * math.log(1 - p)
     print 'kimura initial p =', p
     print 'kimura expected to fixation:', t1
     print 'kimura expected to loss:', t0
     """
Ejemplo n.º 10
0
 def test_wright_fisher(self):
     N_diallelic = 3
     s = 0.03
     # compute the wright fisher transition matrix directly
     Ma = np.exp(wfengine.create_genic_diallelic(N_diallelic, s))
     MatrixUtil.assert_transition_matrix(Ma)
     # compute the wright fisher transition matrix less directly
     N = 2*N_diallelic
     fi = 1.0
     fj = 1.0 - s
     log_distns = np.zeros((N+1, 2))
     for h in range(0, N+1):
         probs = genic_diallelic(fi, fj, h, (N-h))
         log_distns[h] = np.log(np.array(probs))
     Mb = np.exp(wfengine.expand_multinomials(N, log_distns))
     MatrixUtil.assert_transition_matrix(Mb)
     # compare the transition matrices
     self.assertTrue(np.allclose(Ma, Mb))
Ejemplo n.º 11
0
 def test_wright_fisher(self):
     N_diallelic = 3
     s = 0.03
     # compute the wright fisher transition matrix directly
     Ma = np.exp(wfengine.create_genic_diallelic(N_diallelic, s))
     MatrixUtil.assert_transition_matrix(Ma)
     # compute the wright fisher transition matrix less directly
     N = 2 * N_diallelic
     fi = 1.0
     fj = 1.0 - s
     log_distns = np.zeros((N + 1, 2))
     for h in range(0, N + 1):
         probs = genic_diallelic(fi, fj, h, (N - h))
         log_distns[h] = np.log(np.array(probs))
     Mb = np.exp(wfengine.expand_multinomials(N, log_distns))
     MatrixUtil.assert_transition_matrix(Mb)
     # compare the transition matrices
     self.assertTrue(np.allclose(Ma, Mb))
Ejemplo n.º 12
0
def get_transition_matrix(N_diploid, k, mutation, fit):
    """
    Mutation probabilities are away from a fixed state.
    @param N_diploid: diploid population size
    @param k: number of alleles e.g. 4 for A,C,G,T
    @param mutation: k by k matrix of per-generation mutation probabilities
    @param fit: sequence of k fitness values
    @return: a transition matrix
    """
    N = N_diploid * 2
    states = [tuple(s) for s in gen_states(N,k)]
    nstates = len(states)
    s_to_i = dict((s, i) for i, s in enumerate(states))
    P = np.zeros((nstates, nstates))
    # Add rows corresponding to transitions from population states
    # for which an allele is currently fixed in the population.
    for i in range(k):
        P[i, i] = mutation[i, i]
        for j in range(k):
            if i == j:
                continue
            state = [0]*k
            state[i] = N-1
            state[j] = 1
            P[i, s_to_i[tuple(state)]] = mutation[i, j]
    # Define transition matrices within a single diallelic subspace.
    for bi, (i, j) in enumerate(combinations(range(k), 2)):
        s = 1 - fit[j] / fit[i]
        pblock = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
        ibegin = k + (N-1)*bi
        iend = ibegin + N - 1
        # The first index of pblock corresponds to fixation of j,
        # and the last index of pblock corresponds to fixation of i.
        # Incorporate fixation probabilities given various
        # nontrivial diallelic frequencies.
        P[ibegin:iend, i] = pblock[1:-1, -1]
        P[ibegin:iend, j] = pblock[1:-1, 0]
        # Incorporate transition probabilities among
        # nontrivial diallelic frequencies.
        # Note that the first and last row of pblock
        # are completely ignored.  This is intentional.
        P[ibegin:iend, ibegin:iend] = pblock[1:-1, 1:-1]
    return P
Ejemplo n.º 13
0
def get_transition_matrix(N_diploid, k, mutation, fit):
    """
    Mutation probabilities are away from a fixed state.
    @param N_diploid: diploid population size
    @param k: number of alleles e.g. 4 for A,C,G,T
    @param mutation: k by k matrix of per-generation mutation probabilities
    @param fit: sequence of k fitness values
    @return: a transition matrix
    """
    N = N_diploid * 2
    states = [tuple(s) for s in gen_states(N, k)]
    nstates = len(states)
    s_to_i = dict((s, i) for i, s in enumerate(states))
    P = np.zeros((nstates, nstates))
    # Add rows corresponding to transitions from population states
    # for which an allele is currently fixed in the population.
    for i in range(k):
        P[i, i] = mutation[i, i]
        for j in range(k):
            if i == j:
                continue
            state = [0] * k
            state[i] = N - 1
            state[j] = 1
            P[i, s_to_i[tuple(state)]] = mutation[i, j]
    # Define transition matrices within a single diallelic subspace.
    for bi, (i, j) in enumerate(combinations(range(k), 2)):
        s = 1 - fit[j] / fit[i]
        pblock = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
        ibegin = k + (N - 1) * bi
        iend = ibegin + N - 1
        # The first index of pblock corresponds to fixation of j,
        # and the last index of pblock corresponds to fixation of i.
        # Incorporate fixation probabilities given various
        # nontrivial diallelic frequencies.
        P[ibegin:iend, i] = pblock[1:-1, -1]
        P[ibegin:iend, j] = pblock[1:-1, 0]
        # Incorporate transition probabilities among
        # nontrivial diallelic frequencies.
        # Note that the first and last row of pblock
        # are completely ignored.  This is intentional.
        P[ibegin:iend, ibegin:iend] = pblock[1:-1, 1:-1]
    return P
Ejemplo n.º 14
0
def get_two_allele_distribution(N_diploid, f0, f1):
    """
    Assumes small genic selection.
    Assumes small mutation.
    The mutational bias does not affect the distribution.
    @param N_diploid: diploid population size
    @param f0: fitness of allele 0
    @param f1: fitness of allele 1
    @return: distribution over all non-fixed population states
    """
    #"""
    # get the transition matrix without mutation
    s = 1 - f1 / f0
    P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
    # add mutation
    P[0, 0] = 0
    P[0, 1] = 1
    P[2 * N_diploid, 2 * N_diploid] = 0
    P[2 * N_diploid, 2 * N_diploid - 1] = 1
    #"""
    """
    # construct something like a transition matrix
    N_haploid = N_diploid * 2
    nstates = N_haploid + 1
    P = np.zeros((nstates, nstates))
    for i in range(nstates):
        p0, p1 = wrightfisher.genic_diallelic(f0, f1, i, N_haploid-i)
        if i == 0:
            P[i, 1] = 1.0
        elif i == N_haploid:
            P[i, N_haploid-1] = 1.0
        else:
            for j in range(nstates):
                logp = StatsUtil.binomial_log_pmf(j, N_haploid, p0)
                P[i, j] = math.exp(logp)
    """
    # find the stationary distribution
    v = MatrixUtil.get_stationary_distribution(P)
    if not np.allclose(v, np.dot(v, P)):
        raise ValueError
    # return the stationary distribution conditional on dimorphism
    return v[1:-1] / np.sum(v[1:-1])
Ejemplo n.º 15
0
def get_two_allele_distribution(N_diploid, f0, f1):
    """
    Assumes small genic selection.
    Assumes small mutation.
    The mutational bias does not affect the distribution.
    @param N_diploid: diploid population size
    @param f0: fitness of allele 0
    @param f1: fitness of allele 1
    @return: distribution over all non-fixed population states
    """
    #"""
    # get the transition matrix without mutation
    s = 1 - f1 / f0
    P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
    # add mutation
    P[0, 0] = 0
    P[0, 1] = 1
    P[2*N_diploid, 2*N_diploid] = 0
    P[2*N_diploid, 2*N_diploid-1] = 1
    #"""
    """
    # construct something like a transition matrix
    N_haploid = N_diploid * 2
    nstates = N_haploid + 1
    P = np.zeros((nstates, nstates))
    for i in range(nstates):
        p0, p1 = wrightfisher.genic_diallelic(f0, f1, i, N_haploid-i)
        if i == 0:
            P[i, 1] = 1.0
        elif i == N_haploid:
            P[i, N_haploid-1] = 1.0
        else:
            for j in range(nstates):
                logp = StatsUtil.binomial_log_pmf(j, N_haploid, p0)
                P[i, j] = math.exp(logp)
    """
    # find the stationary distribution
    v = MatrixUtil.get_stationary_distribution(P)
    if not np.allclose(v, np.dot(v, P)):
        raise ValueError
    # return the stationary distribution conditional on dimorphism
    return v[1:-1] / np.sum(v[1:-1])
Ejemplo n.º 16
0
def get_stationary_distribution_tricky(N_diploid, k, mutation, fit):
    """
    This uses a decomposition that is too clever.
    The idea is to proceed in three steps.
    Assume that there are k=4 different alleles and you are
    using the Kai Zeng model.
    First do an O(N^3) solve of each of the choose(k, 2) = 6 blocks.
    If this is done cleverly this gives vectors that directly
    yield the directional fixation probabilities
    and the directional stationary distribution conditional on dimorphism.
    This step takes roughly (1/6)^2 the time of a naive solve of
    the full Kai Zeng matrix.
    Second compute the fixed-state-only 4x4 transition matrix
    and get its stationary distribution.
    This uses the fixation probabilities computed in the first step.
    Third compute the stationary distributions of the dimorphic states
    using the stationary distributions of the fixed states
    computed in the second step.
    """
    solves = []
    # Define transition matrices within a single diallelic subspace.
    for bi, (i, j) in enumerate(combinations(range(k), 2)):
        s = 1 - fit[j] / fit[i]
        P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
        A = np.zeros((N_diploid*2+1+2, N_diploid*2+1+2))
        # Adjust P and put it into A.
        # Setting these values to zero causes them to act as sinks.
        P[0, 0] = 0
        P[-1, -1] = 0
        P -= np.eye(N_diploid*2+1)
        A[1:-1, 1:-1] = P
        # Add some probability sources.
        A[0, 0] = 1
        A[0, 2] = 1
        A[-1, -1] = 1
        A[-1, -3] = 1
        # Define the B matrix which will hold the solve.
        # The two columns are the two directions per diallelic block.
        B = np.zeros((N_diploid*2+1+2, 2))
        B[0,0] = 1
        B[-1,-1] = 1
        X = linalg.solve(A.T, B)
        solves.append(X)
    # Compute the fixation probabilities from the block solutions.
    F = np.zeros((k, k))
    for bi, (i, j) in enumerate(combinations(range(k), 2)):
        X = solves[bi]
        #print X
        #print
        # Second row of X is background allele frequency.
        # Second to last row of X is mutant allele frequency.
        # First column of X is forward, second column is reverse.
        # F[i, j] is the probability of fixation of allele j
        # against the background of allele i.
        F[i, j] = X[1, 1]
        F[j, i] = X[-2, 0]
    print F
    # Compute the transition matrix among fixed states.
    # This is nearly the hadamard product of mutation and fixation.
    T = mutation * F
    T += np.eye(k) - np.diag(np.sum(T, axis=1))
    print T
    # Compute the stationary distribution among fixed states.
    v_small = MatrixUtil.get_stationary_distribution(T)
    print v_small
    # Compute dimorphic distributions using the block solutions
    # and the previously computed stuff like fixed state stationary
    # distributions, and also using the mutation probabilities.
    dtotal = v_small.tolist()
    for bi, (i, j) in enumerate(combinations(range(k), 2)):
        X = solves[bi]
        distn = np.zeros(N_diploid*2 - 1)
        d = X.T[1][2:-2]
        distn += v_small[i] * mutation[i, j] * d
        d = X.T[0][2:-2]
        distn += v_small[j] * mutation[j, i] * d
        dtotal.extend(distn)
    # 
    #print sum(sum(d) for d in distns)
    dtotal = np.array(dtotal)
    #print dtotal
    #print dtotal / np.sum(dtotal)
    return dtotal / np.sum(dtotal)
Ejemplo n.º 17
0
def get_response_content(fs):
    N_diploid = fs.N_diploid
    N = N_diploid * 2
    k = 2
    gamma = fs.gamma
    # define the fitnesses and the selection value
    f0 = 1.0
    f1 = 1.0 - gamma / N
    s = 1 - f1 / f0
    if f1 <= 0:
        raise ValueError('the extreme selection caused a non-positive fitness')
    # get a wright fisher transition matrix
    P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
    """
    # condition on no fixation
    for i in range(N):
        P[i] /= 1 - P[i, N]
    # remove the fixed state from the transition matrix
    P = P[:N, :N]
    """
    # add mutations
    P[0, 0] = 0
    P[0, 1] = 1
    P[N, N] = 0
    P[N, 1] = 1
    # compute the stationary distribution
    v = MatrixUtil.get_stationary_distribution(P)
    # get the distribution over dimorphic states
    h = v[1:-1]
    h /= np.sum(h)
    # look at continuous approximations
    w = np.zeros(N+1)
    for i in range(1, N):
        x = i / float(N)
        #x0 = i / float(N)
        #x1 = (i + 1) / float(N)
        #value = sojourn_definite(x0, x1, gamma)
        value = sojourn_kernel(x, gamma)
        w[i] = value
    w = w[1:-1]
    w /= np.sum(w)
    # get the array for the R plot
    arr = [h.tolist(), w.tolist()]
    # define the r script
    out = StringIO()
    print >> out, 'title.string <- "allele 1 vs allele 2"'
    print >> out, 'mdat <-', RUtil.matrix_to_R_string(arr)
    print >> out, mk_call_str(
            'barplot',
            'mdat',
            'legend.text=' + mk_call_str(
                'c',
                '"exact discrete distribution"',
                '"continuous approximation"',
                #'"two-allele large N limit"',
                #'"two-allele"',
                #'"four-allele without mutational bias"',
                #'"four-allele with mutational bias (kappa_{1,2}=2)"',
                #'"four-allele with mutational bias, large N limit"',
                ),
            'args.legend = list(x="topright", bty="n")',
            'names.arg = 1:%s' % (N-1),
            main='title.string',
            xlab='"frequency of allele 1"',
            ylab='"frequency"',
            col=mk_call_str(
                'c',
                #'"red"',
                #'"white"',
                '"black"',
                #'"gray"',
                '"red"',
                ),
            beside='TRUE',
            border='NA',
            )
    #print >> out, 'box()'
    script = out.getvalue().rstrip()
    # create the R plot image
    device_name = Form.g_imageformat_to_r_function[fs.imageformat]
    retcode, r_out, r_err, image_data = RUtil.run_plotter_no_table(
            script, device_name)
    if retcode:
        raise RUtil.RError(r_err)
    return image_data
Ejemplo n.º 18
0
def get_stationary_distribution_tricky(N_diploid, k, mutation, fit):
    """
    This uses a decomposition that is too clever.
    The idea is to proceed in three steps.
    Assume that there are k=4 different alleles and you are
    using the Kai Zeng model.
    First do an O(N^3) solve of each of the choose(k, 2) = 6 blocks.
    If this is done cleverly this gives vectors that directly
    yield the directional fixation probabilities
    and the directional stationary distribution conditional on dimorphism.
    This step takes roughly (1/6)^2 the time of a naive solve of
    the full Kai Zeng matrix.
    Second compute the fixed-state-only 4x4 transition matrix
    and get its stationary distribution.
    This uses the fixation probabilities computed in the first step.
    Third compute the stationary distributions of the dimorphic states
    using the stationary distributions of the fixed states
    computed in the second step.
    """
    solves = []
    # Define transition matrices within a single diallelic subspace.
    for bi, (i, j) in enumerate(combinations(range(k), 2)):
        s = 1 - fit[j] / fit[i]
        P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
        A = np.zeros((N_diploid * 2 + 1 + 2, N_diploid * 2 + 1 + 2))
        # Adjust P and put it into A.
        # Setting these values to zero causes them to act as sinks.
        P[0, 0] = 0
        P[-1, -1] = 0
        P -= np.eye(N_diploid * 2 + 1)
        A[1:-1, 1:-1] = P
        # Add some probability sources.
        A[0, 0] = 1
        A[0, 2] = 1
        A[-1, -1] = 1
        A[-1, -3] = 1
        # Define the B matrix which will hold the solve.
        # The two columns are the two directions per diallelic block.
        B = np.zeros((N_diploid * 2 + 1 + 2, 2))
        B[0, 0] = 1
        B[-1, -1] = 1
        X = linalg.solve(A.T, B)
        solves.append(X)
    # Compute the fixation probabilities from the block solutions.
    F = np.zeros((k, k))
    for bi, (i, j) in enumerate(combinations(range(k), 2)):
        X = solves[bi]
        #print X
        #print
        # Second row of X is background allele frequency.
        # Second to last row of X is mutant allele frequency.
        # First column of X is forward, second column is reverse.
        # F[i, j] is the probability of fixation of allele j
        # against the background of allele i.
        F[i, j] = X[1, 1]
        F[j, i] = X[-2, 0]
    print F
    # Compute the transition matrix among fixed states.
    # This is nearly the hadamard product of mutation and fixation.
    T = mutation * F
    T += np.eye(k) - np.diag(np.sum(T, axis=1))
    print T
    # Compute the stationary distribution among fixed states.
    v_small = MatrixUtil.get_stationary_distribution(T)
    print v_small
    # Compute dimorphic distributions using the block solutions
    # and the previously computed stuff like fixed state stationary
    # distributions, and also using the mutation probabilities.
    dtotal = v_small.tolist()
    for bi, (i, j) in enumerate(combinations(range(k), 2)):
        X = solves[bi]
        distn = np.zeros(N_diploid * 2 - 1)
        d = X.T[1][2:-2]
        distn += v_small[i] * mutation[i, j] * d
        d = X.T[0][2:-2]
        distn += v_small[j] * mutation[j, i] * d
        dtotal.extend(distn)
    #
    #print sum(sum(d) for d in distns)
    dtotal = np.array(dtotal)
    #print dtotal
    #print dtotal / np.sum(dtotal)
    return dtotal / np.sum(dtotal)
Ejemplo n.º 19
0
def get_response_content(fs):
    N_diploid = fs.N_diploid
    N = N_diploid * 2
    k = 2
    gamma = fs.gamma
    # define the fitnesses and the selection value
    f0 = 1.0
    f1 = 1.0 - gamma / N
    s = 1 - f1 / f0
    if f1 <= 0:
        raise ValueError('the extreme selection caused a non-positive fitness')
    # get a wright fisher transition matrix
    P = np.exp(wfengine.create_genic_diallelic(N_diploid, s))
    """
    # condition on no fixation
    for i in range(N):
        P[i] /= 1 - P[i, N]
    # remove the fixed state from the transition matrix
    P = P[:N, :N]
    """
    # add mutations
    P[0, 0] = 0
    P[0, 1] = 1
    P[N, N] = 0
    P[N, 1] = 1
    # compute the stationary distribution
    v = MatrixUtil.get_stationary_distribution(P)
    # get the distribution over dimorphic states
    h = v[1:-1]
    h /= np.sum(h)
    # look at continuous approximations
    w = np.zeros(N + 1)
    for i in range(1, N):
        x = i / float(N)
        #x0 = i / float(N)
        #x1 = (i + 1) / float(N)
        #value = sojourn_definite(x0, x1, gamma)
        value = sojourn_kernel(x, gamma)
        w[i] = value
    w = w[1:-1]
    w /= np.sum(w)
    # get the array for the R plot
    arr = [h.tolist(), w.tolist()]
    # define the r script
    out = StringIO()
    print >> out, 'title.string <- "allele 1 vs allele 2"'
    print >> out, 'mdat <-', RUtil.matrix_to_R_string(arr)
    print >> out, mk_call_str(
        'barplot',
        'mdat',
        'legend.text=' + mk_call_str(
            'c',
            '"exact discrete distribution"',
            '"continuous approximation"',
            #'"two-allele large N limit"',
            #'"two-allele"',
            #'"four-allele without mutational bias"',
            #'"four-allele with mutational bias (kappa_{1,2}=2)"',
            #'"four-allele with mutational bias, large N limit"',
        ),
        'args.legend = list(x="topright", bty="n")',
        'names.arg = 1:%s' % (N - 1),
        main='title.string',
        xlab='"frequency of allele 1"',
        ylab='"frequency"',
        col=mk_call_str(
            'c',
            #'"red"',
            #'"white"',
            '"black"',
            #'"gray"',
            '"red"',
        ),
        beside='TRUE',
        border='NA',
    )
    #print >> out, 'box()'
    script = out.getvalue().rstrip()
    # create the R plot image
    device_name = Form.g_imageformat_to_r_function[fs.imageformat]
    retcode, r_out, r_err, image_data = RUtil.run_plotter_no_table(
        script, device_name)
    if retcode:
        raise RUtil.RError(r_err)
    return image_data