File: MarkovModulated.hs

package info (click to toggle)
bali-phy 4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 15,392 kB
  • sloc: cpp: 120,442; xml: 13,966; haskell: 9,975; python: 2,936; yacc: 1,328; perl: 1,169; lex: 912; sh: 343; makefile: 26
file content (112 lines) | stat: -rw-r--r-- 5,044 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
module SModel.MarkovModulated where

import Foreign.Vector
import Bio.Alphabet
import SModel.ReversibleMarkov
import SModel.MixtureModel
import SModel.Rate
import qualified Markov
import Markov (getQ, getEqFreqs)
import Data.Matrix -- for fromLists, %*%

foreign import bpcall "SModel:modulated_markov_rates" builtin_modulated_markov_rates :: EVector (Matrix Double) -> Matrix Double -> Matrix Double
foreign import bpcall "SModel:modulated_markov_pi" builtin_modulated_markov_pi :: EVector (EVector Double) -> EVector Double -> EVector Double
foreign import bpcall "SModel:modulated_markov_smap" builtin_modulated_markov_smap :: EVector (EVector Int) -> EVector Int

modulatedMarkovRates qs rates_between = builtin_modulated_markov_rates (toVector qs) rates_between

modulatedMarkovPi pis levelProbs = builtin_modulated_markov_pi (toVector pis) (toVector levelProbs)

modulatedMarkovSmap smaps = builtin_modulated_markov_smap (toVector smaps)

{- NOTE: Does ratesBetween + levelProbs = GTR ?

   If so, I could pass:
   - Qs = a list of n rate matrices
   - S  = a rate matrix on n states
   Having the matrix S=GTR(ratesBetween,levelProbs) would be a special case.

   If all the Qs and the S are reversible then the whole thing should be reversible.
   QUESTION: How would we record this?
 -}

modulatedMarkov models ratesBetween levelProbs = reversible $ markov a smap q pi where
    a = getAlphabet $ head models
    qs = map getQ models
    pis = map getEqFreqs models
    smaps = map getSMap models
    q = modulatedMarkovRates qs ratesBetween
    pi = modulatedMarkovPi pis levelProbs
    smap = modulatedMarkovSmap smaps

markovModulateMixture nu dist = modulatedMarkov models ratesBetween levelProbs where
    (models, levelProbs) = unzip $ unpackDiscrete dist
    ratesBetween = Markov.equ (length models) nu

-- We need to scaleTo submodels to have substitution rate `1`.
-- Otherwise class-switching rates are not relative to the substitution rate.

tuffleySteel98Unscaled s01 s10 q = modulatedMarkov [scaleBy 0 q, q] ratesBetween levelProbs where
    levelProbs = [s10/total, s01/total] where total = s10 + s01
    ratesBetween = fromLists [[-s01,s01],[s10,-s10]]

tuffleySteel98 s01 s10 q = tuffleySteel98Unscaled s01 s10 (scaleTo 1 q)

tuffleySteel98Test s01 s10 fraction q = mix [1-fraction, fraction] [tuffleySteel98 1   0   q & unitMixture,
                                                                    tuffleySteel98 s01 s10 q & unitMixture]

huelsenbeck02 s01 s10 model = tuffleySteel98Unscaled s01 s10 <$> scaleTo 1 model

huelsenbeck02Test s01 s10 fraction model = mix [1-fraction, fraction] [model & huelsenbeck02 1 0,
                                                                       model & huelsenbeck02 s01 s10]

huelsenbeck02Two s01a s10a s01b s10b fraction model = mix [1-fraction, fraction] [model & huelsenbeck02 s01b s10b,
                                                                                  model & huelsenbeck02 s01a s10a]

galtier01Ssrv nu model = modulatedMarkov models ratesBetween levelProbs where
    dist = scaleTo 1 model
    (models, levelProbs) = unzip $ unpackDiscrete dist
    nLevels = length models
    -- This is really a generic gtr...  We should be able to get this with f81
    ratesBetween = (Markov.equ nLevels nu) %*% (plus_f_matrix $ toVector levelProbs)

galtier01 nu pi model = (\nu' -> galtier01Ssrv nu' model) <$> (Discrete [(0, 1-pi), (nu, pi)])

wssr07Ssrv s01 s10 nu model = tuffleySteel98 s01 s10 $ galtier01Ssrv nu model

wssr07 s01 s10 nu pi model = (\nu' -> wssr07Ssrv s01 s10 nu' model) <$> (Discrete [(0, 1-pi), (nu, pi)]) 

-- a -> HB02
-- b -> GT01 if no HB02
-- c -> GT01 if    HB02

-- X = (1-a)(1-b)
-- X + HB02 = a(1-c)
-- X + GT01 = (1-a)b
-- X + HB02+GT01 = a * c

wssr07Ext s01 s10 nu a b c model = Discrete [(noCov,   (1-a)*(1-b)),
                                             (gt01,    (1-a)*b),
                                             (hb02,        a*(1-c)),
                                             (hb02gt01,    a*c)]
    where noCov = wssr07Ssrv 1 0 0  model
          gt01  = wssr07Ssrv 1 0 nu model
          hb02  = wssr07Ssrv s01 s10 0 model
          hb02gt01 = wssr07Ssrv s01 s10 nu model

-- Instead of passing ratesBetween+levelProbs, could we just pass a q matrix?
covarionGtrSsrv nu exchange model = modulatedMarkov models ratesBetween levelProbs where
    Discrete dist = scaleTo 1 model
    (models, levelProbs) = unzip dist
    -- This is really a gtr rate matrix, just without the alphabet / smap!
    ratesBetween = (scaleMatrix nu exchange) %*% (plus_f_matrix $ toVector levelProbs)

covarionGtr nu exchange pi model = (\nu' -> covarionGtrSsrv nu' exchange model) <$> (Discrete [(0,1-pi), (nu, pi)])

covarionGtrSym :: Matrix Double -> Discrete ReversibleMarkov -> ReversibleMarkov
covarionGtrSym sym model = modulatedMarkov models ratesBetween levelProbs where
    dist = scaleTo 1 model
    (models, levelProbs) = unzip $ unpackDiscrete dist
    ratesBetween = sym %*% (plus_f_matrix $ toVector levelProbs)