elynx-markov 0.7.1.0 → 0.7.2.0
raw patch · 12 files changed
+82/−45 lines, 12 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ ELynx.MarkovProcess.SubstitutionModel: DoNormalize :: Normalize
+ ELynx.MarkovProcess.SubstitutionModel: DoNotNormalize :: Normalize
+ ELynx.MarkovProcess.SubstitutionModel: data Normalize
+ ELynx.MarkovProcess.SubstitutionModel: instance GHC.Classes.Eq ELynx.MarkovProcess.SubstitutionModel.Normalize
+ ELynx.MarkovProcess.SubstitutionModel: instance GHC.Read.Read ELynx.MarkovProcess.SubstitutionModel.Normalize
+ ELynx.MarkovProcess.SubstitutionModel: instance GHC.Show.Show ELynx.MarkovProcess.SubstitutionModel.Normalize
- ELynx.MarkovProcess.AminoAcid: gtr20 :: [Double] -> StationaryDistribution -> SubstitutionModel
+ ELynx.MarkovProcess.AminoAcid: gtr20 :: Normalize -> [Double] -> StationaryDistribution -> SubstitutionModel
- ELynx.MarkovProcess.AminoAcid: lg :: SubstitutionModel
+ ELynx.MarkovProcess.AminoAcid: lg :: Normalize -> SubstitutionModel
- ELynx.MarkovProcess.AminoAcid: lgCustom :: Maybe String -> StationaryDistribution -> SubstitutionModel
+ ELynx.MarkovProcess.AminoAcid: lgCustom :: Maybe String -> Normalize -> StationaryDistribution -> SubstitutionModel
- ELynx.MarkovProcess.AminoAcid: poisson :: SubstitutionModel
+ ELynx.MarkovProcess.AminoAcid: poisson :: Normalize -> SubstitutionModel
- ELynx.MarkovProcess.AminoAcid: poissonCustom :: Maybe String -> StationaryDistribution -> SubstitutionModel
+ ELynx.MarkovProcess.AminoAcid: poissonCustom :: Maybe String -> Normalize -> StationaryDistribution -> SubstitutionModel
- ELynx.MarkovProcess.AminoAcid: wag :: SubstitutionModel
+ ELynx.MarkovProcess.AminoAcid: wag :: Normalize -> SubstitutionModel
- ELynx.MarkovProcess.AminoAcid: wagCustom :: Maybe String -> StationaryDistribution -> SubstitutionModel
+ ELynx.MarkovProcess.AminoAcid: wagCustom :: Maybe String -> Normalize -> StationaryDistribution -> SubstitutionModel
- ELynx.MarkovProcess.MixtureModel: fromSubstitutionModels :: Name -> Vector Weight -> Vector SubstitutionModel -> MixtureModel
+ ELynx.MarkovProcess.MixtureModel: fromSubstitutionModels :: Name -> Normalize -> Vector Weight -> Vector SubstitutionModel -> MixtureModel
- ELynx.MarkovProcess.Nucleotide: f81 :: StationaryDistribution -> SubstitutionModel
+ ELynx.MarkovProcess.Nucleotide: f81 :: Normalize -> StationaryDistribution -> SubstitutionModel
- ELynx.MarkovProcess.Nucleotide: gtr4 :: [Double] -> StationaryDistribution -> SubstitutionModel
+ ELynx.MarkovProcess.Nucleotide: gtr4 :: Normalize -> [Double] -> StationaryDistribution -> SubstitutionModel
- ELynx.MarkovProcess.Nucleotide: hky :: Double -> StationaryDistribution -> SubstitutionModel
+ ELynx.MarkovProcess.Nucleotide: hky :: Normalize -> Double -> StationaryDistribution -> SubstitutionModel
- ELynx.MarkovProcess.Nucleotide: jc :: SubstitutionModel
+ ELynx.MarkovProcess.Nucleotide: jc :: Normalize -> SubstitutionModel
- ELynx.MarkovProcess.SubstitutionModel: substitutionModel :: Alphabet -> Name -> Params -> StationaryDistribution -> ExchangeabilityMatrix -> SubstitutionModel
+ ELynx.MarkovProcess.SubstitutionModel: substitutionModel :: Alphabet -> Name -> Params -> Normalize -> StationaryDistribution -> ExchangeabilityMatrix -> SubstitutionModel
Files
- ChangeLog.md +5/−0
- README.md +4/−4
- elynx-markov.cabal +1/−1
- src/ELynx/MarkovProcess/AminoAcid.hs +14/−14
- src/ELynx/MarkovProcess/CXXModels.hs +2/−0
- src/ELynx/MarkovProcess/GammaRateHeterogeneity.hs +3/−5
- src/ELynx/MarkovProcess/MixtureModel.hs +22/−4
- src/ELynx/MarkovProcess/Nucleotide.hs +8/−8
- src/ELynx/MarkovProcess/SubstitutionModel.hs +12/−2
- test/ELynx/MarkovProcess/AminoAcidSpec.hs +7/−4
- test/ELynx/MarkovProcess/NucleotideSpec.hs +1/−1
- test/ELynx/Simulate/MarkovProcessAlongTreeSpec.hs +3/−2
ChangeLog.md view
@@ -5,6 +5,11 @@ ## Unreleased changes +## Version 0.7.2.0++- `slynx`: Allow global normalization of mixture models.++ ## Version 0.7.1.0 - Be less strict with quoted identifiers/names in phylogenetic trees.
README.md view
@@ -2,7 +2,7 @@ # The ELynx Suite -Version: 0.7.0.0.+Version: 0.7.2.0. Reproducible evolution made easy. <p align="center"><img src="https://travis-ci.org/dschrempf/elynx.svg?branch=master"/></p>@@ -73,13 +73,13 @@ # OR: stack exec slynx -- --help # OR: slynx --help - Up to date- ELynx Suite version 0.7.0.0.+ ELynx Suite version 0.7.2.0. Developed by Dominik Schrempf.- Compiled on July 10, 2022, at 08:48 am, UTC.+ Compiled on May 3, 2023, at 13:18 pm, UTC. Usage: slynx [-v|--verbosity VALUE] [-o|--output-file-basename NAME] [-f|--force] [--no-elynx-file] COMMAND+ Analyze, and simulate multi sequence alignments. Available options:
elynx-markov.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: elynx-markov-version: 0.7.1.0+version: 0.7.2.0 synopsis: Simulate molecular sequences along trees description: Examine, modify, and simulate molecular sequences in a reproducible way. Please see the README on GitHub at <https://github.com/dschrempf/elynx>.
src/ELynx/MarkovProcess/AminoAcid.hs view
@@ -368,12 +368,12 @@ lgStatDist = pamlToAlphaVec lgStatDistPaml -- | LG substitution model.-lg :: SubstitutionModel-lg = substitutionModel Protein "LG" [] lgStatDist lgExch+lg :: Normalize -> SubstitutionModel+lg nz = substitutionModel Protein "LG" [] nz lgStatDist lgExch -- | LG substitution model with maybe a name and a custom stationary distribution.-lgCustom :: Maybe String -> StationaryDistribution -> SubstitutionModel-lgCustom mnm d = substitutionModel Protein nm [] d lgExch+lgCustom :: Maybe String -> Normalize -> StationaryDistribution -> SubstitutionModel+lgCustom mnm nz d = substitutionModel Protein nm [] nz d lgExch where nm = fromMaybe "LG-Custom" mnm @@ -608,12 +608,12 @@ wagStatDist = pamlToAlphaVec wagStatDistPaml -- | LG substitution model.-wag :: SubstitutionModel-wag = substitutionModel Protein "WAG" [] wagStatDist wagExch+wag :: Normalize -> SubstitutionModel+wag nz = substitutionModel Protein "WAG" [] nz wagStatDist wagExch -- | LG substitution model with maybe a name and a custom stationary distribution.-wagCustom :: Maybe String -> StationaryDistribution -> SubstitutionModel-wagCustom mnm d = substitutionModel Protein nm [] d wagExch+wagCustom :: Maybe String -> Normalize -> StationaryDistribution -> SubstitutionModel+wagCustom mnm nz d = substitutionModel Protein nm [] nz d wagExch where nm = fromMaybe "WAG-Custom" mnm @@ -631,17 +631,17 @@ uniformVec = V.replicate n (1 / fromIntegral n) -- | Poisson substitution model.-poisson :: SubstitutionModel-poisson = substitutionModel Protein "Poisson" [] uniformVec poissonExch+poisson :: Normalize -> SubstitutionModel+poisson nz = substitutionModel Protein "Poisson" [] nz uniformVec poissonExch -- | Poisson substitution model with maybe a name and a custom stationary distribution.-poissonCustom :: Maybe String -> StationaryDistribution -> SubstitutionModel-poissonCustom mnm d = substitutionModel Protein nm [] d poissonExch+poissonCustom :: Maybe String -> Normalize -> StationaryDistribution -> SubstitutionModel+poissonCustom mnm nz d = substitutionModel Protein nm [] nz d poissonExch where nm = fromMaybe "Poisson-Custom" mnm -- | General time reversible (GTR) substitution model for amino acids.-gtr20 :: [Double] -> StationaryDistribution -> SubstitutionModel-gtr20 es d = substitutionModel Protein "GTR" es d e+gtr20 :: Normalize -> [Double] -> StationaryDistribution -> SubstitutionModel+gtr20 nz es d = substitutionModel Protein "GTR" es nz d e where e = exchFromListUpper n es
src/ELynx/MarkovProcess/CXXModels.hs view
@@ -117,6 +117,7 @@ cxxSubstitutionModelFromStatDist nComps comp d = poissonCustom (Just name)+ S.DoNotNormalize (normalizeSD d) where name = componentName nComps comp@@ -139,6 +140,7 @@ cxxFromStatDistsAndWeights ws ds = M.fromSubstitutionModels (cxxName n)+ S.DoNormalize (V.fromList ws) sms where
src/ELynx/MarkovProcess/GammaRateHeterogeneity.hs view
@@ -58,8 +58,7 @@ ++ "shape parameter " ++ show alpha -splitSubstitutionModel ::- Int -> Double -> S.SubstitutionModel -> V.Vector S.SubstitutionModel+splitSubstitutionModel :: Int -> Double -> S.SubstitutionModel -> V.Vector S.SubstitutionModel splitSubstitutionModel n alpha sm = renamedSMs where means = getMeans n alpha@@ -67,9 +66,8 @@ names = V.fromList $ map (("; gamma rate category " ++) . show) [1 :: Int ..] renamedSMs = V.zipWith S.appendName names scaledSMs -expandSubstitutionModel ::- Int -> Double -> S.SubstitutionModel -> M.MixtureModel-expandSubstitutionModel n alpha sm = M.fromSubstitutionModels name ws sms+expandSubstitutionModel :: Int -> Double -> S.SubstitutionModel -> M.MixtureModel+expandSubstitutionModel n alpha sm = M.fromSubstitutionModels name S.DoNotNormalize ws sms where name = S.name sm <> getName n alpha ws = V.replicate n 1.0
src/ELynx/MarkovProcess/MixtureModel.hs view
@@ -64,15 +64,33 @@ getSubstitutionModels :: MixtureModel -> V.Vector S.SubstitutionModel getSubstitutionModels = V.map substModel . components +normalizeGlobally :: V.Vector Weight -> V.Vector S.SubstitutionModel -> V.Vector S.SubstitutionModel+normalizeGlobally ws ss = V.map (S.scale $ recip c) ss+ where+ cks = V.map S.totalRate ss+ cNoWeights = V.sum $ V.zipWith (*) ws cks+ c = cNoWeights / V.sum ws+ -- | Create a mixture model from a list of substitution models.-fromSubstitutionModels :: S.Name -> V.Vector Weight -> V.Vector S.SubstitutionModel -> MixtureModel-fromSubstitutionModels n ws sms+--+-- If 'S.Normalize' is 'S.DoNormalize', globally normalize the mixture model.+-- Global normalization has no effect if all components are already normalized.+fromSubstitutionModels ::+ S.Name ->+ S.Normalize ->+ V.Vector Weight ->+ V.Vector S.SubstitutionModel ->+ MixtureModel+fromSubstitutionModels n nz ws sms | null ws = error "fromSubstitutionModels: No weights given." | length ws /= length sms = error "fromSubstitutionModels: Number of weights and substitution models does not match." | not $ allEqual alphs = error "fromSubstitutionModels: alphabets of substitution models are not equal." | otherwise = MixtureModel n (V.head alphs) comps where- comps = V.zipWith Component ws sms+ smsNormalized = case nz of+ S.DoNormalize -> normalizeGlobally ws sms+ S.DoNotNormalize -> sms+ comps = V.zipWith Component ws smsNormalized alphs = V.map S.alphabet sms allEqual xs | V.null xs = True@@ -80,7 +98,7 @@ -- | Concatenate mixture models. concatenate :: S.Name -> V.Vector MixtureModel -> MixtureModel-concatenate n mms = fromSubstitutionModels n ws sms+concatenate n mms = fromSubstitutionModels n S.DoNotNormalize ws sms where comps = V.concatMap components mms ws = V.map weight comps
src/ELynx/MarkovProcess/Nucleotide.hs view
@@ -81,12 +81,12 @@ uniformVec = V.replicate n (1 / fromIntegral n) -- | JC substitution model.-jc :: SubstitutionModel-jc = substitutionModel DNA "JC" [] uniformVec jcExch+jc :: Normalize -> SubstitutionModel+jc nz = substitutionModel DNA "JC" [] nz uniformVec jcExch -- | F81 substitution model.-f81 :: StationaryDistribution -> SubstitutionModel-f81 d = substitutionModel DNA "F81" [] d jcExch+f81 :: Normalize -> StationaryDistribution -> SubstitutionModel+f81 nz d = substitutionModel DNA "F81" [] nz d jcExch hkyExch :: Double -> ExchangeabilityMatrix hkyExch k =@@ -94,11 +94,11 @@ [0.0, 1.0, k, 1.0, 1.0, 0.0, 1.0, k, k, 1.0, 0.0, 1.0, 1.0, k, 1.0, 0.0] -- | HKY substitution model.-hky :: Double -> StationaryDistribution -> SubstitutionModel-hky k d = substitutionModel DNA "HKY" [k] d e where e = hkyExch k+hky :: Normalize -> Double -> StationaryDistribution -> SubstitutionModel+hky nz k d = substitutionModel DNA "HKY" [k] nz d e where e = hkyExch k -- | HKY substitution model.-gtr4 :: [Double] -> StationaryDistribution -> SubstitutionModel-gtr4 es d = substitutionModel DNA "GTR" es d e+gtr4 :: Normalize -> [Double] -> StationaryDistribution -> SubstitutionModel+gtr4 nz es d = substitutionModel DNA "GTR" es nz d e where e = exchFromListUpper n es
src/ELynx/MarkovProcess/SubstitutionModel.hs view
@@ -27,6 +27,7 @@ totalRate, -- * Building substitution models+ Normalize (..), substitutionModel, -- * Transformations@@ -92,17 +93,26 @@ s = V.sum v {-# INLINE normalizeSumVec #-} +-- | Should the substitution model be normalized?+data Normalize = DoNormalize | DoNotNormalize+ deriving (Show, Read, Eq)+ -- | Create normalized 'SubstitutionModel'. See 'normalize'. substitutionModel :: Alphabet -> Name -> Params ->+ Normalize -> R.StationaryDistribution -> R.ExchangeabilityMatrix -> SubstitutionModel-substitutionModel c n ps d e =+substitutionModel c n ps nz d e = if R.isValid d- then normalize $ SubstitutionModel c n ps (normalizeSumVec d) e+ then+ let sm = SubstitutionModel c n ps (normalizeSumVec d) e+ in case nz of+ DoNormalize -> normalize sm+ DoNotNormalize -> sm else error $ "substitionModel: Stationary distribution does not sum to 1.0: "
test/ELynx/MarkovProcess/AminoAcidSpec.hs view
@@ -16,6 +16,7 @@ import qualified Data.Vector.Storable as V import ELynx.MarkovProcess.AminoAcid import qualified ELynx.MarkovProcess.RateMatrix as R+import ELynx.MarkovProcess.SubstitutionModel (Normalize (DoNormalize)) import qualified ELynx.MarkovProcess.SubstitutionModel as S import ELynx.Tools.Equality import Numeric.LinearAlgebra@@ -482,13 +483,13 @@ statDistUniform = vector $ replicate 20 0.05 statDistLG :: R.StationaryDistribution-statDistLG = S.stationaryDistribution lg+statDistLG = S.stationaryDistribution $ lg DoNormalize exchLG :: R.ExchangeabilityMatrix-exchLG = S.exchangeabilityMatrix lg+exchLG = S.exchangeabilityMatrix $ lg DoNormalize rmLG :: R.RateMatrix-rmLG = S.rateMatrix lg+rmLG = S.rateMatrix $ lg DoNormalize spec :: Spec spec = do@@ -513,11 +514,12 @@ S.rateMatrix $ lgCustom Nothing+ DoNormalize statDistUniform f `nearlyEqVec` statDistUniform `shouldBe` True describe "poisson" $ it "stationary distribution is uniform 1/20" $- R.getStationaryDistribution (S.rateMatrix poisson)+ R.getStationaryDistribution (S.rateMatrix $ poisson DoNormalize) `nearlyEqVec` statDistUniform `shouldBe` True describe "poissonCustom" $@@ -527,5 +529,6 @@ S.rateMatrix $ poissonCustom Nothing+ DoNormalize statDistLGPython f `nearlyEqVec` statDistLGPython `shouldBe` True
test/ELynx/MarkovProcess/NucleotideSpec.hs view
@@ -24,7 +24,7 @@ stationaryDist = fromList [0.2, 0.3, 0.3, 0.2] hkyModel :: SubstitutionModel-hkyModel = hky 6.0 stationaryDist+hkyModel = hky DoNormalize 6.0 stationaryDist spec :: Spec spec =
test/ELynx/Simulate/MarkovProcessAlongTreeSpec.hs view
@@ -15,6 +15,7 @@ import Data.Tree import ELynx.MarkovProcess.Nucleotide+import ELynx.MarkovProcess.SubstitutionModel (Normalize (DoNormalize)) import qualified ELynx.MarkovProcess.SubstitutionModel as S import ELynx.Simulate.MarkovProcess import ELynx.Simulate.MarkovProcessAlongTree@@ -50,5 +51,5 @@ tr <- simulate 10 d e testTree gen (length . rootLabel $ tr) `shouldBe` 10 where- d = S.stationaryDistribution jc- e = S.exchangeabilityMatrix jc+ d = S.stationaryDistribution $ jc DoNormalize+ e = S.exchangeabilityMatrix $ jc DoNormalize