elynx-tree 0.6.1.1 → 0.7.0.1
raw patch · 51 files changed
+469/−341 lines, 51 filesdep +randomdep −mwc-randomdep −primitivePVP ok
version bump matches the API change (PVP)
Dependencies added: random
Dependencies removed: mwc-random, primitive
API changes (from Hackage documentation)
+ ELynx.Tree.Mrca: findNode :: (Ord a, Show a) => a -> Tree e a -> Either String (Set a)
+ ELynx.Tree.Mrca: getPathToMrca :: (Ord a, Show a) => Set a -> Tree e a -> Either String Path
+ ELynx.Tree.Mrca: getTreeAtMrca :: (Ord a, Show a) => Set a -> Tree e a -> Either String (Tree e a)
+ ELynx.Tree.Mrca: isAncestor :: Ord a => Set a -> Tree e a -> Bool
+ ELynx.Tree.Mrca: isMrca :: Ord a => Set a -> Tree e a -> Bool
+ ELynx.Tree.Rooted: duplicateLabels :: Ord a => Tree e a -> Bool
- ELynx.Tree.Simulate.Coalescent: simulate :: PrimMonad m => Int -> Gen (PrimState m) -> m (Tree Length Int)
+ ELynx.Tree.Simulate.Coalescent: simulate :: StatefulGen g m => Int -> g -> m (Tree Length Int)
- ELynx.Tree.Simulate.PointProcess: simulate :: PrimMonad m => Int -> TimeSpec -> Rate -> Rate -> Gen (PrimState m) -> m (PointProcess Int Double)
+ ELynx.Tree.Simulate.PointProcess: simulate :: StatefulGen g m => Int -> TimeSpec -> Rate -> Rate -> g -> m (PointProcess Int Double)
- ELynx.Tree.Simulate.PointProcess: simulateNReconstructedTrees :: PrimMonad m => Int -> Int -> TimeSpec -> Rate -> Rate -> Gen (PrimState m) -> m (Forest Length Int)
+ ELynx.Tree.Simulate.PointProcess: simulateNReconstructedTrees :: StatefulGen g m => Int -> Int -> TimeSpec -> Rate -> Rate -> g -> m (Forest Length Int)
- ELynx.Tree.Simulate.PointProcess: simulateReconstructedTree :: PrimMonad m => Int -> TimeSpec -> Rate -> Rate -> Gen (PrimState m) -> m (Tree Length Int)
+ ELynx.Tree.Simulate.PointProcess: simulateReconstructedTree :: StatefulGen g m => Int -> TimeSpec -> Rate -> Rate -> g -> m (Tree Length Int)
Files
- ChangeLog.md +8/−1
- README.md +7/−8
- bench/Bench.hs +3/−3
- bench/Length.hs +1/−1
- bench/Lens.hs +1/−1
- bench/Tree.hs +1/−1
- elynx-tree.cabal +112/−105
- src/ELynx/Topology.hs +1/−1
- src/ELynx/Topology/Phylogeny.hs +3/−3
- src/ELynx/Topology/Rooted.hs +1/−1
- src/ELynx/Tree.hs +5/−1
- src/ELynx/Tree/Bipartition.hs +6/−6
- src/ELynx/Tree/Distance.hs +26/−26
- src/ELynx/Tree/Distribution/BirthDeath.hs +11/−11
- src/ELynx/Tree/Distribution/BirthDeathCritical.hs +6/−6
- src/ELynx/Tree/Distribution/BirthDeathCriticalNoTime.hs +3/−3
- src/ELynx/Tree/Distribution/BirthDeathNearlyCritical.hs +16/−16
- src/ELynx/Tree/Distribution/CoalescentContinuous.hs +1/−1
- src/ELynx/Tree/Distribution/TimeOfOrigin.hs +8/−8
- src/ELynx/Tree/Distribution/TimeOfOriginNearCritical.hs +7/−7
- src/ELynx/Tree/Distribution/Types.hs +1/−1
- src/ELynx/Tree/Export/Newick.hs +1/−1
- src/ELynx/Tree/Export/Nexus.hs +1/−1
- src/ELynx/Tree/Import/Newick.hs +3/−2
- src/ELynx/Tree/Import/Nexus.hs +1/−1
- src/ELynx/Tree/Length.hs +1/−1
- src/ELynx/Tree/Mrca.hs +112/−0
- src/ELynx/Tree/Name.hs +1/−1
- src/ELynx/Tree/Parallel.hs +5/−5
- src/ELynx/Tree/Partition.hs +3/−3
- src/ELynx/Tree/Phylogeny.hs +8/−8
- src/ELynx/Tree/Rooted.hs +9/−4
- src/ELynx/Tree/Simulate/Coalescent.hs +18/−19
- src/ELynx/Tree/Simulate/PointProcess.hs +48/−54
- src/ELynx/Tree/Splittable.hs +1/−1
- src/ELynx/Tree/Support.hs +1/−1
- src/ELynx/Tree/Zipper.hs +14/−14
- test/ELynx/ClassLaws.hs +1/−1
- test/ELynx/Topology/Arbitrary.hs +1/−1
- test/ELynx/Topology/RootedSpec.hs +1/−1
- test/ELynx/Tree/Arbitrary.hs +1/−1
- test/ELynx/Tree/BipartitionSpec.hs +1/−1
- test/ELynx/Tree/DistanceSpec.hs +1/−1
- test/ELynx/Tree/Export/NewickSpec.hs +1/−1
- test/ELynx/Tree/Export/NexusSpec.hs +1/−1
- test/ELynx/Tree/Import/NewickSpec.hs +1/−1
- test/ELynx/Tree/Import/NexusSpec.hs +1/−1
- test/ELynx/Tree/PartitionSpec.hs +1/−1
- test/ELynx/Tree/PhylogenySpec.hs +1/−1
- test/ELynx/Tree/RootedSpec.hs +1/−1
- test/ELynx/Tree/SupportSpec.hs +1/−1
ChangeLog.md view
@@ -5,9 +5,16 @@ ## Unreleased changes +## Version 0.7.0.1++- Random 1.2: Parallel functions now require an \`IOGenM\` random number+ generator.+- Fix splitting of the random number generator.++ ## Version 0.6.1.1 -- Remove plotting functionality (gnuplot incompatible with ghc921).+- Remove plotting functionality (gnuplot incompatible with ghc922). - Read files strictly. - Refactor; flatten model hierarchy.
README.md view
@@ -2,7 +2,7 @@ # The ELynx Suite -Version: 0.6.1.1.+Version: 0.7.0.0. Reproducible evolution made easy. <p align="center"><img src="https://travis-ci.org/dschrempf/elynx.svg?branch=master"/></p>@@ -74,9 +74,9 @@ # OR: slynx --help Up to date- ELynx Suite version 0.6.1.1.+ ELynx Suite version 0.7.0.0. Developed by Dominik Schrempf.- Compiled on February 22, 2022, at 15:10 pm, UTC.+ Compiled on July 10, 2022, at 08:48 am, UTC. Usage: slynx [-v|--verbosity VALUE] [-o|--output-file-basename NAME] [-f|--force] [--no-elynx-file] COMMAND@@ -144,16 +144,16 @@ # OR: slynx simulate --help Up to date- ELynx Suite version 0.6.1.1.+ ELynx Suite version 0.7.0.0. Developed by Dominik Schrempf.- Compiled on February 22, 2022, at 15:10 pm, UTC.+ Compiled on July 10, 2022, at 08:48 am, UTC. Usage: slynx simulate (-t|--tree-file Name) [-s|--substitution-model MODEL] [-m|--mixture-model MODEL] [-e|--edm-file NAME] [-p|--siteprofile-files NAMES] [-w|--mixture-model-weights "[DOUBLE,DOUBLE,...]"] [-g|--gamma-rate-heterogeneity "(NCAT,SHAPE)"]- (-l|--length NUMBER) [-S|--seed [INT]]+ (-l|--length NUMBER) [-S|--seed INT] Simulate multi sequence alignments. Available options:@@ -175,8 +175,7 @@ -g,--gamma-rate-heterogeneity "(NCAT,SHAPE)" Number of gamma rate categories and shape parameter -l,--length NUMBER Set alignment length to NUMBER- -S,--seed [INT] Seed for random number generator; list of 32 bit- integers with up to 256 elements (default: random)+ -S,--seed INT Seed for random number generator (default: random) -h,--help Show this help text Substitution models:
bench/Bench.hs view
@@ -3,7 +3,7 @@ -- | -- Module : Bench -- Description : Various benchmarks--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -22,7 +22,7 @@ import ELynx.Tree.Simulate.PointProcess import Length import Lens-import System.Random.MWC+import System.Random.Stateful import Tree treeFileMany :: FilePath@@ -32,7 +32,7 @@ getManyTrees = parseFileWith (someNewick Standard) treeFileMany hugeTree :: IO (Tree Length Int)-hugeTree = create >>= simulateReconstructedTree 50000 Random 1.0 0.9+hugeTree = newIOGenM (mkStdGen 0) >>= simulateReconstructedTree 50000 Random 1.0 0.9 sinN :: Int -> Length -> Length sinN n x = iterate sin x !! n
bench/Length.hs view
@@ -1,7 +1,7 @@ -- | -- Module : Length -- Description : Benchmark length newtype--- Copyright : (c) Dominik Schrempf, 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
bench/Lens.hs view
@@ -1,7 +1,7 @@ -- | -- Module : Lens -- Description : Benchmark lens operations--- Copyright : (c) Dominik Schrempf, 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
bench/Tree.hs view
@@ -1,7 +1,7 @@ -- | -- Module : Tree -- Description : Benchmark some tree algorithms--- Copyright : (c) 2021 Dominik Schrempf+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
elynx-tree.cabal view
@@ -1,81 +1,82 @@-cabal-version: 3.0-name: elynx-tree-version: 0.6.1.1-synopsis: Handle phylogenetic trees-description: Examine, compare, and simulate phylogenetic trees in a reproducible way. Please see the README on GitHub at <https://github.com/dschrempf/elynx>.-category: Bioinformatics-homepage: https://github.com/dschrempf/elynx#readme-bug-reports: https://github.com/dschrempf/elynx/issues-author: Dominik Schrempf-maintainer: dominik.schrempf@gmail.com-copyright: Dominik Schrempf (2021)-license: GPL-3.0-or-later-license-file: LICENSE-build-type: Simple+cabal-version: 3.0+name: elynx-tree+version: 0.7.0.1+synopsis: Handle phylogenetic trees+description:+ Examine, compare, and simulate phylogenetic trees in a reproducible way. Please see the README on GitHub at <https://github.com/dschrempf/elynx>. +category: Bioinformatics+homepage: https://github.com/dschrempf/elynx#readme+bug-reports: https://github.com/dschrempf/elynx/issues+author: Dominik Schrempf+maintainer: dominik.schrempf@gmail.com+copyright: 2021 Dominik Schrempf+license: GPL-3.0-or-later+license-file: LICENSE+build-type: Simple extra-source-files:- README.md- ChangeLog.md- data/ConnectA.tree- data/ConnectB.tree- data/ConnectConstraints.tree- data/Many.trees- data/MicrospoEDM32.tree- data/MicrospoEDM64.tree- data/MicrospoPoisson.tree- data/Multifurcating.tree- data/NewickConstraint.tree- data/NewickRevBayes.tree- data/NewickRooted.tree- data/Newick.tree- data/RevBayes.trees- data/SimpleTree.nex- data/TreeDist.trees- data/UltraMetric.tree+ ChangeLog.md+ data/ConnectA.tree+ data/ConnectB.tree+ data/ConnectConstraints.tree+ data/Many.trees+ data/MicrospoEDM32.tree+ data/MicrospoEDM64.tree+ data/MicrospoPoisson.tree+ data/Multifurcating.tree+ data/Newick.tree+ data/NewickConstraint.tree+ data/NewickRevBayes.tree+ data/NewickRooted.tree+ data/RevBayes.trees+ data/SimpleTree.nex+ data/TreeDist.trees+ data/UltraMetric.tree+ README.md source-repository head- type: git+ type: git location: https://github.com/dschrempf/elynx library exposed-modules:- ELynx.Topology- ELynx.Topology.Phylogeny- ELynx.Topology.Rooted- ELynx.Tree- ELynx.Tree.Bipartition- ELynx.Tree.Distance- ELynx.Tree.Length- ELynx.Tree.Name- ELynx.Tree.Parallel- ELynx.Tree.Partition- ELynx.Tree.Phylogeny- ELynx.Tree.Rooted- ELynx.Tree.Splittable- ELynx.Tree.Support- ELynx.Tree.Zipper- ELynx.Tree.Distribution.BirthDeath- ELynx.Tree.Distribution.BirthDeathCritical- ELynx.Tree.Distribution.BirthDeathCriticalNoTime- ELynx.Tree.Distribution.BirthDeathNearlyCritical- ELynx.Tree.Distribution.CoalescentContinuous- ELynx.Tree.Distribution.TimeOfOrigin- ELynx.Tree.Distribution.TimeOfOriginNearCritical- ELynx.Tree.Distribution.Types- ELynx.Tree.Export.Newick- ELynx.Tree.Export.Nexus- ELynx.Tree.Import.Newick- ELynx.Tree.Import.Nexus- ELynx.Tree.Simulate.Coalescent- ELynx.Tree.Simulate.PointProcess- other-modules:- Paths_elynx_tree- autogen-modules:- Paths_elynx_tree- hs-source-dirs: src- ghc-options: -Wall -Wunused-packages+ ELynx.Topology+ ELynx.Topology.Phylogeny+ ELynx.Topology.Rooted+ ELynx.Tree+ ELynx.Tree.Bipartition+ ELynx.Tree.Distance+ ELynx.Tree.Distribution.BirthDeath+ ELynx.Tree.Distribution.BirthDeathCritical+ ELynx.Tree.Distribution.BirthDeathCriticalNoTime+ ELynx.Tree.Distribution.BirthDeathNearlyCritical+ ELynx.Tree.Distribution.CoalescentContinuous+ ELynx.Tree.Distribution.TimeOfOrigin+ ELynx.Tree.Distribution.TimeOfOriginNearCritical+ ELynx.Tree.Distribution.Types+ ELynx.Tree.Export.Newick+ ELynx.Tree.Export.Nexus+ ELynx.Tree.Import.Newick+ ELynx.Tree.Import.Nexus+ ELynx.Tree.Length+ ELynx.Tree.Mrca+ ELynx.Tree.Name+ ELynx.Tree.Parallel+ ELynx.Tree.Partition+ ELynx.Tree.Phylogeny+ ELynx.Tree.Rooted+ ELynx.Tree.Simulate.Coalescent+ ELynx.Tree.Simulate.PointProcess+ ELynx.Tree.Splittable+ ELynx.Tree.Support+ ELynx.Tree.Zipper++ other-modules: Paths_elynx_tree+ autogen-modules: Paths_elynx_tree+ hs-source-dirs: src+ ghc-options: -Wall -Wunused-packages build-depends:- aeson+ , aeson , attoparsec , base , bytestring@@ -86,37 +87,39 @@ , double-conversion , elynx-nexus , math-functions- , mwc-random , parallel- , primitive+ , random , statistics+ default-language: Haskell2010 test-suite tree-test- type: exitcode-stdio-1.0- main-is: Spec.hs+ type: exitcode-stdio-1.0+ main-is: Spec.hs other-modules:- ELynx.ClassLaws- ELynx.Topology.Arbitrary- ELynx.Topology.RootedSpec- ELynx.Tree.Arbitrary- ELynx.Tree.BipartitionSpec- ELynx.Tree.DistanceSpec- ELynx.Tree.PartitionSpec- ELynx.Tree.PhylogenySpec- ELynx.Tree.RootedSpec- ELynx.Tree.SupportSpec- ELynx.Tree.Export.NewickSpec- ELynx.Tree.Export.NexusSpec- ELynx.Tree.Import.NewickSpec- ELynx.Tree.Import.NexusSpec- Paths_elynx_tree- autogen-modules:- Paths_elynx_tree- hs-source-dirs: test- ghc-options: -Wall -Wunused-packages -threaded -rtsopts -with-rtsopts=-N+ ELynx.ClassLaws+ ELynx.Topology.Arbitrary+ ELynx.Topology.RootedSpec+ ELynx.Tree.Arbitrary+ ELynx.Tree.BipartitionSpec+ ELynx.Tree.DistanceSpec+ ELynx.Tree.Export.NewickSpec+ ELynx.Tree.Export.NexusSpec+ ELynx.Tree.Import.NewickSpec+ ELynx.Tree.Import.NexusSpec+ ELynx.Tree.PartitionSpec+ ELynx.Tree.PhylogenySpec+ ELynx.Tree.RootedSpec+ ELynx.Tree.SupportSpec+ Paths_elynx_tree++ autogen-modules: Paths_elynx_tree+ hs-source-dirs: test+ ghc-options:+ -Wall -Wunused-packages -threaded -rtsopts -with-rtsopts=-N+ build-depends:- attoparsec+ , attoparsec , base , bytestring , containers@@ -126,26 +129,30 @@ , hspec , QuickCheck , quickcheck-classes+ default-language: Haskell2010 benchmark tree-bench- type: exitcode-stdio-1.0- main-is: Bench.hs+ type: exitcode-stdio-1.0+ main-is: Bench.hs other-modules:- Length- Lens- Tree- Paths_elynx_tree- autogen-modules:- Paths_elynx_tree- hs-source-dirs: bench- ghc-options: -Wall -Wunused-packages -threaded -rtsopts -with-rtsopts=-N+ Length+ Lens+ Paths_elynx_tree+ Tree++ autogen-modules: Paths_elynx_tree+ hs-source-dirs: bench+ ghc-options:+ -Wall -Wunused-packages -threaded -rtsopts -with-rtsopts=-N+ build-depends:- base >=4.7 && <5+ , base >=4.7 && <5 , criterion , elynx-tools , elynx-tree , microlens- , mwc-random , parallel+ , random+ default-language: Haskell2010
src/ELynx/Topology.hs view
@@ -1,7 +1,7 @@ -- | -- Module : ELynx.Topology -- Description : Rooted topologies--- Copyright : (c) Dominik Schrempf, 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
src/ELynx/Topology/Phylogeny.hs view
@@ -1,7 +1,7 @@ -- | -- Module : ELynx.Topology.Phylogeny -- Description : Phylogenetic topologies--- Copyright : (c) Dominik Schrempf, 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -66,8 +66,8 @@ intersect ts | S.null lvsCommon = Left "intersect: Intersection of leaves is empty." | otherwise = case sequence [dropLeavesWith (predicate ls) t | (ls, t) <- zip leavesToDrop ts] of- Nothing -> Left "intersect: A topology is empty."- Just ts' -> Right ts'+ Nothing -> Left "intersect: A topology is empty."+ Just ts' -> Right ts' where -- Leaf sets. lvss = map (S.fromList . leaves) ts
src/ELynx/Topology/Rooted.hs view
@@ -4,7 +4,7 @@ -- | -- Module : ELynx.Topology.Rooted -- Description : Topologies--- Copyright : (c) Dominik Schrempf, 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
src/ELynx/Tree.hs view
@@ -1,7 +1,7 @@ -- | -- Module : ELynx.Tree -- Description : Rooted trees--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -32,6 +32,9 @@ -- * Phylogenies module ELynx.Tree.Phylogeny, + -- * Most recent common ancestors+ module ELynx.Tree.Mrca,+ -- * Partitions and distances module ELynx.Tree.Bipartition, module ELynx.Tree.Partition,@@ -52,6 +55,7 @@ import ELynx.Tree.Import.Newick import ELynx.Tree.Import.Nexus import ELynx.Tree.Length+import ELynx.Tree.Mrca import ELynx.Tree.Name import ELynx.Tree.Parallel import ELynx.Tree.Partition
src/ELynx/Tree/Bipartition.hs view
@@ -3,7 +3,7 @@ -- | -- Module : ELynx.Tree.Bipartition -- Description : Bipartitions on trees--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -146,7 +146,7 @@ [Set a] getComplementaryLeaves p (Node _ _ ts) = [ S.unions $ p : take i lvsChildren ++ drop (i + 1) lvsChildren- | i <- [0 .. (n -1)]+ | i <- [0 .. (n - 1)] ] where n = length ts@@ -158,8 +158,8 @@ bipartitions' p (Node _ p' []) = either (const S.empty) S.singleton $ bp p p' bipartitions' p t@(Node _ p' ts) = S.unions $- either (const S.empty) S.singleton (bp p p') :- [bipartitions' c s | (c, s) <- zip cs ts]+ either (const S.empty) S.singleton (bp p p')+ : [bipartitions' c s | (c, s) <- zip cs ts] where cs = getComplementaryLeaves p t @@ -200,7 +200,7 @@ Map (Bipartition a) e bipartitionToBranch' p t@(Node b p' ts) = M.unionsWith (<>) $- either (const M.empty) (`M.singleton` b) (bp p p') :- [bipartitionToBranch' c s | (c, s) <- zip cs ts]+ either (const M.empty) (`M.singleton` b) (bp p p')+ : [bipartitionToBranch' c s | (c, s) <- zip cs ts] where cs = getComplementaryLeaves p t
src/ELynx/Tree/Distance.hs view
@@ -1,7 +1,7 @@ -- | -- Module : ELynx.Tree.Distance -- Description : Compute distances between trees--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -55,11 +55,11 @@ symmetric :: Ord a => Tree e1 a -> Tree e2 a -> Either String Int symmetric t1 t2 | S.fromList (leaves t1) /= S.fromList (leaves t2) =- Left "symmetric: Trees contain different leaves."+ Left "symmetric: Trees contain different leaves." | otherwise = do- bps1 <- bipartitions t1- bps2 <- bipartitions t2- return $ length $ symmetricDifference bps1 bps2+ bps1 <- bipartitions t1+ bps2 <- bipartitions t2+ return $ length $ symmetricDifference bps1 bps2 countIncompatibilities :: (Show a, Ord a) => Set (Bipartition a) -> Set (Partition a) -> Int countIncompatibilities bs ms =@@ -102,22 +102,22 @@ incompatibleSplits :: (Show a, Ord a) => Tree e1 a -> Tree e2 a -> Either String Int incompatibleSplits t1 t2 | S.fromList (leaves t1) /= S.fromList (leaves t2) =- Left "incompatibleSplits: Trees contain different leaves."+ Left "incompatibleSplits: Trees contain different leaves." | otherwise = do- -- Bipartitions.- bs1 <- bipartitions t1- bs2 <- bipartitions t2- -- traceShowM $ "bs1" ++ show (S.map bpHuman bs1)- -- traceShowM $ "bs2" ++ show (S.map bpHuman bs2)- let -- Putative incompatible bipartitions of trees one and two, respectively.- putIncBs1 = bs1 S.\\ bs2- putIncBs2 = bs2 S.\\ bs1- -- Partitions.- ms1 <- partitions t1- ms2 <- partitions t2- -- traceShowM $ "putIncBs1 " ++ show (S.map bpHuman putIncBs1)- -- traceShowM $ "putIncBs2 " ++ show (S.map bpHuman putIncBs2)- return $ countIncompatibilities putIncBs1 ms2 + countIncompatibilities putIncBs2 ms1+ -- Bipartitions.+ bs1 <- bipartitions t1+ bs2 <- bipartitions t2+ -- traceShowM $ "bs1" ++ show (S.map bpHuman bs1)+ -- traceShowM $ "bs2" ++ show (S.map bpHuman bs2)+ let -- Putative incompatible bipartitions of trees one and two, respectively.+ putIncBs1 = bs1 S.\\ bs2+ putIncBs2 = bs2 S.\\ bs1+ -- Partitions.+ ms1 <- partitions t1+ ms2 <- partitions t2+ -- traceShowM $ "putIncBs1 " ++ show (S.map bpHuman putIncBs1)+ -- traceShowM $ "putIncBs2 " ++ show (S.map bpHuman putIncBs2)+ return $ countIncompatibilities putIncBs1 ms2 + countIncompatibilities putIncBs2 ms1 -- | Compute branch score distance between two trees. --@@ -128,10 +128,10 @@ branchScore :: (HasLength e1, HasLength e2, Ord a) => Tree e1 a -> Tree e2 a -> Either String Double branchScore t1 t2 | S.fromList (leaves t1) /= S.fromList (leaves t2) =- Left "branchScoreWith: Trees contain different leaves."+ Left "branchScoreWith: Trees contain different leaves." | otherwise = do- bpToBr1 <- bipartitionToBranch $ first (Sum . getLength) t1- bpToBr2 <- bipartitionToBranch $ first (Sum . getLength) t2- let dBs = M.unionWith (-) bpToBr1 bpToBr2- dsSquared = foldl' (\acc e -> acc + e * e) 0 dBs- return $ sqrt $ fromLength $ getSum dsSquared+ bpToBr1 <- bipartitionToBranch $ first (Sum . getLength) t1+ bpToBr2 <- bipartitionToBranch $ first (Sum . getLength) t2+ let dBs = M.unionWith (-) bpToBr1 bpToBr2+ dsSquared = foldl' (\acc e -> acc + e * e) 0 dBs+ return $ sqrt $ fromLength $ getSum dsSquared
src/ELynx/Tree/Distribution/BirthDeath.hs view
@@ -4,7 +4,7 @@ -- | -- Module : ELynx.Tree.Distribution.BirthDeath -- Description : Birth and death distribution--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -57,8 +57,8 @@ | otherwise = t1 * t2 where d = l - m- t1 = (1.0 - exp (- d * x)) / (l - m * exp (- d * x))- t2 = (l - m * exp (- d * t)) / (1.0 - exp (- d * t))+ t1 = (1.0 - exp (-d * x)) / (l - m * exp (-d * x))+ t2 = (l - m * exp (-d * t)) / (1.0 - exp (-d * t)) instance D.ContDistr BirthDeathDistribution where density = density@@ -72,23 +72,23 @@ | otherwise = d ** 2 * t1 * t2 where d = l - m- t1 = exp (- d * x) / ((l - m * exp (- d * x)) ** 2)- t2 = (l - m * exp (- d * t)) / (1.0 - exp (- d * t))+ t1 = exp (-d * x) / ((l - m * exp (-d * x)) ** 2)+ t2 = (l - m * exp (-d * t)) / (1.0 - exp (-d * t)) -- | Inverted cumulative probability distribution 'cumulative'. See also -- 'D.ContDistr'. quantile :: BirthDeathDistribution -> Double -> Time quantile (BDD t l m) p | p >= 0 && p <= 1 =- res+ res | otherwise =- error $- "BirthDeath.quantile: p must be in range [0,1] but got "- ++ show p- ++ "."+ error $+ "BirthDeath.quantile: p must be in range [0,1] but got "+ ++ show p+ ++ "." where d = l - m- t2 = (l - m * exp (- d * t)) / (1.0 - exp (- d * t))+ t2 = (l - m * exp (-d * t)) / (1.0 - exp (-d * t)) res = (-1.0 / d) * log ((1.0 - p * l / t2) / (1.0 - p * m / t2)) instance D.ContGen BirthDeathDistribution where
src/ELynx/Tree/Distribution/BirthDeathCritical.hs view
@@ -4,7 +4,7 @@ -- | -- Module : ELynx.Tree.Distribution.BirthDeathCritical -- Description : Birth and death distribution--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -71,12 +71,12 @@ quantile :: BirthDeathCriticalDistribution -> Double -> Time quantile (BDCD t l) p | p >= 0 && p <= 1 =- res+ res | otherwise =- error $- "PointProcess.quantile: p must be in [0,1] range. Got: "- ++ show p- ++ "."+ error $+ "PointProcess.quantile: p must be in [0,1] range. Got: "+ ++ show p+ ++ "." where res = p * t / (1 + l * t - l * p * t)
src/ELynx/Tree/Distribution/BirthDeathCriticalNoTime.hs view
@@ -4,7 +4,7 @@ -- | -- Module : ELynx.Tree.Distribution.BirthDeathCriticalNoTime -- Description : Birth and death distribution--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -68,9 +68,9 @@ quantile :: BirthDeathCriticalNoTimeDistribution -> Double -> Time quantile (BDCNTD l) p | p >= 0 && p <= 1 =- p / (l - l * p)+ p / (l - l * p) | otherwise =- error $ "PointProcess.quantile: p must be in [0,1]. Got: " ++ show p ++ "."+ error $ "PointProcess.quantile: p must be in [0,1]. Got: " ++ show p ++ "." instance D.ContGen BirthDeathCriticalNoTimeDistribution where genContVar = D.genContinuous
src/ELynx/Tree/Distribution/BirthDeathNearlyCritical.hs view
@@ -4,7 +4,7 @@ -- | -- Module : ELynx.Tree.Distribution.BirthDeathNearlyCritical -- Description : Birth and death distribution--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -60,7 +60,7 @@ | otherwise = o0 + o1 where o0 = s * (1.0 + t * l) / t / (1.0 + s * l)- o1 = (- s * s + s * t) * (m - l) / (2.0 * t * (1.0 + s * l) ** 2)+ o1 = (-s * s + s * t) * (m - l) / (2.0 * t * (1.0 + s * l) ** 2) instance D.ContDistr BirthDeathNearlyCriticalDistribution where density = density@@ -81,27 +81,27 @@ quantile :: BirthDeathNearlyCriticalDistribution -> Double -> Time quantile (BDNCD t l m) p | p >= 0 && p <= 1 =- res+ res | otherwise =- error $- "PointProcess.quantile: p must be in [0,1] range. Got: "- ++ show p- ++ "."+ error $+ "PointProcess.quantile: p must be in [0,1] range. Got: "+ ++ show p+ ++ "." where den = l * (-3.0 + 2.0 * t * (-1.0 + p) * l) + m t1 = (2.0 + t * (l - 4.0 * p * l + m)) / den t2Nom = 4.0 + t- * ( l- * (4.0 + t * l + 8.0 * p * (1.0 + t * l))- + 2.0- * (2.0 + t * l - 4.0 * p * (1.0 + t * l))- * m- + t- * m- * m- )+ * ( l+ * (4.0 + t * l + 8.0 * p * (1.0 + t * l))+ + 2.0+ * (2.0 + t * l - 4.0 * p * (1.0 + t * l))+ * m+ + t+ * m+ * m+ ) t2 = t2Nom / (den ** 2) res = 0.5 * (t1 + sqrt t2)
src/ELynx/Tree/Distribution/CoalescentContinuous.hs view
@@ -1,7 +1,7 @@ -- | -- Module : ELynx.Tree.Distribution.CoalescentContinuous -- Description : Distribution of coalescent times--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
src/ELynx/Tree/Distribution/TimeOfOrigin.hs view
@@ -4,7 +4,7 @@ -- | -- Module : ELynx.Tree.Distribution.TimeOfOrigin -- Description : Distribution of time of origin for birth and death trees--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -56,7 +56,7 @@ | otherwise = te ** fromIntegral n where d = l - m- te = l * (1.0 - exp (- d * x)) / (l - m * exp (- d * x))+ te = l * (1.0 - exp (-d * x)) / (l - m * exp (-d * x)) instance D.ContDistr TimeOfOriginDistribution where density = density@@ -70,7 +70,7 @@ where d = l - m n = fromIntegral nn- ex = exp (- d * x)+ ex = exp (-d * x) t1 = 1.0 - ex t2 = l - m * ex @@ -79,12 +79,12 @@ quantile :: TimeOfOriginDistribution -> Double -> Time quantile (TOD n' l m) p | p >= 0 && p <= 1 =- -1.0 / d * log (t1 / t2)+ -1.0 / d * log (t1 / t2) | otherwise =- error $- "PointProcess.quantile: p must be in [0,1] range. Got: "- ++ show p- ++ "."+ error $+ "PointProcess.quantile: p must be in [0,1] range. Got: "+ ++ show p+ ++ "." where d = l - m n = fromIntegral n'
src/ELynx/Tree/Distribution/TimeOfOriginNearCritical.hs view
@@ -4,7 +4,7 @@ -- | -- Module : ELynx.Tree.Distribution.TimeOfOriginNearCritical -- Description : Distribution of time of origin for birth and death trees--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -80,15 +80,15 @@ quantile :: TimeOfOriginNearCriticalDistribution -> Double -> Time quantile (TONCD n' l m) p | p >= 0 && p <= 1 =- t1 + t2nom / t2den+ t1 + t2nom / t2den | otherwise =- error $- "PointProcess.quantile: p must be in [0,1] range. Got: "- ++ show p- ++ "."+ error $+ "PointProcess.quantile: p must be in [0,1] range. Got: "+ ++ show p+ ++ "." where n = fromIntegral n'- t1 = - p ** (1 / n) / ((-1 + p ** (1 / n)) * l)+ t1 = -p ** (1 / n) / ((-1 + p ** (1 / n)) * l) t2nom = p ** (2 / n) * (m - l) t2den = 2 * (-1 + p ** (1 / n)) ** 2 * l ** 2
src/ELynx/Tree/Distribution/Types.hs view
@@ -1,7 +1,7 @@ -- | -- Module : ELynx.Tree.Distribution.Types -- Description : Data types for distributions on trees--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
src/ELynx/Tree/Export/Newick.hs view
@@ -3,7 +3,7 @@ -- | -- Module : ELynx.Tree.Export.Newick -- Description : Export tree objects to Newick format--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
src/ELynx/Tree/Export/Nexus.hs view
@@ -3,7 +3,7 @@ -- | -- Module : ELynx.Tree.Export.Nexus -- Description : Export trees to Nexus files--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3 -- -- Maintainer : dominik.schrempf@gmail.com
src/ELynx/Tree/Import/Newick.hs view
@@ -3,7 +3,7 @@ -- | -- Module : ELynx.Tree.Import.Newick -- Description : Import Newick trees--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -225,7 +225,8 @@ *> optional brackets *> treeRevBayes <* char ';'- <* skipWhile isSpace <?> "newickRevBayes"+ <* skipWhile isSpace+ <?> "newickRevBayes" treeRevBayes :: Parser (Tree Phylo Name) treeRevBayes = branchedRevBayes <|> leafRevBayes <?> "treeRevBayes"
src/ELynx/Tree/Import/Nexus.hs view
@@ -3,7 +3,7 @@ -- | -- Module : ELynx.Tree.Import.Nexus -- Description : Import trees from Nexus files--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3 -- -- Maintainer : dominik.schrempf@gmail.com
src/ELynx/Tree/Length.hs view
@@ -5,7 +5,7 @@ -- | -- Module : ELynx.Tree.Length -- Description : Labels having a length--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
+ src/ELynx/Tree/Mrca.hs view
@@ -0,0 +1,112 @@+-- |+-- Module : ELynx.Tree.Mrca+-- Description : Most recent common ancestors+-- Copyright : 2022 Dominik Schrempf+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : experimental+-- Portability : portable+--+-- Creation date: Wed Jun 29 15:57:09 2022.+--+-- Specify nodes using most recent common ancestors (MRCA).+module ELynx.Tree.Mrca+ ( isAncestor,+ isMrca,+ getPathToMrca,+ getTreeAtMrca,+ findNode,+ )+where++import Data.Either+import Data.List+import Data.Maybe+import qualified Data.Set as S+import ELynx.Tree.Rooted+import ELynx.Tree.Zipper++-- | Test if the root node of the given tree is an ancestor of the given leaves.+isAncestor :: Ord a => S.Set a -> Tree e a -> Bool+-- True if an x of xs is not in the collection of leaves.+-- False if an x of xs is not in the collection of leaves. -> OK.+isAncestor xs t = not $ any (`S.notMember` lvs) xs+ where+ lvs = S.fromList $ leaves t++-- | Test if the root node of the given tree is the MRCA of the given leaves.+isMrca :: Ord a => S.Set a -> Tree e a -> Bool+-- True if any daughter forest is an ancestor.+-- False if any daughter forest is an ancestor. -> OK.+isMrca xs t = isAncestor xs t && not (any (isAncestor xs) (forest t))++-- | Get the path to the MRCA of the given leaves on the given tree.+--+-- Return 'Left' if:+--+-- - The tree has duplicate leaves.+--+-- - The MRCA cannot be found.+getPathToMrca :: (Ord a, Show a) => S.Set a -> Tree e a -> Either String Path+getPathToMrca ss tr+ | duplicateLeaves tr = Left "getPathToMrca: Tree contains duplicate leaves."+ | otherwise = tail <$> go 0 tr+ where+ go i t+ | isMrca ss t = Right [i]+ -- One path will be (Right p).+ | isAncestor ss t =+ case find isRight [go j t' | (j, t') <- zip [0 ..] (forest t)] of+ -- Use 'error' because this should never happen since one subtree has+ -- to contain the MRCA.+ Nothing -> error $ "getPathToMrca: BUG; I am ancestor but no MRCA found for: " <> show ss+ Just xs -> fmap (i :) xs+ | otherwise = Left $ "getPathToMrca: Could not get MRCA for: " <> show ss <> "."++getTreeAtMrca :: (Ord a, Show a) => S.Set a -> Tree e a -> Either String (Tree e a)+getTreeAtMrca ss tr+ | duplicateLeaves tr = Left "getTreeAtMrca: Tree contains duplicate leaves."+ | otherwise = go tr+ where+ go t+ | isMrca ss t = Right t+ -- One tree will be (Right t).+ | isAncestor ss t = case find isRight $ map go (forest t) of+ -- Use 'error' because this should never happen since one subtree has+ -- to contain the MRCA.+ Nothing -> error $ "getTreeAtMrca: BUG; I am ancestor but no MRCA found for: " <> show ss+ Just x -> x+ | otherwise = Left $ "getTreeAtMrca: Could not get MRCA for: " <> show ss <> "."++-- | Find a node on a tree.+--+-- If the node is found, the node is specified by the MRCA of the returned set+-- of leaves. The set will contain one element if the node is a leaf, or two+-- elements, if the node is internal.+--+-- Return 'Left' if:+--+-- - The tree has duplicate labels.+--+-- - The node cannot be found.+--+-- - The node is a degree two node.+findNode :: (Ord a, Show a) => a -> Tree e a -> Either String (S.Set a)+findNode n t+ | duplicateLabels t = Left "findNode: tree contains duplicate labels"+ | otherwise = case go n t of+ Nothing -> Left $ "findNode: node not found: " <> show n+ Just x -> x+ where+ go x (Node _ y ts)+ | x == y = case ts of+ [] -> Just $ Right $ S.singleton x+ (l : r : _) -> Just $ Right $ S.fromList [head $ leaves l, head $ leaves r]+ _ -> Just $ Left $ "findNode: degree two node found" <> show n+ | otherwise = case catMaybes $ map (go x) ts of+ [] -> Nothing+ [z] -> Just z+ -- Use 'error' because this should never happen since we check for+ -- duplicate labels.+ _ -> error $ "findNode: BUG; more internal nodes found" <> show n
src/ELynx/Tree/Name.hs view
@@ -5,7 +5,7 @@ -- | -- Module : ELynx.Tree.Name -- Description : Trees with named nodes--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
src/ELynx/Tree/Parallel.hs view
@@ -1,7 +1,7 @@ -- | -- Module : ELynx.Tree.Parallel -- Description : Evaluation strategies for trees--- Copyright : (c) Dominik Schrempf, 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -40,11 +40,11 @@ parTree :: (NFData e, NFData a) => Int -> Strategy (Tree e a) parTree n t@(Node br lb ts) | n == 1 = do- ts' <- myParList rdeepseq ts- return $ Node br lb ts'+ ts' <- myParList rdeepseq ts+ return $ Node br lb ts' | n >= 2 = do- ts' <- myParList (parTree (n -1)) ts- return $ Node br lb ts'+ ts' <- myParList (parTree (n - 1)) ts+ return $ Node br lb ts' | otherwise = rdeepseq t branchFoldMap :: (e -> f) -> (f -> f -> f) -> Tree e a -> f
src/ELynx/Tree/Partition.hs view
@@ -1,7 +1,7 @@ -- | -- Module : ELynx.Tree.Partition -- Description : Partitions on rose trees--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -109,8 +109,8 @@ partitions' _ (Node _ _ []) = S.empty partitions' p t@(Node _ _ ts) = S.unions $- either (const S.empty) S.singleton (pt (p : map label ts)) :- zipWith partitions' cs ts+ either (const S.empty) S.singleton (pt (p : map label ts))+ : zipWith partitions' cs ts where cs = getComplementaryLeaves p t
src/ELynx/Tree/Phylogeny.hs view
@@ -5,7 +5,7 @@ -- | -- Module : ELynx.Tree.Phylogeny -- Description : Phylogenetic trees--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -120,8 +120,8 @@ intersect ts | S.null lvsCommon = Left "intersect: Intersection of leaves is empty." | otherwise = case sequence [dropLeavesWith (predicate ls) t | (ls, t) <- zip leavesToDrop ts] of- Nothing -> Left "intersect: A tree is empty."- Just ts' -> Right ts'+ Nothing -> Left "intersect: A tree is empty."+ Just ts' -> Right ts' where -- Leaf sets. lvss = map (S.fromList . leaves) ts@@ -186,10 +186,10 @@ | length lvLst /= S.size lvSet = Left "rootAt: Tree has duplicate leaves." | toSet b /= lvSet = Left "rootAt: Bipartition does not match leaves of tree." | otherwise = do- ts <- roots t- case find (\x -> bipartition x == Right b) ts of- Nothing -> Left "rootAt': Bipartition not found on tree."- Just t' -> Right t'+ ts <- roots t+ case find (\x -> bipartition x == Right b) ts of+ Nothing -> Left "rootAt': Bipartition not found on tree."+ Just t' -> Right t' where lvLst = leaves t lvSet = S.fromList $ leaves t@@ -289,7 +289,7 @@ tR = Node bL' c $ tail ts complementaryForests :: Tree e a -> Forest e a -> [Forest e a]-complementaryForests t ts = [t : take i ts ++ drop (i + 1) ts | i <- [0 .. (n -1)]]+complementaryForests t ts = [t : take i ts ++ drop (i + 1) ts | i <- [0 .. (n - 1)]] where n = length ts
src/ELynx/Tree/Rooted.hs view
@@ -6,7 +6,7 @@ -- | -- Module : ELynx.Tree.Rooted -- Description : Rooted trees with labeled branches--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -77,6 +77,7 @@ setLabel, modifyLabel, labels,+ duplicateLabels, setLabels, identify, @@ -295,6 +296,10 @@ where squish (Node _ lb ts) xs = lb : foldr squish xs ts +-- | Check if a tree has duplicate labels.+duplicateLabels :: Ord a => Tree e a -> Bool+duplicateLabels = duplicates . labels+ -- | Set node labels in pre-order. -- -- Return 'Nothing' if the provided list of node labels is too short.@@ -353,9 +358,9 @@ dropNodesWith p (Node br lb ts) | p lb = Nothing | otherwise =- if null ts'- then Nothing- else Just $ Node br lb ts'+ if null ts'+ then Nothing+ else Just $ Node br lb ts' where ts' = mapMaybe (dropNodesWith p) ts
src/ELynx/Tree/Simulate/Coalescent.hs view
@@ -1,7 +1,7 @@ -- | -- Module : ELynx.Tree.Simulate.Coalescent -- Description : Generate coalescent trees--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -14,46 +14,45 @@ ) where -import Control.Monad.Primitive import ELynx.Tree.Distribution.CoalescentContinuous import ELynx.Tree.Length import ELynx.Tree.Rooted import Statistics.Distribution-import System.Random.MWC+import System.Random.Stateful -- | Simulate a coalescent tree with @n@ leaves. The branch lengths are in units -- of effective population size. simulate ::- (PrimMonad m) =>+ StatefulGen g m => -- | Number of leaves. Int ->- Gen (PrimState m) ->+ g -> m (Tree Length Int) simulate n = simulate' n 0 trs where trs = [Node 0 i [] | i <- [0 .. n - 1]] simulate' ::- (PrimMonad m) =>+ StatefulGen g m => Int -> Int -> Forest Length Int ->- Gen (PrimState m) ->+ g -> m (Tree Length Int) simulate' n a trs g | n <= 0 = error "Cannot construct trees without leaves." | n == 1 && length trs /= 1 = error "Too many trees provided." | n == 1 && length trs == 1 = return $ head trs | otherwise = do- -- Indices of the leaves to join will be i-1 and i.- i <- uniformR (1, n - 1) g- -- The time of the coalescent event.- t <- toLengthUnsafe <$> genContVar (coalescentDistributionCont n) g- let trs' = map (modifyStem (+ t)) trs -- Move time 't' up on the tree.- tl = trs' !! (i - 1)- tr = trs' !! i- -- Join the two chosen trees.- tm = Node 0 a [tl, tr]- -- Take the trees on the left, the merged tree, and the trees on the right.- trs'' = take (i - 1) trs' ++ [tm] ++ drop (i + 1) trs'- simulate' (n - 1) a trs'' g+ -- Indices of the leaves to join will be i-1 and i.+ i <- uniformRM (1, n - 1) g+ -- The time of the coalescent event.+ t <- toLengthUnsafe <$> genContVar (coalescentDistributionCont n) g+ let trs' = map (modifyStem (+ t)) trs -- Move time 't' up on the tree.+ tl = trs' !! (i - 1)+ tr = trs' !! i+ -- Join the two chosen trees.+ tm = Node 0 a [tl, tr]+ -- Take the trees on the left, the merged tree, and the trees on the right.+ trs'' = take (i - 1) trs' ++ [tm] ++ drop (i + 1) trs'+ simulate' (n - 1) a trs'' g
src/ELynx/Tree/Simulate/PointProcess.hs view
@@ -3,7 +3,7 @@ -- | -- Module : ELynx.Tree.Simulate.PointProcess -- Description : Point process and functions--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -28,7 +28,6 @@ where import Control.Monad-import Control.Monad.Primitive import Data.Function import Data.List import Data.Sequence (Seq)@@ -43,9 +42,7 @@ import ELynx.Tree.Length import ELynx.Tree.Rooted import qualified Statistics.Distribution as D- ( genContVar,- )-import System.Random.MWC+import System.Random.Stateful -- Require near critical process if birth and death rates are closer than this value. epsNearCriticalPointProcess :: Double@@ -67,10 +64,10 @@ sortListWithIndices xs = sortBy (compare `on` fst) $ zip xs ([0 ..] :: [Int]) -- Insert element into random position of list.-randomInsertList :: PrimMonad m => a -> [a] -> Gen (PrimState m) -> m [a]+randomInsertList :: StatefulGen g m => a -> [a] -> g -> m [a] randomInsertList e v g = do let l = length v- i <- uniformR (0, l) g+ i <- uniformRM (0, l) g return $ take i v ++ [e] ++ drop i v -- | A __point process__ for \(n\) points and of age \(t_{or}\) is defined as@@ -98,7 +95,7 @@ -- | Sample a point process using the 'BirthDeathDistribution'. The names of the -- points will be integers. simulate ::- (PrimMonad m) =>+ StatefulGen g m => -- | Number of points (samples). Int -> -- | Time of origin or MRCA.@@ -107,58 +104,57 @@ Rate -> -- | Death rate. Rate ->- -- | Generator.- Gen (PrimState m) ->+ g -> m (PointProcess Int Double) simulate n ts l m g | n < 1 = error "Number of samples needs to be one or larger." | l < 0.0 = error "Birth rate needs to be positive." | otherwise = case ts of- Random -> simulateRandom n l m g- Origin t -> simulateOrigin n t l m g- Mrca t -> simulateMrca n t l m g+ Random -> simulateRandom n l m g+ Origin t -> simulateOrigin n t l m g+ Mrca t -> simulateMrca n t l m g -- No time of origin given. We also don't need to take care of the conditioning -- (origin or MRCA). simulateRandom ::- PrimMonad m =>+ StatefulGen g m => Int -> Double -> Double ->- Gen (PrimState m) ->+ g -> m (PointProcess Int Double) simulateRandom n l m g | -- There is no formula for the over-critical process. m > l =- error- "simulateRandom: Please specify height if mu > lambda."+ error+ "simulateRandom: Please specify height if mu > lambda." | -- For the critical process, we have no idea about the time of origin, but can -- use a specially derived distribution. m =~= l =- do- !vs <- replicateM (n - 1) (D.genContVar (BDCNTD l) g)- -- The length of the root branch will be 0.- let t = maximum vs- return $ PointProcess [0 .. (n - 1)] vs t+ do+ !vs <- replicateM (n - 1) (D.genContVar (BDCNTD l) g)+ -- The length of the root branch will be 0.+ let t = maximum vs+ return $ PointProcess [0 .. (n - 1)] vs t | -- For the near critical process, we use a special distribution. abs (m - l) <= epsNearCriticalTimeOfOrigin =- do- t <- D.genContVar (TONCD n l m) g- simulateOrigin n t l m g+ do+ t <- D.genContVar (TONCD n l m) g+ simulateOrigin n t l m g | -- For a sub-critical branching process, we can use the formula from Tanja Stadler. otherwise =- do- t <- D.genContVar (TOD n l m) g- simulateOrigin n t l m g+ do+ t <- D.genContVar (TOD n l m) g+ simulateOrigin n t l m g -- Time of origin is given. simulateOrigin ::- PrimMonad m =>+ StatefulGen g m => Int -> Time -> Double -> Double ->- Gen (PrimState m) ->+ g -> m (PointProcess Int Double) simulateOrigin n t l m g | t < 0.0 = error "simulateOrigin: Time of origin needs to be positive."@@ -171,38 +167,38 @@ -- 2. The near critical branching process. -- 3. Normal values :). m =~= l = do- !vs <- replicateM (n - 1) (D.genContVar (BDCD t l) g)- return $ PointProcess [0 .. (n - 1)] vs t+ !vs <- replicateM (n - 1) (D.genContVar (BDCD t l) g)+ return $ PointProcess [0 .. (n - 1)] vs t | abs (m - l) <= epsNearCriticalPointProcess = do- !vs <- replicateM (n - 1) (D.genContVar (BDNCD t l m) g)- return $ PointProcess [0 .. (n - 1)] vs t+ !vs <- replicateM (n - 1) (D.genContVar (BDNCD t l m) g)+ return $ PointProcess [0 .. (n - 1)] vs t | otherwise = do- !vs <- replicateM (n - 1) (D.genContVar (BDD t l m) g)- return $ PointProcess [0 .. (n - 1)] vs t+ !vs <- replicateM (n - 1) (D.genContVar (BDD t l m) g)+ return $ PointProcess [0 .. (n - 1)] vs t -- Time of Mrca is given. simulateMrca ::- PrimMonad m =>+ StatefulGen g m => Int -> Time -> Double -> Double ->- Gen (PrimState m) ->+ g -> m (PointProcess Int Double) simulateMrca n t l m g | t < 0.0 = error "simulateMrca: Time of MRCA needs to be positive." | m =~= l = do- !vs <- replicateM (n - 2) (D.genContVar (BDCD t l) g)- vs' <- randomInsertList t vs g- return $ PointProcess [0 .. (n - 1)] vs' t+ !vs <- replicateM (n - 2) (D.genContVar (BDCD t l) g)+ vs' <- randomInsertList t vs g+ return $ PointProcess [0 .. (n - 1)] vs' t | abs (m - l) <= epsNearCriticalPointProcess = do- !vs <- replicateM (n - 2) (D.genContVar (BDNCD t l m) g)- vs' <- randomInsertList t vs g- return $ PointProcess [0 .. (n - 1)] vs' t+ !vs <- replicateM (n - 2) (D.genContVar (BDNCD t l m) g)+ vs' <- randomInsertList t vs g+ return $ PointProcess [0 .. (n - 1)] vs' t | otherwise = do- !vs <- replicateM (n - 2) (D.genContVar (BDD t l m) g)- vs' <- randomInsertList t vs g- return $ PointProcess [0 .. (n - 1)] vs' t+ !vs <- replicateM (n - 2) (D.genContVar (BDD t l m) g)+ vs' <- randomInsertList t vs g+ return $ PointProcess [0 .. (n - 1)] vs' t -- Sort the values of a point process and their indices to be (the indices -- that they will have while creating the tree).@@ -226,7 +222,7 @@ -- | See 'simulateReconstructedTree', but n times. simulateNReconstructedTrees ::- (PrimMonad m) =>+ (StatefulGen g m) => -- | Number of trees Int -> -- | Number of points (samples)@@ -237,8 +233,7 @@ Rate -> -- | Death rate Rate ->- -- | Generator (see 'System.Random.MWC')- Gen (PrimState m) ->+ g -> m (Forest Length Int) simulateNReconstructedTrees nT nP t l m g | nT <= 0 = return []@@ -248,7 +243,7 @@ -- 'toReconstructedTree') possibly with specific height and a fixed number of -- leaves according to the birth and death process. simulateReconstructedTree ::- (PrimMonad m) =>+ StatefulGen g m => -- | Number of points (samples) Int -> -- | Time of origin or MRCA@@ -257,8 +252,7 @@ Rate -> -- | Death rate Rate ->- -- | Generator (see 'System.Random.MWC')- Gen (PrimState m) ->+ g -> m (Tree Length Int) simulateReconstructedTree n t l m g = do PointProcess ns vs o <- simulate n t l m g@@ -284,7 +278,7 @@ | -- -- Test is deactivated. -- -- | otherwise = if isReconstructed treeOrigin then treeOrigin else error "Error in algorithm." otherwise =- treeOrigin+ treeOrigin where (vsSorted, isSorted) = sortPP pp !lvs = S.fromList [Node 0 p [] | p <- ps]
src/ELynx/Tree/Splittable.hs view
@@ -1,7 +1,7 @@ -- | -- Module : ELynx.Tree.Splittable -- Description : Splittable branch labels--- Copyright : (c) Dominik Schrempf, 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
src/ELynx/Tree/Support.hs view
@@ -5,7 +5,7 @@ -- | -- Module : ELynx.Tree.Support -- Description : Labels with support values--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
src/ELynx/Tree/Zipper.hs view
@@ -1,7 +1,7 @@ -- | -- Module : ELynx.Tree.Zipper -- Description : Zippers on rooted rose trees with branch labels--- Copyright : (c) Dominik Schrempf, 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com@@ -133,13 +133,13 @@ | null ts -> Nothing | length ts <= n -> Nothing | otherwise ->- Just $- Pos- { current = head rs',- before = reverse ls',- after = tail rs',- parents = (before pos, br, lb, after pos) : parents pos- }+ Just $+ Pos+ { current = head rs',+ before = reverse ls',+ after = tail rs',+ parents = (before pos, br, lb, after pos) : parents pos+ } where (ls', rs') = splitAt n ts @@ -151,12 +151,12 @@ | null ts -> error "goChildUnsafe: Forest is empty." | length ts <= n -> error "goChildUnsafe: Forest is too short." | otherwise ->- Pos- { current = head rs',- before = reverse ls',- after = tail rs',- parents = (before pos, br, lb, after pos) : parents pos- }+ Pos+ { current = head rs',+ before = reverse ls',+ after = tail rs',+ parents = (before pos, br, lb, after pos) : parents pos+ } where (ls', rs') = splitAt n ts
test/ELynx/ClassLaws.hs view
@@ -1,7 +1,7 @@ -- | -- Module : ELynx.ClassLaws -- Description : Unit tests for ELynx.ClassLaws--- Copyright : (c) 2021 Dominik Schrempf+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
test/ELynx/Topology/Arbitrary.hs view
@@ -3,7 +3,7 @@ -- | -- Module : ELynx.Topology.Arbitrary -- Description : Arbitrary instances for topologies--- Copyright : (c) 2021 Dominik Schrempf+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
test/ELynx/Topology/RootedSpec.hs view
@@ -1,7 +1,7 @@ -- | -- Module : ELynx.Topology.RootedSpec -- Description : Unit tests for ELynx.Topology.Rooted--- Copyright : (c) Dominik Schrempf, 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
test/ELynx/Tree/Arbitrary.hs view
@@ -3,7 +3,7 @@ -- | -- Module : ELynx.Tree.Arbitrary -- Description : Arbitrary instances for trees--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
test/ELynx/Tree/BipartitionSpec.hs view
@@ -2,7 +2,7 @@ -- | -- Module : ELynx.Tree.BipartitionSpec--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
test/ELynx/Tree/DistanceSpec.hs view
@@ -3,7 +3,7 @@ -- | -- Module : ELynx.Tree.DistanceSpec--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
test/ELynx/Tree/Export/NewickSpec.hs view
@@ -2,7 +2,7 @@ -- | -- Module : ELynx.Tree.Export.NewickSpec--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
test/ELynx/Tree/Export/NexusSpec.hs view
@@ -3,7 +3,7 @@ -- | -- Module : ELynx.Tree.Export.NexusSpec -- Description : Test export of trees in Nexus files--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3 -- -- Maintainer : dominik.schrempf@gmail.com
test/ELynx/Tree/Import/NewickSpec.hs view
@@ -2,7 +2,7 @@ -- | -- Module : ELynx.Tree.Import.NewickSpec--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
test/ELynx/Tree/Import/NexusSpec.hs view
@@ -3,7 +3,7 @@ -- | -- Module : ELynx.Tree.Import.NexusSpec -- Description : Test import of trees in Nexus files--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3 -- -- Maintainer : dominik.schrempf@gmail.com
test/ELynx/Tree/PartitionSpec.hs view
@@ -2,7 +2,7 @@ -- | -- Module : ELynx.Tree.PartitionSpec--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
test/ELynx/Tree/PhylogenySpec.hs view
@@ -4,7 +4,7 @@ -- | -- Module : ELynx.Tree.PhylogenySpec -- Description : Unit tests for ELynx.Tree.Phylogeny--- Copyright : (c) Dominik Schrempf, 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
test/ELynx/Tree/RootedSpec.hs view
@@ -3,7 +3,7 @@ -- | -- Module : ELynx.Tree.RootedSpec -- Description : Unit tests for ELynx.Tree.Rooted--- Copyright : (c) Dominik Schrempf 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com
test/ELynx/Tree/SupportSpec.hs view
@@ -3,7 +3,7 @@ -- | -- Module : ELynx.Tree.SupportSpec -- Description : Unit tests for ELynx.Tree.SupportSpec--- Copyright : (c) Dominik Schrempf, 2021+-- Copyright : 2021 Dominik Schrempf -- License : GPL-3.0-or-later -- -- Maintainer : dominik.schrempf@gmail.com