packages feed

elynx-seq 0.0.1 → 0.1.0

raw patch · 28 files changed

+795/−650 lines, 28 filesdep −lensdep ~elynx-toolsdep ~elynx-treedep ~math-functionsPVP ok

version bump matches the API change (PVP)

Dependencies removed: lens

Dependency ranges changed: elynx-tools, elynx-tree, math-functions

API changes (from Hackage documentation)

- ELynx.Data.Alphabet.Alphabet: alphabetNameVerbose :: Alphabet -> String
- ELynx.Data.MarkovProcess.SubstitutionModel: getRateMatrix :: SubstitutionModel -> RateMatrix
- ELynx.Data.Sequence.Defaults: defFieldWidth :: Int
- ELynx.Data.Sequence.Defaults: defSequenceListSummaryNumber :: Int
- ELynx.Data.Sequence.Defaults: defSequenceNameWidth :: Int
- ELynx.Data.Sequence.Defaults: defSequenceSummaryLength :: Int
- ELynx.Data.Sequence.MultiSequenceAlignment: MultiSequenceAlignment :: [SequenceName] -> Alphabet -> Matrix Character -> MultiSequenceAlignment
- ELynx.Data.Sequence.MultiSequenceAlignment: countGaps :: MultiSequenceAlignment -> Int
- ELynx.Data.Sequence.MultiSequenceAlignment: countIUPACChars :: MultiSequenceAlignment -> Int
- ELynx.Data.Sequence.MultiSequenceAlignment: countUnknowns :: MultiSequenceAlignment -> Int
- ELynx.Data.Sequence.MultiSequenceAlignment: data MultiSequenceAlignment
- ELynx.Data.Sequence.MultiSequenceAlignment: filterColumnsNoGaps :: MultiSequenceAlignment -> MultiSequenceAlignment
- ELynx.Data.Sequence.MultiSequenceAlignment: filterColumnsOnlyStd :: MultiSequenceAlignment -> MultiSequenceAlignment
- ELynx.Data.Sequence.MultiSequenceAlignment: filterColumnsStd :: Double -> MultiSequenceAlignment -> MultiSequenceAlignment
- ELynx.Data.Sequence.MultiSequenceAlignment: fromSequenceList :: [Sequence] -> Either String MultiSequenceAlignment
- ELynx.Data.Sequence.MultiSequenceAlignment: instance GHC.Classes.Eq ELynx.Data.Sequence.MultiSequenceAlignment.MultiSequenceAlignment
- ELynx.Data.Sequence.MultiSequenceAlignment: instance GHC.Read.Read ELynx.Data.Sequence.MultiSequenceAlignment.MultiSequenceAlignment
- ELynx.Data.Sequence.MultiSequenceAlignment: instance GHC.Show.Show ELynx.Data.Sequence.MultiSequenceAlignment.MultiSequenceAlignment
- ELynx.Data.Sequence.MultiSequenceAlignment: kEffEntropy :: FrequencyData -> [Double]
- ELynx.Data.Sequence.MultiSequenceAlignment: kEffHomoplasy :: FrequencyData -> [Double]
- ELynx.Data.Sequence.MultiSequenceAlignment: msaConcatenate :: MultiSequenceAlignment -> MultiSequenceAlignment -> MultiSequenceAlignment
- ELynx.Data.Sequence.MultiSequenceAlignment: msaJoin :: MultiSequenceAlignment -> MultiSequenceAlignment -> MultiSequenceAlignment
- ELynx.Data.Sequence.MultiSequenceAlignment: msaLength :: MultiSequenceAlignment -> Int
- ELynx.Data.Sequence.MultiSequenceAlignment: msaNSequences :: MultiSequenceAlignment -> Int
- ELynx.Data.Sequence.MultiSequenceAlignment: msasConcatenate :: [MultiSequenceAlignment] -> MultiSequenceAlignment
- ELynx.Data.Sequence.MultiSequenceAlignment: randomSubSample :: PrimMonad m => Int -> MultiSequenceAlignment -> Gen (PrimState m) -> m MultiSequenceAlignment
- ELynx.Data.Sequence.MultiSequenceAlignment: showMSA :: MultiSequenceAlignment -> ByteString
- ELynx.Data.Sequence.MultiSequenceAlignment: subSample :: [Int] -> MultiSequenceAlignment -> MultiSequenceAlignment
- ELynx.Data.Sequence.MultiSequenceAlignment: summarizeMSA :: MultiSequenceAlignment -> ByteString
- ELynx.Data.Sequence.MultiSequenceAlignment: toFrequencyData :: MultiSequenceAlignment -> FrequencyData
- ELynx.Data.Sequence.MultiSequenceAlignment: toSequenceList :: MultiSequenceAlignment -> [Sequence]
- ELynx.Data.Sequence.MultiSequenceAlignment: type FrequencyData = Matrix Double
- ELynx.Data.Sequence.Sequence: alphabet :: Lens' Sequence Alphabet
- ELynx.Data.Sequence.Sequence: characters :: Lens' Sequence SequenceCharacters
- ELynx.Data.Sequence.Sequence: concatenate :: Sequence -> Sequence -> Sequence
- ELynx.Data.Sequence.Sequence: concatenateSeqs :: [[Sequence]] -> [Sequence]
- ELynx.Data.Sequence.Sequence: fromCharacters :: SequenceCharacters -> ByteString
- ELynx.Data.Sequence.Sequence: lengthSequence :: Sequence -> Int
- ELynx.Data.Sequence.Sequence: name :: Lens' Sequence SequenceName
- ELynx.Data.Sequence.Sequence: sequenceListHeader :: ByteString
- ELynx.Data.Sequence.Sequence: showSequence :: Sequence -> ByteString
- ELynx.Data.Sequence.Sequence: showSequenceList :: [Sequence] -> ByteString
- ELynx.Data.Sequence.Sequence: summarizeSequence :: Sequence -> ByteString
- ELynx.Data.Sequence.Sequence: summarizeSequenceList :: [Sequence] -> ByteString
- ELynx.Data.Sequence.Sequence: summarizeSequenceListBody :: [Sequence] -> ByteString
- ELynx.Data.Sequence.Sequence: toCharacters :: ByteString -> SequenceCharacters
- ELynx.Data.Sequence.Sequence: trimSequence :: Int -> Sequence -> Sequence
- ELynx.Data.Sequence.Sequence: type SequenceCharacters = Vector Character
- ELynx.Data.Sequence.Sequence: type SequenceName = ByteString
- ELynx.Simulate.MarkovProcessAlongTree: simulateAndFlattenNSitesAlongTree :: (PrimMonad m, Measurable a) => Int -> StationaryDistribution -> ExchangeabilityMatrix -> Tree a -> Gen (PrimState m) -> m [[State]]
- ELynx.Simulate.MarkovProcessAlongTree: simulateAndFlattenNSitesAlongTreeMixtureModel :: (PrimMonad m, Measurable a) => Int -> Vector R -> [StationaryDistribution] -> [ExchangeabilityMatrix] -> Tree a -> Gen (PrimState m) -> m [[State]]
- ELynx.Simulate.MarkovProcessAlongTree: simulateNSitesAlongTree :: (PrimMonad m, Measurable a) => Int -> StationaryDistribution -> ExchangeabilityMatrix -> Tree a -> Gen (PrimState m) -> m (Tree [State])
- ELynx.Simulate.MarkovProcessAlongTree: simulateNSitesAlongTreeMixtureModel :: (PrimMonad m, Measurable a) => Int -> Vector R -> [StationaryDistribution] -> [ExchangeabilityMatrix] -> Tree a -> Gen (PrimState m) -> m (Tree [State])
+ ELynx.Data.Alphabet.Alphabet: description :: Alphabet -> String
+ ELynx.Data.MarkovProcess.SubstitutionModel: rateMatrix :: SubstitutionModel -> RateMatrix
+ ELynx.Data.Sequence.Alignment: Alignment :: [Name] -> Alphabet -> Matrix Character -> Alignment
+ ELynx.Data.Sequence.Alignment: [alphabet] :: Alignment -> Alphabet
+ ELynx.Data.Sequence.Alignment: [matrix] :: Alignment -> Matrix Character
+ ELynx.Data.Sequence.Alignment: [names] :: Alignment -> [Name]
+ ELynx.Data.Sequence.Alignment: concat :: Alignment -> Alignment -> Alignment
+ ELynx.Data.Sequence.Alignment: concatAlignments :: [Alignment] -> Alignment
+ ELynx.Data.Sequence.Alignment: countGaps :: Alignment -> Int
+ ELynx.Data.Sequence.Alignment: countIUPACChars :: Alignment -> Int
+ ELynx.Data.Sequence.Alignment: countUnknowns :: Alignment -> Int
+ ELynx.Data.Sequence.Alignment: data Alignment
+ ELynx.Data.Sequence.Alignment: distribution :: FrequencyData -> [Double]
+ ELynx.Data.Sequence.Alignment: filterColsNoGaps :: Alignment -> Alignment
+ ELynx.Data.Sequence.Alignment: filterColsOnlyStd :: Alignment -> Alignment
+ ELynx.Data.Sequence.Alignment: filterColsStd :: Double -> Alignment -> Alignment
+ ELynx.Data.Sequence.Alignment: fromSequences :: [Sequence] -> Either String Alignment
+ ELynx.Data.Sequence.Alignment: instance GHC.Classes.Eq ELynx.Data.Sequence.Alignment.Alignment
+ ELynx.Data.Sequence.Alignment: instance GHC.Show.Show ELynx.Data.Sequence.Alignment.Alignment
+ ELynx.Data.Sequence.Alignment: join :: Alignment -> Alignment -> Alignment
+ ELynx.Data.Sequence.Alignment: kEffEntropy :: FrequencyData -> [Double]
+ ELynx.Data.Sequence.Alignment: kEffHomoplasy :: FrequencyData -> [Double]
+ ELynx.Data.Sequence.Alignment: length :: Alignment -> Int
+ ELynx.Data.Sequence.Alignment: nSequences :: Alignment -> Int
+ ELynx.Data.Sequence.Alignment: randomSubSample :: PrimMonad m => Int -> Alignment -> Gen (PrimState m) -> m Alignment
+ ELynx.Data.Sequence.Alignment: subSample :: [Int] -> Alignment -> Alignment
+ ELynx.Data.Sequence.Alignment: summarize :: Alignment -> ByteString
+ ELynx.Data.Sequence.Alignment: toFrequencyData :: Alignment -> FrequencyData
+ ELynx.Data.Sequence.Alignment: toSequences :: Alignment -> [Sequence]
+ ELynx.Data.Sequence.Alignment: type FrequencyData = Matrix Double
+ ELynx.Data.Sequence.Defaults: fieldWidth :: Int
+ ELynx.Data.Sequence.Defaults: nameWidth :: Int
+ ELynx.Data.Sequence.Defaults: summaryLength :: Int
+ ELynx.Data.Sequence.Defaults: summaryNSequences :: Int
+ ELynx.Data.Sequence.Sequence: [alphabet] :: Sequence -> Alphabet
+ ELynx.Data.Sequence.Sequence: [characters] :: Sequence -> Characters
+ ELynx.Data.Sequence.Sequence: [name] :: Sequence -> Name
+ ELynx.Data.Sequence.Sequence: body :: [Sequence] -> ByteString
+ ELynx.Data.Sequence.Sequence: concat :: Sequence -> Sequence -> Sequence
+ ELynx.Data.Sequence.Sequence: concatSequences :: [[Sequence]] -> [Sequence]
+ ELynx.Data.Sequence.Sequence: filterStandard :: [Sequence] -> [Sequence]
+ ELynx.Data.Sequence.Sequence: fromByteString :: ByteString -> Characters
+ ELynx.Data.Sequence.Sequence: header :: [Sequence] -> ByteString
+ ELynx.Data.Sequence.Sequence: length :: Sequence -> Int
+ ELynx.Data.Sequence.Sequence: summarize :: Sequence -> ByteString
+ ELynx.Data.Sequence.Sequence: summarizeSequences :: [Sequence] -> ByteString
+ ELynx.Data.Sequence.Sequence: toByteString :: Characters -> ByteString
+ ELynx.Data.Sequence.Sequence: trim :: Int -> Sequence -> Sequence
+ ELynx.Data.Sequence.Sequence: type Characters = Vector Character
+ ELynx.Data.Sequence.Sequence: type Name = ByteString
+ ELynx.Import.MarkovProcess.SiteprofilesPhylobayes: siteprofiles :: Parser [EDMComponent]
+ ELynx.Import.MarkovProcess.SiteprofilesPhylobayes: type EDMComponent = (Weight, Vector Double)
+ ELynx.Import.MarkovProcess.SiteprofilesPhylobayes: type Parser = Parsec Void ByteString
+ ELynx.Import.Sequence.Fasta: type Parser = Parsec Void ByteString
+ ELynx.Simulate.MarkovProcessAlongTree: simulate :: (PrimMonad m, Measurable a) => Int -> StationaryDistribution -> ExchangeabilityMatrix -> Tree a -> Gen (PrimState m) -> m (Tree [State])
+ ELynx.Simulate.MarkovProcessAlongTree: simulateAndFlatten :: (PrimMonad m, Measurable a) => Int -> StationaryDistribution -> ExchangeabilityMatrix -> Tree a -> Gen (PrimState m) -> m [[State]]
+ ELynx.Simulate.MarkovProcessAlongTree: simulateAndFlattenMixtureModel :: (PrimMonad m, Measurable a) => Int -> Vector R -> [StationaryDistribution] -> [ExchangeabilityMatrix] -> Tree a -> Gen (PrimState m) -> m [[State]]
+ ELynx.Simulate.MarkovProcessAlongTree: simulateAndFlattenMixtureModelPar :: Measurable a => Int -> Vector R -> [StationaryDistribution] -> [ExchangeabilityMatrix] -> Tree a -> GenIO -> IO [[[State]]]
+ ELynx.Simulate.MarkovProcessAlongTree: simulateMixtureModel :: (PrimMonad m, Measurable a) => Int -> Vector R -> [StationaryDistribution] -> [ExchangeabilityMatrix] -> Tree a -> Gen (PrimState m) -> m (Tree [State])
- ELynx.Data.MarkovProcess.MixtureModel: name :: Lens' MixtureModel Name
+ ELynx.Data.MarkovProcess.MixtureModel: name :: MixtureModel -> Name
- ELynx.Data.MarkovProcess.SubstitutionModel: alphabet :: Lens' SubstitutionModel Alphabet
+ ELynx.Data.MarkovProcess.SubstitutionModel: alphabet :: SubstitutionModel -> Alphabet
- ELynx.Data.MarkovProcess.SubstitutionModel: exchangeabilityMatrix :: Lens' SubstitutionModel ExchangeabilityMatrix
+ ELynx.Data.MarkovProcess.SubstitutionModel: exchangeabilityMatrix :: SubstitutionModel -> ExchangeabilityMatrix
- ELynx.Data.MarkovProcess.SubstitutionModel: name :: Lens' SubstitutionModel Name
+ ELynx.Data.MarkovProcess.SubstitutionModel: name :: SubstitutionModel -> Name
- ELynx.Data.MarkovProcess.SubstitutionModel: stationaryDistribution :: Lens' SubstitutionModel StationaryDistribution
+ ELynx.Data.MarkovProcess.SubstitutionModel: stationaryDistribution :: SubstitutionModel -> StationaryDistribution
- ELynx.Data.Sequence.Sequence: Sequence :: SequenceName -> Alphabet -> SequenceCharacters -> Sequence
+ ELynx.Data.Sequence.Sequence: Sequence :: Name -> Alphabet -> Characters -> Sequence

Files

ChangeLog.md view
@@ -1,10 +1,10 @@  # Table of Contents -1.  [Changelog for ELynx](#org9916021)+1.  [Changelog for ELynx](#org263dcac)  -<a id="org9916021"></a>+<a id="org263dcac"></a>  # Changelog for ELynx 
README.md view
@@ -2,33 +2,33 @@  # The ELynx Suite -Version: 0.0.1.+Version: 0.1.0. Reproducible evolution made easy.  The ELynx Suite is a Haskell library and a tool set for computational biology. The goal of the ELynx Suite is reproducible research. Evolutionary sequences and phylogenetic trees can be read, viewed, modified and simulated. Exact specification of all options is necessary, and nothing is assumed about the data-(e.g., the type of code). The command line with all arguments is consistently,-and automatically logged. The work overhead in the beginning usually pays off in-the end.+(e.g., the type of the genetic code). The command line with all arguments is+consistently, and automatically logged. The work overhead in the beginning+usually pays off in the end.  The Elynx Suite consists of three library packages and two executables providing a range of sub commands.  The library packages are: --   **elynx-seq:** Handle evolutionary sequences and multi sequence alignments;--   **elynx-tree:** Handle phylogenetic trees;--   **elynx-tools:** Tools for the provided executables;+-   **elynx-seq:** Handle evolutionary sequences and multi sequence alignments.+-   **elynx-tree:** Handle phylogenetic trees.+-   **elynx-tools:** Tools for the provided executables.  The executables are: --   **SLynx:** Analyze, modify, and simulate evolutionary sequences (FASTA format);--   **TLynx:** Analyze, modify, and simulate phylogenetic trees (Newick format).+-   **slynx:** Analyze, modify, and simulate evolutionary sequences (FASTA format).+-   **tlynx:** Analyze, modify, and simulate phylogenetic trees (Newick format). -**ELynx is still under development. We happily receive comments, ideas, feature-requests, or pull requests!**+**ELynx is actively developed. We happily receive comments, ideas, feature+requests, and pull requests!**   # Installation@@ -57,8 +57,8 @@              stack install     -    The binaries are installed into `~/.local/bin/` which has to be added [PATH](https://en.wikipedia.org/wiki/PATH_(variable)).-    Then, they can be used directly.+    The binaries are installed into `~/.local/bin/` which has to be added to the+    [PATH](https://en.wikipedia.org/wiki/PATH_(variable)) environment variable. Then, they can be used directly.   # SLynx@@ -67,8 +67,8 @@      slynx --help -    ELynx Suite version 0.5.1. Developed by Dominik Schrempf. Compiled on September-    9, 2019, at 10:48 am, UTC.+    ELynx Suite version 0.1.0. Developed by Dominik Schrempf. Compiled on January+    30, 2020, at 09:18 am, UTC.          Usage: slynx [-v|--verbosity VALUE] [-o|--output-file-basename NAME] COMMAND       Analyze, and simulate multi sequence alignments.@@ -82,17 +82,14 @@                                Specify base name of output file          Available commands:-      concatenate              -      examine                  If data is a multi sequence alignment, additionally-                               analyze columns.-      filter-rows              -      filter-columns           -      simulate                 -      sub-sample               Create a given number of multi sequence alignments,-                               each of which containing a given number of random-                               sites drawn from the original multi sequence-                               alignment.-      translate                +      concatenate              Concatenate sequences found in input files.+      examine                  Examine sequences. If data is a multi sequence+                               alignment, additionally analyze columns.+      filter-rows              Filter rows (or sequences) found in input files.+      filter-columns           Filter columns of multi-sequence alignments.+      simulate                 Simulate multi sequence alignments.+      sub-sample               Sub-sample columns from multi sequence alignments.+      translate                Translate from DNA to Protein or DNAX to ProteinX.          File formats:       - FASTA@@ -106,15 +103,20 @@       - ProteinS (amino acids; including gaps, and translation stops)       - ProteinI (amino acids; including gaps, translation stops, and IUPAC codes)     -    The ELynx Suite.+    The ELynx Suite+    ---------------     A Haskell library and a tool set for computational biology. The goal of the     ELynx Suite is reproducible research. Evolutionary sequences and phylogenetic     trees can be read, viewed, modified and simulated. Exact specification of all     options is necessary, and nothing is assumed about the data (e.g., the type of     code). The command line with all arguments is consistently, and automatically-    logged. The work overhead in the beginning usually pays off in the end.+    logged.+         slynx     Analyze, modify, and simulate evolutionary sequences.     tlynx     Analyze, modify, and simulate phylogenetic trees.+    +    Get help for specific commands:+      slynx examine --help   ## Concatenate@@ -123,9 +125,8 @@      slynx concatenate --help -    Concatenate sequences found in input files.-         Usage: slynx concatenate (-a|--alphabet NAME) INPUT-FILE+      Concatenate sequences found in input files.          Available options:       -a,--alphabet NAME       Specify alphabet type NAME@@ -139,10 +140,9 @@      slynx examine --help -    Examine sequences.-         Usage: slynx examine (-a|--alphabet NAME) [INPUT-FILE] [--per-site]-      If data is a multi sequence alignment, additionally analyze columns.+      Examine sequences. If data is a multi sequence alignment, additionally analyze+      columns.          Available options:       -a,--alphabet NAME       Specify alphabet type NAME@@ -157,26 +157,27 @@      slynx filter-rows --help -    Filter rows (or sequences) found in input files.-         Usage: slynx filter-rows (-a|--alphabet NAME) [INPUT-FILE]                              [--longer-than LENGTH] [--shorter-than LENGTH]+                             [--standard-characters]+      Filter rows (or sequences) found in input files.          Available options:       -a,--alphabet NAME       Specify alphabet type NAME       INPUT-FILE               Read sequences from INPUT-FILE       --longer-than LENGTH     Only keep sequences longer than LENGTH       --shorter-than LENGTH    Only keep sequences shorter than LENGTH+      --standard-characters    Only keep sequences containing at least one standard+                               (i.e., non-IUPAC) character       -h,--help                Show this help text  Filter columns of multi sequence alignments with `filter-columns`.      slynx filter-columns --help -    Filter columns of multi-sequence alignments.-         Usage: slynx filter-columns (-a|--alphabet NAME) [INPUT-FILE]                                 [--standard-chars DOUBLE]+      Filter columns of multi-sequence alignments.          Available options:       -a,--alphabet NAME       Specify alphabet type NAME@@ -192,13 +193,13 @@      slynx simulate --help -    Simulate multi sequence alignments.-         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]]+      Simulate multi sequence alignments.          Available options:       -t,--tree-file Name      Read trees from file NAME@@ -210,6 +211,8 @@                                are shown below (mutually exclusive with -s option)       -e,--edm-file NAME       Empirical distribution model file NAME in Phylobayes                                format+      -p,--siteprofile-files NAMES+                               File names of site profiles in Phylobayes format       -w,--mixture-model-weights "[DOUBLE,DOUBLE,...]"                                Weights of mixture model components       -g,--gamma-rate-heterogeneity "(NCAT,SHAPE)"@@ -257,8 +260,7 @@     Usage: slynx sub-sample (-a|--alphabet NAME) [INPUT-FILE]                             (-n|--number-of-sites INT)                             (-m|--number-of-alignments INT) [-S|--seed [INT]]-      Create a given number of multi sequence alignments, each of which containing a-      given number of random sites drawn from the original multi sequence alignment.+      Sub-sample columns from multi sequence alignments.          Available options:       -a,--alphabet NAME       Specify alphabet type NAME@@ -269,6 +271,9 @@       -S,--seed [INT]          Seed for random number generator; list of 32 bit                                integers with up to 256 elements (default: random)       -h,--help                Show this help text+    +    Create a given number of multi sequence alignments, each of which contains a+    given number of random sites drawn from the original multi sequence alignment.   ## Translate@@ -277,10 +282,9 @@      slynx translate --help -    Translate from DNA to Protein or DNAX to ProteinX.-         Usage: slynx translate (-a|--alphabet NAME) [INPUT-FILE]                            (-r|--reading-frame INT) (-u|--universal-code CODE)+      Translate from DNA to Protein or DNAX to ProteinX.          Available options:       -a,--alphabet NAME       Specify alphabet type NAME@@ -297,8 +301,8 @@      tlynx --help -    ELynx Suite version 0.5.1. Developed by Dominik Schrempf. Compiled on September-    9, 2019, at 10:48 am, UTC.+    ELynx Suite version 0.1.0. Developed by Dominik Schrempf. Compiled on January+    30, 2020, at 09:18 am, UTC.          Usage: tlynx [-v|--verbosity VALUE] [-o|--output-file-basename NAME] COMMAND       Compare, examine, and simulate phylogenetic trees.@@ -312,26 +316,34 @@                                Specify base name of output file          Available commands:-      compare                  -      examine                  -      simulate                 Simulate reconstructed trees using the point process.-                               See Gernhard, T. (2008). The conditioned-                               reconstructed process. Journal of Theoretical-                               Biology, 253(4), 769–778.-                               http://doi.org/10.1016/j.jtbi.2008.04.005+      distance                 Compute distances between many phylogenetic trees.+      examine                  Compute summary statistics of phylogenetic trees.+      simulate                 Simulate phylogenetic trees using birth and death+                               processes.+      compare                  Compare two phylogenetic trees (compute distances and+                               branch-wise differences).+      connect                  Connect two phylogenetic trees in all ways (possibly+                               honoring constraints).+      shuffle                  Shuffle a phylogenetic tree (keep coalescent times,+                               but shuffle topology and leaves).          File formats:       - Newick     -    The ELynx Suite.+    The ELynx Suite+    ---------------     A Haskell library and a tool set for computational biology. The goal of the     ELynx Suite is reproducible research. Evolutionary sequences and phylogenetic     trees can be read, viewed, modified and simulated. Exact specification of all     options is necessary, and nothing is assumed about the data (e.g., the type of     code). The command line with all arguments is consistently, and automatically-    logged. The work overhead in the beginning usually pays off in the end.+    logged.+         slynx     Analyze, modify, and simulate evolutionary sequences.     tlynx     Analyze, modify, and simulate phylogenetic trees.+    +    Get help for specific commands:+      slynx examine --help   ## Compare@@ -340,24 +352,18 @@      tlynx compare --help -    Compute distances between phylogenetic trees.-    -    Usage: tlynx compare (-d|--distance MEASURE) [-s|--summary-statistics]-                         [INPUT-FILES]+    Usage: tlynx compare [-n|--normalize] [-b|--bipartitions] [-i|--newick-iqtree]+                         NAME+      Compare two phylogenetic trees (compute distances and branch-wise+      differences).          Available options:-      -d,--distance MEASURE    Type of distance to calculate (available distance-                               measures are listed below)-      -s,--summary-statistics  Report summary statistics only-      INPUT-FILES              Read tree(s) from INPUT-FILES; if more files are-                               given, one tree is expected per file+      -n,--normalize           Normalize trees before comparison+      -b,--bipartitions        Print common and missing bipartitions+      -i,--newick-iqtree       Use IQ-TREE Newick format (internal node labels are+                               branch support values)+      NAME                     Tree file       -h,--help                Show this help text-    -    Available distance measures:-      Symmetric distance: -d symmetric-      Incompatible split distance: -d incompatible-split[VAL]-        Collapse branches with support less than VAL before distance calculation;-        in this way, only well supported difference contribute to the distance measure.   ## Examine@@ -366,12 +372,13 @@      tlynx examine --help -    Compute summary statistics of phylogenetic trees.-    -    Usage: tlynx examine [INPUT-FILE]+    Usage: tlynx examine [INPUT-FILE] [-i|--newick-iqtree]+      Compute summary statistics of phylogenetic trees.          Available options:       INPUT-FILE               Read trees from INPUT-FILE+      -i,--newick-iqtree       Use IQ-TREE Newick format (internal node labels are+                               branch support values)       -h,--help                Show this help text  @@ -381,15 +388,11 @@      tlynx simulate --help -    Simulate phylogenetic trees using birth and death processes.-         Usage: tlynx simulate [-t|--nTrees INT] [-n|--nLeaves INT] [-H|--height DOUBLE]                           [-M|--condition-on-mrca] [-l|--lambda DOUBLE]                           [-m|--mu DOUBLE] [-r|--rho DOUBLE] [-u|--sub-sample]                           [-s|--summary-statistics] [-S|--seed [INT]]-      Simulate reconstructed trees using the point process. See Gernhard, T. (2008).-      The conditioned reconstructed process. Journal of Theoretical Biology, 253(4),-      769–778. http://doi.org/10.1016/j.jtbi.2008.04.005+      Simulate phylogenetic trees using birth and death processes.          Available options:       -t,--nTrees INT          Number of trees (default: 10)@@ -409,9 +412,16 @@     Height of Trees: if no tree height is given, the heights will be randomly drawn from the expected distribution given the number of leaves, the birth and the death rate.     Summary statistics only: only print (NumberOfExtantChildren BranchLength) pairs for each branch of each tree. The trees are separated by a newline character.     Sub-sampling: simulate one big tree with n'=round(n/rho), n'>=n, leaves, and randomly sample sub-trees with n leaves. Hence, with rho=1.0, the same tree is reported over and over again.+    Gernhard, T. (2008). The conditioned reconstructed process. Journal of Theoretical Biology, 253(4), 769–778. http://doi.org/10.1016/j.jtbi.2008.04.005   # ELynx -Documentation of the library can be found on Hackage.+Documentation of the library can be found on [Hackage](https://hackage.haskell.org/):++-   [elynx-seq](https://hackage.haskell.org/package/elynx-seq)+-   [elynx-tree](https://hackage.haskell.org/package/elynx-tree)+-   [elynx-tools](https://hackage.haskell.org/package/elynx-tools)+-   [slynx](https://hackage.haskell.org/package/slynx)+-   [tlynx](https://hackage.haskell.org/package/tlynx) 
elynx-seq.cabal view
@@ -1,6 +1,6 @@ cabal-version: 1.12 name: elynx-seq-version: 0.0.1+version: 0.1.0 license: GPL-3 license-file: LICENSE copyright: Dominik Schrempf (2019)@@ -46,13 +46,14 @@         ELynx.Data.MarkovProcess.PhyloModel         ELynx.Data.MarkovProcess.RateMatrix         ELynx.Data.MarkovProcess.SubstitutionModel+        ELynx.Data.Sequence.Alignment         ELynx.Data.Sequence.Defaults-        ELynx.Data.Sequence.MultiSequenceAlignment         ELynx.Data.Sequence.Sequence         ELynx.Data.Sequence.Translate         ELynx.Export.Sequence.CountsFile         ELynx.Export.Sequence.Fasta         ELynx.Import.MarkovProcess.EDMModelPhylobayes+        ELynx.Import.MarkovProcess.SiteprofilesPhylobayes         ELynx.Import.Sequence.Fasta         ELynx.Simulate.MarkovProcess         ELynx.Simulate.MarkovProcessAlongTree@@ -60,19 +61,18 @@     other-modules:         Paths_elynx_seq     default-language: Haskell2010-    ghc-options: -Wall+    ghc-options: -Wall -O2     build-depends:         async >=2.2.2 && <2.3,         base >=4.12.0.0 && <4.13,         bytestring >=0.10.8.2 && <0.11,         containers >=0.6.0.1 && <0.7,         data-memocombinators >=0.5.1 && <0.6,-        elynx-tools >=0.0.1 && <0.1,-        elynx-tree >=0.0.1 && <0.1,+        elynx-tools >=0.1.0 && <0.2,+        elynx-tree >=0.1.0 && <0.2,         hmatrix >=0.20.0.0 && <0.21,         integration >=0.2.1 && <0.3,-        lens >=4.17.1 && <4.18,-        math-functions >=0.3.1.0 && <0.4,+        math-functions >=0.3.2.1 && <0.4,         matrices >=0.5.0 && <0.6,         megaparsec >=7.0.5 && <7.1,         mwc-random >=0.14.0.0 && <0.15,@@ -93,17 +93,19 @@         ELynx.Data.Alphabet.DistributionDiversitySpec         ELynx.Data.MarkovProcess.AminoAcidSpec         ELynx.Data.MarkovProcess.NucleotideSpec-        ELynx.Data.Sequence.MultiSequenceAlignmentSpec+        ELynx.Data.Sequence.AlignmentSpec         ELynx.Data.Sequence.SequenceSpec         ELynx.Data.Sequence.TranslateSpec         ELynx.Export.Sequence.FastaSpec         ELynx.Import.MarkovProcess.EDMModelPhylobayesSpec+        ELynx.Import.MarkovProcess.SiteprofilesPhylobayesSpec         ELynx.Import.Sequence.FastaSpec         ELynx.Simulate.MarkovProcessAlongTreeSpec         Files         Paths_elynx_seq     default-language: Haskell2010-    ghc-options: -Wall -eventlog -threaded -rtsopts -with-rtsopts=-N+    ghc-options: -Wall -O2 -eventlog -threaded -rtsopts+                 -with-rtsopts=-N     build-depends:         async >=2.2.2 && <2.3,         base >=4.12.0.0 && <4.13,@@ -111,14 +113,13 @@         containers >=0.6.0.1 && <0.7,         data-memocombinators >=0.5.1 && <0.6,         elynx-seq -any,-        elynx-tools >=0.0.1 && <0.1,-        elynx-tree >=0.0.1 && <0.1,+        elynx-tools >=0.1.0 && <0.2,+        elynx-tree >=0.1.0 && <0.2,         hmatrix >=0.20.0.0 && <0.21,         hspec >=2.7.1 && <2.8,         hspec-megaparsec >=2.0.1 && <2.1,         integration >=0.2.1 && <0.3,-        lens >=4.17.1 && <4.18,-        math-functions >=0.3.1.0 && <0.4,+        math-functions >=0.3.2.1 && <0.4,         matrices >=0.5.0 && <0.6,         megaparsec >=7.0.5 && <7.1,         mwc-random >=0.14.0.0 && <0.15,
src/ELynx/Data/Alphabet/Alphabet.hs view
@@ -34,7 +34,7 @@     Alphabet (..)   , AlphabetSpec (..)   , alphabetSpec-  , alphabetNameVerbose+  , description   , isStd   , isGap   , isUnknown@@ -53,14 +53,14 @@               deriving (Show, Read, Eq, Ord, Enum, Bounded)  -- | Verbose alphabet name.-alphabetNameVerbose :: Alphabet -> String-alphabetNameVerbose DNA      = "DNA (nucleotides)"-alphabetNameVerbose DNAX     = "DNAX (nucleotides; including gaps)"-alphabetNameVerbose DNAI     = "DNAI (nucleotides; including gaps, and IUPAC codes)"-alphabetNameVerbose Protein  = "Protein (amino acids)"-alphabetNameVerbose ProteinX = "ProteinX (amino acids; including gaps)"-alphabetNameVerbose ProteinS = "ProteinS (amino acids; including gaps, and translation stops)"-alphabetNameVerbose ProteinI = "ProteinI (amino acids; including gaps, translation stops, and IUPAC codes)"+description :: Alphabet -> String+description DNA      = "DNA (nucleotides)"+description DNAX     = "DNAX (nucleotides; including gaps)"+description DNAI     = "DNAI (nucleotides; including gaps, and IUPAC codes)"+description Protein  = "Protein (amino acids)"+description ProteinX = "ProteinX (amino acids; including gaps)"+description ProteinS = "ProteinS (amino acids; including gaps, and translation stops)"+description ProteinI = "ProteinI (amino acids; including gaps, translation stops, and IUPAC codes)"  -- | Alphabet specification. 'S.Set' is used because it provides fast lookups. data AlphabetSpec = AlphabetSpec {
src/ELynx/Data/Alphabet/DistributionDiversity.hs view
@@ -84,6 +84,9 @@   else fromIntegral value / fromIntegral divisor  -- | For a given code vector of characters, calculate frequency of characters.+-- The input vector has arbitrary length (most often the number of sequences in+-- an alignment), the length of the output vector is the number of characters in+-- the alphabet. frequencyCharacters :: AlphabetSpec -> V.Vector Character -> V.Vector Double frequencyCharacters alph d = V.map (`saveDivision` s) counts   where
src/ELynx/Data/Character/BoundaryMutation.hs view
@@ -12,7 +12,8 @@  * Changelog -TODO: BM states can not be read and written with a single letter, like characters.+TODO: BM states can not be read and written with a single letter, like+characters. Check status of implementation.  -} @@ -34,7 +35,6 @@   , neighbors   ) where -import           Control.Lens import qualified Data.ByteString.Lazy.Char8      as L import           Numeric.SpecFunctions           (choose) @@ -140,12 +140,12 @@   | i >= stateSpaceSize n = error $     "Index " ++ show i ++ "out of bounds when population size is " ++ show n ++ "."   | i < nAlleles = Bnd n (toEnum i)-  | otherwise = Ply n (i' - p^._1 + 1) (p^._2) (p^._3)+  | otherwise = Ply n (i' - j + 1) x k   where i' = i - nAlleles         l = [ (enumCombination a b * (n-1), a, b)             | a <- [minBound .. pred maxBound]             , b <- [succ a ..]]-        p = last $ takeWhile (\e -> e^._1 <= i') l+        (j, x, k) = last $ takeWhile (\(e, _, _) -> e <= i') l  -- | Convert 'State' to a number 'Int' for the given population size 'PopulationSize'. -- Back conversion can be done with 'fromIndexWith', with the same population size.
src/ELynx/Data/MarkovProcess/GammaRateHeterogeneity.hs view
@@ -22,7 +22,6 @@   , expand   ) where -import           Control.Lens import qualified Data.ByteString.Lazy.Char8                 as L import           Numeric.Integration.TanhSinh import           Statistics.Distribution@@ -65,13 +64,13 @@ expandSubstitutionModel :: Int -> Double -> S.SubstitutionModel -> M.MixtureModel expandSubstitutionModel n alpha sm = M.fromSubstitutionModels name (repeat 1.0) sms   where-    name = sm ^. S.name <> getName n alpha+    name = S.name sm <> getName n alpha     sms  = splitSubstitutionModel n alpha sm  expandMixtureModel :: Int -> Double -> M.MixtureModel -> M.MixtureModel expandMixtureModel n alpha mm = M.concatenate name renamedMMs   where-    name = mm ^. M.name <> getName n alpha+    name = M.name mm <> getName n alpha     means = getMeans n alpha     scaledMMs = map (`M.scale` mm) means     names = map (("; gamma rate category " ++) . show) [1 :: Int ..]
src/ELynx/Data/MarkovProcess/MixtureModel.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE TemplateHaskell #-}- {- | Module      :  ELynx.Data.MarkovProcess.MixtureModel Description :  Mixture models are a set of substitution models with weights@@ -21,7 +19,7 @@     Weight   , Component (Component)   , MixtureModel (MixtureModel)-    -- * Lenses and other accessors+    -- * Getters   , name   , getAlphabet   , getWeights@@ -40,7 +38,6 @@   , summarize   ) where -import           Control.Lens import qualified Data.ByteString.Builder                    as L import qualified Data.ByteString.Lazy.Char8                 as L @@ -53,37 +50,32 @@  -- | A mixture model component has a weight and a substitution model. data Component = Component-  { _weight     :: Weight-  , _substModel :: S.SubstitutionModel+  { weight     :: Weight+  , substModel :: S.SubstitutionModel   }   deriving (Show, Read) -makeLenses ''Component- -- | A mixture model with its components. data MixtureModel = MixtureModel-  { _name       :: S.Name-  , _components :: [Component]+  { name       :: S.Name        -- ^ Name+  , components :: [Component]   }   deriving (Show, Read) -makeLenses ''MixtureModel---- | Get alphabet used with mixture model. Throws error if components use different--- 'Alphabet's.+-- | Get alphabet used with mixture model. Throws error if components use+-- different 'Alphabet's. getAlphabet :: MixtureModel -> Alphabet getAlphabet mm = if isValid mm-            -- then S.alphabet . substModel $ head (components mm)-            then head $ mm ^.. components . traverse . substModel . S.alphabet+            then S.alphabet . substModel $ head (components mm)             else error "Mixture model is invalid."  -- | Get weights. getWeights :: MixtureModel -> [Weight]-getWeights m = m ^.. components . traverse . weight+getWeights = map weight . components  -- | Get substitution models. getSubstitutionModels :: MixtureModel -> [S.SubstitutionModel]-getSubstitutionModels m = m ^.. components . traverse . substModel+getSubstitutionModels = map substModel . components   -- | Create a mixture model from a list of substitution models.@@ -93,11 +85,17 @@  -- | Concatenate mixture models. concatenate :: S.Name -> [MixtureModel] -> MixtureModel-concatenate n mms = MixtureModel n $ concatMap (view components) mms+concatenate n mms = MixtureModel n $ concatMap components mms +scaleComponent :: Double -> Component -> Component+scaleComponent s c = c {substModel = s'}+  where s' = S.scale s $ substModel c+ -- | Scale all substitution models of the mixture model. scale :: Double -> MixtureModel -> MixtureModel-scale s = over (components . traverse . substModel) (S.scale s)+scale s m = m {components = cs'}+  where cs  = components m+        cs' = map (scaleComponent s) cs  -- | Globally normalize a mixture model so that on average one event happens per -- unit time.@@ -107,9 +105,15 @@         weights = getWeights mm         scales  = map S.totalRate $ getSubstitutionModels mm +appendNameComponent :: S.Name -> Component -> Component+appendNameComponent n c = c {substModel = s'}+  where s' = S.appendName n $ substModel c+ -- | Append byte string to all substitution models of mixture model. appendName :: S.Name -> MixtureModel -> MixtureModel-appendName n = over (components . traverse . substModel) (S.appendName n)+appendName n m = m {components = cs'}+  where cs  = components m+        cs' = map (appendNameComponent n) cs  -- | Checks if a mixture model is valid. --@@ -118,19 +122,24 @@ -- and providing an algebraic way of creating mixture models (empty and -- addComponent which performs necessary checks). isValid :: MixtureModel -> Bool-isValid mm = not (null $ mm ^. components)-                         && allEqual alphabets-  where alphabets = mm ^.. components . traverse . substModel . S.alphabet+isValid m = not (null $ components m) && allEqual alphabets+  where alphabets = map (S.alphabet . substModel) $ components m  -- | Summarize a mixture model component; lines to be printed to screen or log. summarizeComponent :: Component -> [L.ByteString]-summarizeComponent mmc =-  L.pack "Weight: " <> (L.toLazyByteString . L.doubleDec $ mmc ^. weight)-  : S.summarize (mmc ^. substModel)+summarizeComponent c =+  L.pack "Weight: " <> (L.toLazyByteString . L.doubleDec $ weight c)+  : S.summarize (substModel c)  -- | Summarize a mixture model; lines to be printed to screen or log. summarize :: MixtureModel -> [L.ByteString]-summarize mm =-  L.pack ("Mixture model: " ++ mm ^. name ++ ".")-  : concat [ L.pack ("Component " ++ show i ++ ":") : summarizeComponent c-            | (i, c) <- zip [1 :: Int ..] (mm ^. components) ]+summarize m =+      [ L.pack $ "Mixture model: " ++ name m ++ "."+      , L.pack $ "Number of components: " ++ show n ++ "." ]+      ++ detail+      where+        n = length $ components m+        detail = if n <= 100+          then concat [ L.pack ("Component " ++ show i ++ ":") : summarizeComponent c+                      | (i, c) <- zip [1 :: Int ..] (components m) ]+          else []
src/ELynx/Data/MarkovProcess/Nucleotide.hs view
@@ -34,6 +34,11 @@  -- data PhyloModel = MixtureModel | SubstitutionModel +--+-- I think it could simply be:+-- data PhyloModel = [(Weight, SubstitutionModel)]+--+ -- data MixtureModel = [(Weight, SubstitutionModel)]  -- data SubstitutionModel = SMDNA DNASubstitutionModel | SMAA AASubstitutionModel
src/ELynx/Data/MarkovProcess/PhyloModel.hs view
@@ -24,7 +24,6 @@   , summarize   ) where -import           Control.Lens import qualified Data.ByteString.Lazy.Char8                 as L  import           ELynx.Data.Alphabet.Alphabet@@ -39,7 +38,7 @@ -- | Extract code from phylogenetic model. getAlphabet :: PhyloModel -> Alphabet getAlphabet (MixtureModel mm)      = M.getAlphabet mm-getAlphabet (SubstitutionModel sm) = sm ^. S.alphabet+getAlphabet (SubstitutionModel sm) = S.alphabet sm  -- | Summarize a phylogenetic model; lines to be printed to screen or log. summarize :: PhyloModel -> [L.ByteString]
src/ELynx/Data/MarkovProcess/SubstitutionModel.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE TemplateHaskell #-}- {- | Module      :  ELynx.Data.MarkovProcess.SubstitutionModel Description :  Data type describing substitution model@@ -26,7 +24,7 @@   , name   , stationaryDistribution   , exchangeabilityMatrix-  , getRateMatrix+  , rateMatrix   , totalRate   -- * Building substitution models   , substitutionModel@@ -39,7 +37,6 @@   , summarize   ) where -import           Control.Lens import qualified Data.ByteString.Lazy.Char8          as L import qualified Numeric.LinearAlgebra               as LinAlg @@ -56,25 +53,26 @@ type Params = [Double]  -- | Complete definition of a substitution model. Create instances with--- 'substitutionModel'.+-- 'substitutionModel'. A substitution model has an alphabet, a name, and a list+-- of parameters (e.g., the kappa value for the HKY model). Further, the+-- transition rate matrix is defined by a stationary distribution and a set of+-- exchangeabilities. data SubstitutionModel = SubstitutionModel-  { _alphabet               :: Alphabet-  , _name                   :: Name-  , _params                 :: Params-  , _stationaryDistribution :: R.StationaryDistribution-  , _exchangeabilityMatrix  :: R.ExchangeabilityMatrix+  { alphabet               :: Alphabet -- ^ Alphabet+  , name                   :: Name     -- ^ Name+  , params                 :: Params   -- ^ List of parameters+  , stationaryDistribution :: R.StationaryDistribution -- ^ Stationary distribution+  , exchangeabilityMatrix  :: R.ExchangeabilityMatrix  -- ^ Exchangeability matrix   }   deriving (Show, Read) -makeLenses ''SubstitutionModel- -- | Calculate rate matrix from substitution model.-getRateMatrix :: SubstitutionModel -> R.RateMatrix-getRateMatrix sm = R.fromExchangeabilityMatrix (sm^.exchangeabilityMatrix) (sm^.stationaryDistribution)+rateMatrix :: SubstitutionModel -> R.RateMatrix+rateMatrix sm = R.fromExchangeabilityMatrix (exchangeabilityMatrix sm) (stationaryDistribution sm)  -- | Get scale of substitution model. totalRate :: SubstitutionModel -> Double-totalRate sm = R.totalRate (sm^.stationaryDistribution) (getRateMatrix sm)+totalRate sm = R.totalRate (stationaryDistribution sm) (rateMatrix sm)  -- | Create normalized 'SubstitutionModel'. See 'normalize'. substitutionModel :: Alphabet -> Name -> Params@@ -90,7 +88,8 @@  -- | Scale the rate of a substitution model by given factor. scale :: Double -> SubstitutionModel -> SubstitutionModel-scale r = over exchangeabilityMatrix (LinAlg.scale r)+scale r sm = sm {exchangeabilityMatrix = em'}+  where em' = LinAlg.scale r $ exchangeabilityMatrix sm  -- | Normalize a substitution model, so that, on average, one substitution -- happens per unit time.@@ -100,19 +99,20 @@  -- | Abbend to name. appendName :: Name -> SubstitutionModel -> SubstitutionModel-appendName n = over name (<> n)+appendName n sm = sm {name = n'}+  where n' = name sm <> n  -- | Summarize a substitution model; lines to be printed to screen or log. summarize :: SubstitutionModel -> [L.ByteString] summarize sm = map L.pack $-  (show (sm^.alphabet) ++ " substitution model: " ++ sm^.name ++ ".") :-  [ "Parameters: " ++ show (sm^.params) ++ "." | not (null (sm^.params))] ++-  case sm^.alphabet of-    DNA -> [ "Stationary distribution: " ++ dispv precision (sm^.stationaryDistribution) ++ "."-           , "Exchangeability matrix:\n" ++ dispmi 2 precision (sm^.exchangeabilityMatrix) ++ "."+  (show (alphabet sm) ++ " substitution model: " ++ name sm ++ ".") :+  [ "Parameters: " ++ show (params sm) ++ "." | not (null (params sm))] +++  case alphabet sm of+    DNA -> [ "Stationary distribution: " ++ dispv precision (stationaryDistribution sm) ++ "."+           , "Exchangeability matrix:\n" ++ dispmi 2 precision (exchangeabilityMatrix sm) ++ "."            , "Scale: " ++ show (roundN precision $ totalRate sm) ++ "."            ]-    Protein -> [ "Stationary distribution: " ++ dispv precision (sm^.stationaryDistribution) ++ "."+    Protein -> [ "Stationary distribution: " ++ dispv precision (stationaryDistribution sm) ++ "."                , "Scale: " ++ show (roundN precision $ totalRate sm) ++ "."                ]     _ -> error "Extended character sets are not supported with substitution models."
+ src/ELynx/Data/Sequence/Alignment.hs view
@@ -0,0 +1,244 @@+{- |+Module      :  ELynx.Data.Sequence.Alignment+Description :  Multi sequence alignment related types and functions+Copyright   :  (c) Dominik Schrempf 2018+License     :  GPL-3++Maintainer  :  dominik.schrempf@gmail.com+Stability   :  unstable++Portability :  portable++Creation date: Thu Oct  4 18:40:18 2018.++This module is to be imported qualified.++-}+++module ELynx.Data.Sequence.Alignment+  ( Alignment (..)+  , length+  , nSequences+  -- | * Input, output+  , fromSequences+  , toSequences+  , summarize+  -- | * Manipulation+  , join+  , concat+  , concatAlignments+  , filterColsOnlyStd+  , filterColsStd+  , filterColsNoGaps+  -- | * Analysis+  , FrequencyData+  , distribution+  , toFrequencyData+  , kEffEntropy+  , kEffHomoplasy+  , countIUPACChars+  , countGaps+  , countUnknowns+  -- | * Sub sample+  , subSample+  , randomSubSample+  ) where++import           Control.Monad                             hiding (join)+import           Control.Monad.Primitive+import qualified Data.ByteString.Lazy.Char8                as L+import           Data.List                                 hiding (concat,+                                                            length)+import qualified Data.Matrix.Unboxed                       as M+import qualified Data.Vector.Unboxed                       as V+import           Prelude                                   hiding (concat,+                                                            length)+import           System.Random.MWC++import qualified ELynx.Data.Alphabet.Alphabet              as A+import           ELynx.Data.Alphabet.Character+import qualified ELynx.Data.Alphabet.DistributionDiversity as D+import           ELynx.Data.Sequence.Defaults+import qualified ELynx.Data.Sequence.Sequence              as S+import           ELynx.Tools.Concurrent+import           ELynx.Tools.Definitions+import           ELynx.Tools.Equality+import           ELynx.Tools.Matrix++-- | A collection of sequences.+data Alignment = Alignment+                              { names    :: [S.Name]+                              , alphabet :: A.Alphabet+                              , matrix   :: M.Matrix Character+                              }+  deriving (Show, Eq)++-- | Number of sites.+length :: Alignment -> Int+length = M.cols . matrix++-- | Number of sequences.+nSequences :: Alignment -> Int+nSequences = M.rows . matrix++-- | Create 'Alignment' from a list of 'S.Sequence's.+fromSequences :: [S.Sequence] -> Either String Alignment+fromSequences ss+  | S.equalLength ss && allEqual (map S.alphabet ss) =+      Right $ Alignment ns a d+  | S.equalLength ss =+      Left "Sequences do not have equal codes."+  | otherwise =+      Left "Sequences do not have equal lengths."+  where+    ns   = map S.name ss+    a    = S.alphabet $ head ss+    bss  = map S.characters ss+    d    = M.fromRows bss++-- | Conversion to list of 'S.Sequence's.+toSequences :: Alignment -> [S.Sequence]+toSequences (Alignment ns a d) = zipWith (\n r -> S.Sequence n a r) ns rows+  where+    rows  = M.toRows d++-- -- | Show a 'Alignment', untrimmed.+-- summarizeSeq :: Alignment -> Int -> L.ByteString+-- summarizeSeq m i =+--   L.unwords [ alignLeft nameWidth $ names m !! i+--             , summarizeByteString summaryLength $+--               L.pack $ V.toList $ V.map toChar $ M.takeRow (matrix m) i ]++header :: Alignment -> L.ByteString+header a = L.unlines $+  [ L.pack "Multi sequence alignment."+  , L.pack $ "Code: " ++ A.description (alphabet a) ++ "."+  , L.pack $ "Length: " ++ show (length a) ++ "." ]+  ++ reportLengthSummary ++ reportNumberSummary+  where reportLengthSummary =+          [ L.pack $ "For each sequence, the "+            ++ show summaryLength ++ " first bases are shown."+          | length a > summaryLength ]+        reportNumberSummary =+          [ L.pack $ show summaryNSequences ++ " out of " +++            show (nSequences a) ++ " sequences are shown."+          | nSequences a > summaryNSequences ]++-- | Similar to 'S.summarizeSequenceList' but with different Header.+summarize :: Alignment -> L.ByteString+summarize a = header a <> S.body (toSequences a)++-- | Join two 'Alignment's vertically. That is, add more sequences+-- to an alignment. See also 'concat'.+join :: Alignment+     -> Alignment+     -> Alignment+-- top bottom.+join t b+  | length t == length b &&+    al       == alphabet b+  = Alignment ns al (tD === bD)+  | otherwise  = error "join: Multi sequence alignments do not have equal length."+  where+    ns = names t ++ names b+    tD = matrix t+    bD = matrix b+    al = alphabet t++-- | Concatenate two 'Alignment's horizontally. That is, add more+-- sites to an alignment. See also 'join'.+concat :: Alignment+       -> Alignment+       -> Alignment+-- left right.+concat l r+  | nSequences l == nSequences r &&+    al           == alphabet r+  = Alignment (names l) al (lD ||| rD)+  | otherwise = error "concat: Multi sequence alignments do not have equal length."+  where+    lD = matrix l+    rD = matrix r+    al = alphabet l++-- | Concatenate a list of 'Alignment's horizontally. See+-- 'concat'.+concatAlignments :: [Alignment] -> Alignment+concatAlignments []  = error "concatAlignments: Nothing to concatenate."+concatAlignments [a] = a+concatAlignments as  = foldl' concat (head as) (tail as)++-- Only keep columns from alignment that satisfy given predicate.+filterColsWith :: (V.Vector Character -> Bool) -> Alignment -> Alignment+filterColsWith p a =  a {matrix = m'}+  where m' = M.fromColumns . filter p . M.toColumns $ matrix a++-- | Only keep columns with standard characters. Alignment columns with IUPAC+-- characters are removed.+filterColsOnlyStd :: Alignment -> Alignment+filterColsOnlyStd a = filterColsWith (V.all $ A.isStd (alphabet a)) a++-- | Filter columns with proportion of standard character larger than given number.+filterColsStd :: Double -> Alignment -> Alignment+filterColsStd prop a = filterColsWith+  (\col -> prop * n <= fromIntegral (V.length (V.filter (A.isStd al) col))) a+  where al = alphabet a+        n = fromIntegral $ nSequences a++-- | Only keep columns without gaps or unknown characters.+filterColsNoGaps :: Alignment -> Alignment+filterColsNoGaps a = filterColsWith (V.all $ not . A.isGap (alphabet a)) a++-- | Frequency data; do not store the actual characters, but their frequencies.+-- The matrix is of size @N x K@, where @N@ is the number of sites, and @K@ is+-- the number of characters.+type FrequencyData = M.Matrix Double++-- | Calculcate frequency of characters at each site of a multi sequence alignment.+toFrequencyData :: Alignment -> FrequencyData+toFrequencyData a = fMapColParChunk 100 (D.frequencyCharacters spec) (matrix a)+  where spec = A.alphabetSpec (alphabet a)++-- | Calculate the distribution of characters.+distribution :: FrequencyData -> [Double]+distribution fd = map (/ fromIntegral nSites) $ V.toList $+  foldl1 (V.zipWith (+)) (M.toColumns fd)+  where nSites = M.cols fd++-- | Diversity analysis. See 'kEffEntropy'.+kEffEntropy :: FrequencyData -> [Double]+kEffEntropy fd = parMapChunk chunksize D.kEffEntropy (M.toColumns fd)++-- | Diversity analysis. See 'kEffEntropy'.+kEffHomoplasy :: FrequencyData -> [Double]+kEffHomoplasy fd = parMapChunk chunksize D.kEffHomoplasy (M.toColumns fd)++-- | Count the number of standard (i.e., not extended IUPAC) characters in the+-- alignment.+countIUPACChars :: Alignment -> Int+countIUPACChars a = V.length . V.filter (A.isIUPAC (alphabet a)) $ allChars+  where allChars = M.flatten $ matrix a++-- | Count the number of gaps in the alignment.+countGaps :: Alignment -> Int+countGaps a = V.length . V.filter (A.isGap (alphabet a)) $ allChars+  where allChars = M.flatten $ matrix a++-- | Count the number of unknown characters in the alignment.+countUnknowns :: Alignment -> Int+countUnknowns a = V.length . V.filter (A.isUnknown (alphabet a)) $ allChars+  where allChars = M.flatten $ matrix a++-- | Sample the given sites from a multi sequence alignment.+subSample :: [Int] -> Alignment -> Alignment+subSample is a = a {matrix = m'}+  where m' = subSampleMatrix is $ matrix a++-- | Randomly sample a given number of sites of the multi sequence alignment.+randomSubSample :: PrimMonad m+          => Int -> Alignment  -> Gen (PrimState m) -> m Alignment+randomSubSample n a g = do+  let l = length a+  is <- replicateM n $ uniformR (0, l-1) g+  return $ subSample is a
src/ELynx/Data/Sequence/Defaults.hs view
@@ -14,24 +14,24 @@   module ELynx.Data.Sequence.Defaults-  ( defSequenceNameWidth-  , defSequenceSummaryLength-  , defSequenceListSummaryNumber-  , defFieldWidth+  ( nameWidth+  , summaryLength+  , summaryNSequences+  , fieldWidth   ) where  -- | Space reserved for sequence names when printing them.-defSequenceNameWidth :: Int-defSequenceNameWidth = 23+nameWidth :: Int+nameWidth = 23  -- | The length shown when summarizing sequences.-defSequenceSummaryLength :: Int-defSequenceSummaryLength = 60+summaryLength :: Int+summaryLength = 60  -- | How many sequences are shown in summary.-defSequenceListSummaryNumber :: Int-defSequenceListSummaryNumber = 200+summaryNSequences :: Int+summaryNSequences = 200  -- | Field width for tables.-defFieldWidth :: Int-defFieldWidth = 13+fieldWidth :: Int+fieldWidth = 13
− src/ELynx/Data/Sequence/MultiSequenceAlignment.hs
@@ -1,253 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--{- |-Module      :  ELynx.Data.MultiSequenceAlignment-Description :  Multi sequence alignment related types and functions-Copyright   :  (c) Dominik Schrempf 2018-License     :  GPL-3--Maintainer  :  dominik.schrempf@gmail.com-Stability   :  unstable--Portability :  portable--Creation date: Thu Oct  4 18:40:18 2018.---}---module ELynx.Data.Sequence.MultiSequenceAlignment-  ( MultiSequenceAlignment (MultiSequenceAlignment)-  , msaLength-  , msaNSequences-  -- | * Input, output-  , fromSequenceList-  , toSequenceList-  , showMSA-  , summarizeMSA-  -- | * Manipulation-  , msaJoin-  , msaConcatenate-  , msasConcatenate-  , filterColumnsOnlyStd-  , filterColumnsStd-  , filterColumnsNoGaps-  -- | * Analysis-  , FrequencyData-  , toFrequencyData-  , kEffEntropy-  , kEffHomoplasy-  , countIUPACChars-  , countGaps-  , countUnknowns-  -- | * Sub sample-  , subSample-  , randomSubSample-  ) where--import           Control.Lens-import           Control.Monad-import           Control.Monad.Primitive-import qualified Data.ByteString.Lazy.Char8                as L-import           Data.List-import qualified Data.Matrix.Unboxed                       as M-import qualified Data.Vector.Unboxed                       as V-import           System.Random.MWC--import qualified ELynx.Data.Alphabet.Alphabet              as A-import           ELynx.Data.Alphabet.Character-import qualified ELynx.Data.Alphabet.DistributionDiversity as D-import           ELynx.Data.Sequence.Defaults-import qualified ELynx.Data.Sequence.Sequence              as S-import           ELynx.Tools.ByteString-import           ELynx.Tools.Concurrent-import           ELynx.Tools.Equality-import           ELynx.Tools.Matrix---- | A collection of sequences.-data MultiSequenceAlignment = MultiSequenceAlignment-                              { _names    :: [S.SequenceName]-                              , _alphabet :: A.Alphabet-                              , _matrix   :: M.Matrix Character-                              }-  deriving (Read, Show, Eq)--makeLenses ''MultiSequenceAlignment---- | Number of sites.-msaLength :: MultiSequenceAlignment -> Int-msaLength = M.cols . view matrix---- | Number of sequences.-msaNSequences :: MultiSequenceAlignment -> Int-msaNSequences = M.rows . view matrix---- | Create 'MultiSequenceAlignment' from a list of 'S.Sequence's.-fromSequenceList :: [S.Sequence] -> Either String MultiSequenceAlignment-fromSequenceList ss-  | S.equalLength ss && allEqual (map (view S.alphabet) ss) =-      Right $ MultiSequenceAlignment ns a d-  | S.equalLength ss =-      Left "Sequences do not have equal codes."-  | otherwise =-      Left "Sequences do not have equal lengths."-  where-    ns   = map (view S.name) ss-    a    = head ss ^. S.alphabet-    bss  = map (view S.characters) ss-    d    = M.fromRows bss---- | Conversion to list of 'S.Sequence's.-toSequenceList :: MultiSequenceAlignment -> [S.Sequence]-toSequenceList (MultiSequenceAlignment ns a d) = zipWith (\n r -> S.Sequence n a r) ns rows-  where-    rows  = M.toRows d--msaHeader :: L.ByteString-msaHeader = L.unwords [ alignLeft defSequenceNameWidth (L.pack "Name")-                      , L.pack "Sequence" ]---- | Show a 'S.Sequence', untrimmed.-showSequence :: MultiSequenceAlignment -> Int -> L.ByteString-showSequence m i =-  L.unwords [ alignLeft defSequenceNameWidth $ (m ^. names) !! i-            , S.fromCharacters $ M.takeRow (m ^. matrix) i ]---- | Show a 'S.Sequence', untrimmed.-summarizeSequence :: MultiSequenceAlignment -> Int -> L.ByteString-summarizeSequence m i =-  L.unwords [ alignLeft defSequenceNameWidth $ (m ^. names) !! i-            , summarizeByteString defSequenceSummaryLength $-              S.fromCharacters $ M.takeRow (m ^. matrix) i ]---- | Show a 'MultiSequenceAlignment' in text form.-showMSA :: MultiSequenceAlignment -> L.ByteString-showMSA msa = L.unlines $ msaHeader :-  map (showSequence msa) [0 .. (msaNSequences msa - 1)]--summarizeMSAHeader :: MultiSequenceAlignment -> L.ByteString-summarizeMSAHeader msa = L.unlines $-  [ L.pack "Multi sequence alignment."-  , L.pack $ "Code: " ++ A.alphabetNameVerbose (msa^.alphabet) ++ "."-  , L.pack $ "Length: " ++ show (msaLength msa) ++ "." ]-  ++ reportLengthSummary ++ reportNumberSummary-  where reportLengthSummary =-          [ L.pack $ "For each sequence, the "-            ++ show defSequenceSummaryLength ++ " first bases are shown."-          | msaLength msa > defSequenceSummaryLength ]-        reportNumberSummary =-          [ L.pack $ show defSequenceListSummaryNumber ++ " out of " ++-            show (msaNSequences msa) ++ " sequences are shown."-          | msaNSequences msa > defSequenceListSummaryNumber ]---- | Similar to 'S.summarizeSequenceList' but with different Header.-summarizeMSA :: MultiSequenceAlignment -> L.ByteString-summarizeMSA msa = L.unlines $ summarizeMSAHeader msa :-  map (summarizeSequence msa) [0 .. n - 1]-  where n = min (msaNSequences msa) defSequenceListSummaryNumber---- | Join two 'MultiSequenceAlignment's vertically. That is, add more sequences--- to an alignment. See also 'msaConcatenate'.-msaJoin :: MultiSequenceAlignment-        -> MultiSequenceAlignment-        -> MultiSequenceAlignment--- top bottom.-msaJoin t b-  | msaLength t == msaLength b-    && t^.alphabet == b^.alphabet-  = MultiSequenceAlignment ns a (tD === bD)-  | otherwise  = error "msaJoin: Multi sequence alignments do not have equal length."-  where-    ns = t^.names ++ b^.names-    tD = t^.matrix-    bD = t^.matrix-    a  = t^.alphabet---- | Concatenate two 'MultiSequenceAlignment's horizontally. That is, add more--- sites to an alignment. See also 'msaJoin'.-msaConcatenate :: MultiSequenceAlignment-               -> MultiSequenceAlignment-               -> MultiSequenceAlignment--- left right.-msaConcatenate l r-  | msaNSequences l == msaNSequences r-    && l^.alphabet == r^.alphabet-  = MultiSequenceAlignment (l ^. names) a (lD ||| rD)-  | otherwise = error "msaConcatenate: Multi sequence alignments do not have equal length."-  where-    lD = l^.matrix-    rD = r^.matrix-    a  = l^.alphabet---- | Concatenate a list of 'MultiSequenceAlignment's horizontally. See--- 'msaConcatenate'.-msasConcatenate :: [MultiSequenceAlignment] -> MultiSequenceAlignment-msasConcatenate []    = error "msasConcatenate: Nothing to concatenate."-msasConcatenate [msa] = msa-msasConcatenate msas  = foldl' msaConcatenate (head msas) (tail msas)---- Only keep columns from alignment that satisfy given predicate.-filterColumnsWith :: (V.Vector Character -> Bool) -> MultiSequenceAlignment -> MultiSequenceAlignment-filterColumnsWith p = over matrix (M.fromColumns . filter p . M.toColumns)---- | Only keep columns with standard characters. Alignment columns with IUPAC--- characters are removed.-filterColumnsOnlyStd :: MultiSequenceAlignment -> MultiSequenceAlignment-filterColumnsOnlyStd msa = filterColumnsWith (V.all $ A.isStd (msa^.alphabet)) msa---- | Filter columns with proportion of standard character larger than given number.-filterColumnsStd :: Double -> MultiSequenceAlignment -> MultiSequenceAlignment-filterColumnsStd prop msa = filterColumnsWith-  (\col -> prop * nSeqs <= fromIntegral (V.length (V.filter (A.isStd a) col)))-  msa-  where a = msa^.alphabet-        nSeqs = fromIntegral $ msaNSequences msa---- | Only keep columns without gaps or unknown characters.-filterColumnsNoGaps :: MultiSequenceAlignment -> MultiSequenceAlignment-filterColumnsNoGaps msa = filterColumnsWith (V.all $ not . A.isGap (msa^.alphabet)) msa---- | Frequency data; do not store the actual characters, but only their--- frequencies.-type FrequencyData = M.Matrix Double---- | Calculcate frequency of characters in multi sequence alignment.-toFrequencyData :: MultiSequenceAlignment -> FrequencyData-toFrequencyData msa = fMapColParChunk 100 (D.frequencyCharacters spec) (msa^.matrix)-  where spec = A.alphabetSpec (msa^.alphabet)---- | Diversity analysis. See 'kEffEntropy'.-kEffEntropy :: FrequencyData -> [Double]-kEffEntropy fd = parMapChunk 500 D.kEffEntropy (M.toColumns fd)---- | Diversity analysis. See 'kEffEntropy'.-kEffHomoplasy :: FrequencyData -> [Double]-kEffHomoplasy fd = parMapChunk 500 D.kEffHomoplasy (M.toColumns fd)---- | Count the number of standard (i.e., not extended IUPAC) characters in the--- alignment.-countIUPACChars :: MultiSequenceAlignment -> Int-countIUPACChars msa = V.length . V.filter (A.isIUPAC (msa^.alphabet)) $ allChars-  where allChars = M.flatten $ msa^.matrix---- | Count the number of gaps in the alignment.-countGaps :: MultiSequenceAlignment -> Int-countGaps msa = V.length . V.filter (A.isGap (msa^.alphabet)) $ allChars-  where allChars = M.flatten $ msa^.matrix---- | Count the number of unknown characters in the alignment.-countUnknowns :: MultiSequenceAlignment -> Int-countUnknowns msa = V.length . V.filter (A.isUnknown (msa^.alphabet)) $ allChars-  where allChars = M.flatten $ msa^.matrix---- | Sample the given sites from a multi sequence alignment.-subSample :: [Int] -> MultiSequenceAlignment -> MultiSequenceAlignment-subSample is = over matrix (subSampleMatrix is)---- | Randomly sample a given number of sites of the multi sequence alignment.-randomSubSample :: PrimMonad m-          => Int -> MultiSequenceAlignment  -> Gen (PrimState m) -> m MultiSequenceAlignment-randomSubSample n msa g = do-  let l = msaLength msa-  is <- replicateM n $ uniformR (0, l-1) g-  return $ subSample is msa
src/ELynx/Data/Sequence/Sequence.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE OverloadedStrings #-}  {- | Module      :  ELynx.Data.Sequence@@ -12,46 +12,44 @@  Creation date: Thu Oct  4 18:54:51 2018. +This module is to be imported qualified.+ -}  module ELynx.Data.Sequence.Sequence   ( -- * Types-    SequenceName-  , SequenceCharacters-  , Sequence (Sequence)-  -- * Lenses-  , name-  , alphabet-  , characters+    Name+  , Characters+  , Sequence (..)   -- * Input-  , toCharacters+  , fromByteString   -- * Output-  , fromCharacters-  , showSequence-  , showSequenceList-  , sequenceListHeader-  , summarizeSequence-  , summarizeSequenceList-  , summarizeSequenceListBody+  , toByteString+  , header+  , summarize+  , summarizeSequences+  , body   -- * Analysis-  , lengthSequence+  , length   , equalLength   , longest   -- * Manipulation-  , trimSequence-  , concatenate-  , concatenateSeqs+  , trim+  , concat+  , concatSequences   -- * Filtering   , filterShorterThan   , filterLongerThan+  , filterStandard   ) where -import           Control.Lens import           Control.Parallel.Strategies import qualified Data.ByteString.Lazy.Char8    as L import           Data.List                     (maximumBy) import           Data.Ord                      (comparing) import qualified Data.Vector.Unboxed           as V+import           Prelude                       hiding (concat, length)+import qualified Prelude                       as Pr (length) import qualified Text.Printf                   as P  import qualified ELynx.Data.Alphabet.Alphabet  as A@@ -60,122 +58,116 @@ import           ELynx.Tools.ByteString import           ELynx.Tools.Equality --- | For now, 'SequenceName's are just 'L.ByteString's.-type SequenceName = L.ByteString+-- | For now, 'Name's are just 'L.ByteString's.+type Name = L.ByteString  -- | The vector of characters of a sequence.-type SequenceCharacters = V.Vector Character---- | Sequences have a name, a code and hopefully a lot of data.-data Sequence = Sequence { _name       :: SequenceName-                         , _alphabet   :: A.Alphabet-                         , _characters :: SequenceCharacters }-  deriving (Eq)--makeLenses ''Sequence+type Characters = V.Vector Character  -- | Convert byte string to sequence characters.-toCharacters :: L.ByteString -> SequenceCharacters-toCharacters = V.fromList . map fromChar . L.unpack+fromByteString :: L.ByteString -> Characters+fromByteString = V.fromList . map fromChar . L.unpack  -- | Convert sequence characters to byte string.-fromCharacters :: SequenceCharacters -> L.ByteString-fromCharacters = L.pack . map toChar . V.toList+toByteString :: Characters -> L.ByteString+toByteString = L.pack . map toChar . V.toList -showInfo :: Sequence -> L.ByteString-showInfo s = L.unwords [ alignLeft defSequenceNameWidth (s^.name)-                       , alignRight defFieldWidth (L.pack $ show $ s^.alphabet)-                       , alignRight defFieldWidth (L.pack . show $ len)-                       , alignRight defFieldWidth (L.pack $ P.printf "%.3f" pGaps) ]-  where len = lengthSequence s+-- | Sequences have a name, a code and hopefully a lot of data.+data Sequence = Sequence { name       :: Name+                         , alphabet   :: A.Alphabet+                         , characters :: Characters }+  deriving (Show, Eq)++getInfo :: Sequence -> L.ByteString+getInfo s = L.unwords [ alignLeft nameWidth (name s)+                      , alignRight fieldWidth (L.pack $ show $ alphabet s)+                      , alignRight fieldWidth (L.pack . show $ len)+                      , alignRight fieldWidth (L.pack $ P.printf "%.3f" pGaps) ]+  where len = length s         nGaps = countGaps s         pGaps = fromIntegral nGaps / fromIntegral len :: Double -instance Show Sequence where-  show s = L.unpack $ showSequence s---- | Show a 'Sequence', untrimmed.-showSequence :: Sequence -> L.ByteString-showSequence s = L.unwords [showInfo s, fromCharacters $ s^.characters]---- | Show a list of 'Sequence's, untrimmed.-showSequenceList :: [Sequence] -> L.ByteString-showSequenceList = L.unlines . map showSequence---- | Header printed before 'Sequence' list.-sequenceListHeader :: L.ByteString-sequenceListHeader = L.unwords [ alignLeft defSequenceNameWidth (L.pack "Name")-                               , alignRight defFieldWidth (L.pack "Code")-                               , alignRight defFieldWidth (L.pack "Length")-                               , alignRight defFieldWidth (L.pack "Gaps [%]")-                               , L.pack "Sequence" ]- -- | Trim and show a 'Sequence'.-summarizeSequence :: Sequence -> L.ByteString-summarizeSequence s = L.unwords [ showInfo s-                                , summarizeByteString defSequenceSummaryLength-                                  (fromCharacters $ s^.characters) ]+summarize :: Sequence -> L.ByteString+summarize s = L.unwords [ getInfo s , summarizeByteString summaryLength $ toByteString (characters s) ]  -- | Trim and show a list of 'Sequence's.-summarizeSequenceList :: [Sequence] -> L.ByteString-summarizeSequenceList ss = summarizeSequenceListHeader ss <>-                           summarizeSequenceListBody (take defSequenceListSummaryNumber ss)+summarizeSequences :: [Sequence] -> L.ByteString+summarizeSequences ss = header ss <> body (take summaryNSequences ss) -summarizeSequenceListHeader :: [Sequence] -> L.ByteString-summarizeSequenceListHeader ss = L.unlines $+-- | Header printed before 'Sequence' list.+tableHeader :: L.ByteString+tableHeader = L.unwords [ alignLeft  nameWidth "Name"+                        , alignRight fieldWidth        "Code"+                        , alignRight fieldWidth        "Length"+                        , alignRight fieldWidth        "Gaps [%]"+                        , "Sequence" ]++-- | A short description of the sequence.+header :: [Sequence] -> L.ByteString+header ss = L.unlines $   reportIfSubsetIsShown ++-  [ L.pack $ "For each sequence, the " ++ show defSequenceSummaryLength ++ " first bases are shown."-  , L.pack $ "List contains " ++ show (length ss) ++ " sequences."-  , L.pack ""-  , sequenceListHeader ]-  where l = length ss-        s = show defSequenceListSummaryNumber ++ " out of " ++-            show (length ss) ++ " sequences are shown."+  [ L.pack $ "For each sequence, the " ++ show summaryLength ++ " first bases are shown."+  , L.pack $ "List contains " ++ show (Pr.length ss) ++ " sequences."+  , ""+  , tableHeader ]+  where l = Pr.length ss+        s = show summaryNSequences ++ " out of " +++            show (Pr.length ss) ++ " sequences are shown."         reportIfSubsetIsShown-          | l > defSequenceListSummaryNumber = [L.pack s]+          | l > summaryNSequences = [L.pack s]           | otherwise = []  -- | Trim and show a list of 'Sequence's.-summarizeSequenceListBody :: [Sequence] -> L.ByteString-summarizeSequenceListBody ss = L.unlines (map summarizeSequence ss `using` parListChunk 5 rdeepseq)+body :: [Sequence] -> L.ByteString+body ss = L.unlines (map summarize ss `using` parListChunk 5 rdeepseq)  -- | Calculate length of 'Sequence'.-lengthSequence :: Sequence -> Int-lengthSequence s = fromIntegral $ V.length $ s ^. characters+length :: Sequence -> Int+length = fromIntegral . V.length . characters  -- | Check if all 'Sequence's have equal length. equalLength :: [Sequence] -> Bool-equalLength = allEqual . map lengthSequence+equalLength = allEqual . map length  -- | Find the longest 'Sequence' in a list. longest :: [Sequence] -> Sequence-longest = maximumBy (comparing lengthSequence)+longest = maximumBy (comparing length)  -- | Count number of gaps or unknown characters in sequence. countGaps :: Sequence -> Int-countGaps s = V.length . V.filter (A.isGap (s^.alphabet)) $ s^.characters+countGaps s = V.length . V.filter (A.isGap $ alphabet s) $ characters s  -- | Trim to given length.-trimSequence :: Int -> Sequence -> Sequence-trimSequence n = over characters (V.take $ fromIntegral n)+trim :: Int -> Sequence -> Sequence+trim n (Sequence nm a cs) = Sequence nm a (V.take (fromIntegral n) cs) --- | Concatenate two sequences. 'SequenceName's have to match.-concatenate :: Sequence -> Sequence -> Sequence-concatenate (Sequence i c cs) (Sequence j k ks)+-- | Concatenate two sequences. 'Name's have to match.+concat :: Sequence -> Sequence -> Sequence+concat (Sequence i c cs) (Sequence j k ks)   | i == j && c == k = Sequence i c (cs <> ks)   | otherwise        = error $ "concatenate: Sequences do not have equal names: "                        ++ L.unpack i ++ ", " ++ L.unpack j ++ "." --- | Concatenate a list of sequences, see 'concatenate'.-concatenateSeqs :: [[Sequence]] -> [Sequence]-concatenateSeqs []   = error "concatenateSeqs: Nothing to concatenate."-concatenateSeqs [ss] = ss-concatenateSeqs sss  = foldl1 (zipWith concatenate) sss+-- | Concatenate a list of sequences, see 'concat'.+concatSequences :: [[Sequence]] -> [Sequence]+concatSequences []   = error "concatenateSequences: Nothing to concatenate."+concatSequences [ss] = ss+concatSequences sss  = foldl1 (zipWith concat) sss  -- | Only take 'Sequence's that are shorter than a given number. filterShorterThan :: Int -> [Sequence] -> [Sequence]-filterShorterThan n = filter (\x -> lengthSequence x < n)+filterShorterThan n = filter (\x -> length x < n)  -- | Only take 'Sequence's that are longer than a given number. filterLongerThan :: Int -> [Sequence] -> [Sequence]-filterLongerThan n = filter (\x -> lengthSequence x > n)+filterLongerThan n = filter (\x -> length x > n)++-- | Only take 'Sequence's that contain at least on non-IUPAC character.+filterStandard :: [Sequence] -> [Sequence]+filterStandard = filter (\s -> anyStandard (alphabet s) s)++-- Are all characters IUPAC characters?+anyStandard :: A.Alphabet -> Sequence -> Bool+anyStandard a s = V.any (A.isStd a) cs+  where cs = characters s
src/ELynx/Data/Sequence/Translate.hs view
@@ -37,8 +37,8 @@ -- Translate from DNA to Protein with given reading frame (0, 1, 2). translateVecWith :: (V.Unbox a, Ord a, V.Unbox b)               => (Codon a -> b) -> Int -> V.Vector a -> V.Vector b-translateVecWith f rf cs | rf > 2    = error "translate: reading frame is larger than 2."-                         | rf < 0    = error "translate: reading frame is negative."+translateVecWith f rf cs | rf > 2    = error "translateVecWith: reading frame is larger than 2."+                         | rf < 0    = error "translateVecWith: reading frame is negative."                          | otherwise  = aas   where codons = map unsafeFromVec $ chop 3 $ V.drop rf cs         aas = V.fromList $ map f codons
src/ELynx/Export/Sequence/Fasta.hs view
@@ -21,7 +21,6 @@   , sequencesToFasta   ) where -import           Control.Lens import qualified Data.ByteString.Lazy.Char8   as L  import           ELynx.Data.Sequence.Sequence@@ -31,7 +30,7 @@  -- | Convert a 'Sequence' to Fasta format. sequenceToFasta :: Sequence -> L.ByteString-sequenceToFasta s = L.unlines [ fastaHeader $ s^.name , fromCharacters $ s^.characters ]+sequenceToFasta s = L.unlines [ fastaHeader $ name s, toByteString $ characters s ]  -- | Convert a list 'Sequence's to Fasta format. A newline is added between any -- two 'Sequence's.
+ src/ELynx/Import/MarkovProcess/SiteprofilesPhylobayes.hs view
@@ -0,0 +1,77 @@+{- |+Module      :  ELynx.Import.MarkovProcess.SiteprofilesPhylobayes+Description :  Import site profiles in Phylobayes format+Copyright   :  (c) Dominik Schrempf 2019+License     :  GPL-3++Maintainer  :  dominik.schrempf@gmail.com+Stability   :  unstable+Portability :  portable++Creation date: Tue Jan 29 12:12:55 2019.++For now I just try to go with a huge empirical distribution mixture model. Let's+see if performance is good enough.++-}++module ELynx.Import.MarkovProcess.SiteprofilesPhylobayes+  ( Parser+  , EDMComponent+  , siteprofiles+  ) where++import           Control.Monad+import qualified Data.ByteString.Lazy.Char8        as L+import           Data.List                         (nub)+import qualified Data.Vector.Storable              as V+import           Data.Void+import           Text.Megaparsec+import           Text.Megaparsec.Byte+import           Text.Megaparsec.Byte.Lexer++import           ELynx.Data.MarkovProcess.EDMModel+import           ELynx.Tools.ByteString            (c2w)++-- | Shortcut.+type Parser = Parsec Void L.ByteString++-- | Parse stationary distributions from Phylobayes format.+siteprofiles :: Parser [EDMComponent]+siteprofiles = do+  _  <- headerLines+  cs <- many dataLine+  _  <- many newline *> eof+     <?> "phylobayes siteprofiles"+  let ls = map length cs+      nLs = length $ nub ls+  when (nLs /= 1) (error "The site profiles have a different number of entries.")+  return cs++horizontalSpace :: Parser ()+horizontalSpace = skipMany $ char (c2w ' ') <|> tab++line :: Parser ()+line = do+  _ <- many $ noneOf [c2w '\n']+  pure ()++-- For now, just ignore the header.+headerLines :: Parser ()+headerLines = do+  _ <- line+  _ <- many newline+    <?> "headerLine"+  pure ()++dataLine :: Parser EDMComponent+dataLine = do+  -- Ignore site number.+  _ <- decimal :: Parser Integer+  _ <- horizontalSpace+  -- Also ignore additional white space on line.+  vals <- float `sepEndBy1` horizontalSpace+  _ <- many newline+    <?> "dataLine"+  -- Set the weight to 1.0 for all sites.+  return (1.0, V.fromList vals)
src/ELynx/Import/Sequence/Fasta.hs view
@@ -20,7 +20,8 @@   module ELynx.Import.Sequence.Fasta-  ( fastaSequence+  ( Parser+  , fastaSequence   , fasta   ) where @@ -72,7 +73,7 @@                      let !alph  = S.map toWord (A.all . alphabetSpec $ a)                      lns <- some (sequenceLine alph)                      _  <- many eol-                     return $ Sequence hd a (toCharacters $ L.concat lns)+                     return $ Sequence hd a (fromByteString $ L.concat lns)  -- | Parse a Fasta file with given 'Alphabet'. fasta :: Alphabet -> Parser [Sequence]
src/ELynx/Simulate/MarkovProcess.hs view
@@ -37,8 +37,8 @@ probMatrix :: RateMatrix -> Double -> ProbMatrix probMatrix q t | t == 0 = if rows q == cols q                           then ident (rows q)-                          else error "Matrix is not square."-               | t < 0 = error "Time is negative."+                          else error "probMatrix: Matrix is not square."+               | t < 0 = error "probMatrix: Time is negative."                | otherwise = expm $ scale t q  -- | Move from a given state to a new one according to a transition probability@@ -48,7 +48,6 @@ -- This function is the bottleneck of the simulator and takes up most of the -- computation time. However, I was not able to find a faster implementation -- than the one from Data.Distribution.--- jump :: (PrimMonad m) => State -> ProbMatrix -> Gen (PrimState m) -> m State jump i p = categorical (p ! i) 
src/ELynx/Simulate/MarkovProcessAlongTree.hs view
@@ -1,5 +1,5 @@ {- |-   Description :  Functions to work with transition probability matrices on rooted trees+   Description :  Work with transition probability matrices on rooted trees    Copyright   :  (c) Dominik Schrempf 2017    License     :  GPLv3 @@ -17,27 +17,30 @@  module ELynx.Simulate.MarkovProcessAlongTree   ( -- * Single rate matrix.-    simulateNSitesAlongTree-  , simulateAndFlattenNSitesAlongTree+    simulate+  , simulateAndFlatten     -- * Mixture models.-  , simulateNSitesAlongTreeMixtureModel-  , simulateAndFlattenNSitesAlongTreeMixtureModel+  , simulateMixtureModel+  , simulateAndFlattenMixtureModel+  , simulateAndFlattenMixtureModelPar   )   where  import           Control.Monad import           Control.Monad.Primitive+import           Control.Parallel.Strategies import           Data.Tree import           Numeric.LinearAlgebra-import           System.Random.MWC-import           System.Random.MWC.Distributions+import           System.Random.MWC                   (Gen, GenIO)+import           System.Random.MWC.Distributions     (categorical)  import           ELynx.Data.MarkovProcess.RateMatrix import           ELynx.Data.Tree.MeasurableTree import           ELynx.Simulate.MarkovProcess+import           ELynx.Tools.Concurrent -measureableTreeToProbTree :: (Measurable a) => RateMatrix -> Tree a -> Tree ProbMatrix-measureableTreeToProbTree q = fmap (probMatrix q . getLen)+toProbTree :: (Measurable a) => RateMatrix -> Tree a -> Tree ProbMatrix+toProbTree q = fmap (probMatrix q . getLen)  getRootStates :: PrimMonad m   => Int -> StationaryDistribution -> Gen (PrimState m) -> m [State]@@ -46,48 +49,48 @@ -- | Simulate a number of sites for a given substitution model. Only the states -- at the leafs are retained. The states at internal nodes are removed. This has -- a lower memory footprint.-simulateAndFlattenNSitesAlongTree :: (PrimMonad m, Measurable a)+simulateAndFlatten :: (PrimMonad m, Measurable a)   => Int -> StationaryDistribution -> ExchangeabilityMatrix -> Tree a -> Gen (PrimState m) -> m [[State]]-simulateAndFlattenNSitesAlongTree n d e t g = do+simulateAndFlatten n d e t g = do   let q = fromExchangeabilityMatrix e d-      pt = measureableTreeToProbTree q t+      pt = toProbTree q t   is <- getRootStates n d g-  simulateAndFlattenAlongProbTree is pt g+  simulateAndFlatten' is pt g  -- This is the heart of the simulation. Take a tree and a list of root states. -- Recursively jump down the branches to the leafs. Forget states at internal.-simulateAndFlattenAlongProbTree :: (PrimMonad m)+simulateAndFlatten' :: (PrimMonad m)   => [State] -> Tree ProbMatrix -> Gen (PrimState m) -> m [[State]]-simulateAndFlattenAlongProbTree is (Node p f) g = do+simulateAndFlatten' is (Node p f) g = do   is' <- mapM (\i -> jump i p g) is   if null f     then return [is']-    else concat <$> sequence [simulateAndFlattenAlongProbTree is' t g | t <- f]+    else concat <$> sequence [simulateAndFlatten' is' t g | t <- f]  -- | Simulate a number of sites for a given substitution model. Keep states at -- internal nodes. The result is a tree with the list of simulated states as -- node labels.-simulateNSitesAlongTree :: (PrimMonad m, Measurable a)+simulate :: (PrimMonad m, Measurable a)   => Int -> StationaryDistribution -> ExchangeabilityMatrix -> Tree a -> Gen (PrimState m) -> m (Tree [State])-simulateNSitesAlongTree n d e t g = do+simulate n d e t g = do   let q = fromExchangeabilityMatrix e d-      pt = measureableTreeToProbTree q t+      pt = toProbTree q t   is <- getRootStates n d g-  simulateAlongProbTree is pt g+  simulate' is pt g  -- This is the heart of the simulation. Take a tree and a list of root states. -- Recursively jump down the branches to the leafs.-simulateAlongProbTree :: (PrimMonad m)+simulate' :: (PrimMonad m)   => [State] -> Tree ProbMatrix -> Gen (PrimState m) -> m (Tree [State])-simulateAlongProbTree is (Node p f) g = do+simulate' is (Node p f) g = do   is' <- mapM (\i -> jump i p g) is-  f' <- sequence [simulateAlongProbTree is' t g | t <- f]+  f' <- sequence [simulate' is' t g | t <- f]   return $ Node is' f' -measureableTreeToProbTreeMixtureModel :: (Measurable a)+toProbTreeMixtureModel :: (Measurable a)   => [RateMatrix] -> Tree a -> Tree [ProbMatrix]-measureableTreeToProbTreeMixtureModel qs =-  fmap (\a -> [probMatrix q . getLen $ a | q <- qs])+toProbTreeMixtureModel qs =+  fmap (\a -> [probMatrix q . getLen $ a | q <- qs] `using` parList rpar)  getComponentsAndRootStates :: PrimMonad m   => Int -> Vector R -> [StationaryDistribution] -> Gen (PrimState m) -> m ([Int], [State])@@ -98,41 +101,54 @@  -- | Simulate a number of sites for a given set of substitution models with -- corresponding weights. Forget states at internal nodes. See also--- 'simulateAndFlattenNSitesAlongTree'.-simulateAndFlattenNSitesAlongTreeMixtureModel :: (PrimMonad m, Measurable a)+-- 'simulateAndFlatten'.+simulateAndFlattenMixtureModel :: (PrimMonad m, Measurable a)   => Int -> Vector R -> [StationaryDistribution] -> [ExchangeabilityMatrix] -> Tree a   -> Gen (PrimState m) -> m [[State]]-simulateAndFlattenNSitesAlongTreeMixtureModel n ws ds es t g = do+simulateAndFlattenMixtureModel n ws ds es t g = do   let qs = zipWith fromExchangeabilityMatrix es ds-      pt = measureableTreeToProbTreeMixtureModel qs t+      pt = toProbTreeMixtureModel qs t   (cs, is) <- getComponentsAndRootStates n ws ds g-  simulateAndFlattenAlongProbTreeMixtureModel is cs pt g+  simulateAndFlattenMixtureModel' is cs pt g -simulateAndFlattenAlongProbTreeMixtureModel :: (PrimMonad m)+simulateAndFlattenMixtureModel' :: (PrimMonad m)   => [State] -> [Int] -> Tree [ProbMatrix] -> Gen (PrimState m) -> m [[State]]-simulateAndFlattenAlongProbTreeMixtureModel is cs (Node ps f) g+simulateAndFlattenMixtureModel' is cs (Node ps f) g   = do is' <- sequence [ jump i (ps !! c) g | (i, c) <- zip is cs ]        if null f          then return [is']-         else concat <$> sequence [ simulateAndFlattenAlongProbTreeMixtureModel is' cs t g | t <- f ]+         else concat <$> sequence [ simulateAndFlattenMixtureModel' is' cs t g | t <- f ] +-- | See 'simulateAndFlattenMixtureModel', parallel version;+-- needs to be run in IO monad.+simulateAndFlattenMixtureModelPar+  :: Measurable a+  => Int -> Vector R -> [StationaryDistribution] -> [ExchangeabilityMatrix] -> Tree a+  -> GenIO -> IO [[[State]]]+simulateAndFlattenMixtureModelPar n ws ds es t g = do+  let qs = zipWith fromExchangeabilityMatrix es ds+      pt = toProbTreeMixtureModel qs t+  parComp n (\n' g' -> do+                (cs, is) <- getComponentsAndRootStates n' ws ds g'+                simulateAndFlattenMixtureModel' is cs pt g') g+ -- | Simulate a number of sites for a given set of substitution models with -- corresponding weights. Keep states at internal nodes. See also--- 'simulateNSitesAlongTree'.-simulateNSitesAlongTreeMixtureModel :: (PrimMonad m, Measurable a)+-- 'simulate'.+simulateMixtureModel :: (PrimMonad m, Measurable a)   => Int -> Vector R -> [StationaryDistribution] -> [ExchangeabilityMatrix] -> Tree a   -> Gen (PrimState m) -> m (Tree [State])-simulateNSitesAlongTreeMixtureModel n ws ds es t g = do+simulateMixtureModel n ws ds es t g = do   let qs = zipWith fromExchangeabilityMatrix es ds-      pt = measureableTreeToProbTreeMixtureModel qs t+      pt = toProbTreeMixtureModel qs t   (cs, is) <- getComponentsAndRootStates n ws ds g-  simulateAlongProbTreeMixtureModel is cs pt g+  simulateMixtureModel' is cs pt g  -- See 'simulateAlongProbTree', only we have a number of mixture components. The -- starting states and the components for each site have to be provided.-simulateAlongProbTreeMixtureModel :: (PrimMonad m)+simulateMixtureModel' :: (PrimMonad m)   => [State] -> [Int] -> Tree [ProbMatrix] -> Gen (PrimState m) -> m (Tree [State])-simulateAlongProbTreeMixtureModel is cs (Node ps f) g = do+simulateMixtureModel' is cs (Node ps f) g = do   is' <- sequence [ jump i (ps !! c) g | (i, c) <- zip is cs ]-  f'  <- sequence [ simulateAlongProbTreeMixtureModel is' cs t g | t <- f ]+  f'  <- sequence [ simulateMixtureModel' is' cs t g | t <- f ]   return $ Node is' f'
test/ELynx/Data/MarkovProcess/AminoAcidSpec.hs view
@@ -14,7 +14,6 @@ module ELynx.Data.MarkovProcess.AminoAcidSpec   (spec) where -import           Control.Lens import           Numeric.LinearAlgebra import           Test.Hspec @@ -117,13 +116,13 @@ statDistUniform = vector $ replicate 20 0.05  statDistLG :: R.StationaryDistribution-statDistLG = lg ^. S.stationaryDistribution+statDistLG = S.stationaryDistribution lg  exchLG :: R.ExchangeabilityMatrix-exchLG = lg ^. S.exchangeabilityMatrix+exchLG = S.exchangeabilityMatrix lg  rmLG :: R.RateMatrix-rmLG = S.getRateMatrix lg+rmLG = S.rateMatrix lg  spec :: Spec spec = do@@ -142,14 +141,14 @@    describe "lgCustom" $     it "stationary distribution can be recovered" $ do-    let f = R.getStationaryDistribution $ S.getRateMatrix $ lgCustom Nothing statDistUniform+    let f = R.getStationaryDistribution $ S.rateMatrix $ lgCustom Nothing statDistUniform     f `nearlyEqVec` statDistUniform `shouldBe` True    describe "poisson" $     it "stationary distribution is uniform 1/20" $-    R.getStationaryDistribution (S.getRateMatrix poisson) `nearlyEqVec` statDistUniform `shouldBe` True+    R.getStationaryDistribution (S.rateMatrix poisson) `nearlyEqVec` statDistUniform `shouldBe` True    describe "poissonCustom" $     it "stationary distribution can be recovered" $ do-    let f = R.getStationaryDistribution $ S.getRateMatrix $ poissonCustom Nothing statDistLGPython+    let f = R.getStationaryDistribution $ S.rateMatrix $ poissonCustom Nothing statDistLGPython     f `nearlyEqVec` statDistLGPython `shouldBe` True
test/ELynx/Data/MarkovProcess/NucleotideSpec.hs view
@@ -32,5 +32,5 @@ spec =   describe "getStationaryDistribution" $   it "extracts the stationary distribution from a rate matrix" $ do-  let sd = getStationaryDistribution (getRateMatrix hkyModel)+  let sd = getStationaryDistribution (rateMatrix hkyModel)   sd `nearlyEqVec` stationaryDist `shouldBe` True
+ test/ELynx/Data/Sequence/AlignmentSpec.hs view
@@ -0,0 +1,40 @@+{- |+Module      :  ELynx.Data.Sequence.AlignmentSpec+Copyright   :  (c) Dominik Schrempf 2018+License     :  GPL-3++Maintainer  :  dominik.schrempf@gmail.com+Stability   :  unstable+Portability :  portable++Creation date: Fri Oct  5 14:25:42 2018.++-}++module ELynx.Data.Sequence.AlignmentSpec+  (spec) where++import qualified Data.ByteString.Lazy.Char8    as L+import qualified Data.Matrix.Unboxed           as M+import           Test.Hspec++import           ELynx.Data.Alphabet.Alphabet+import           ELynx.Data.Alphabet.Character+import           ELynx.Data.Sequence.Alignment+import           ELynx.Import.Sequence.Fasta+import           ELynx.Tools.InputOutput+import           Files++ssData :: M.Matrix Character+ssData = M.fromLists $ map (reverse . map fromChar) [ "AAA", "GAA", "TAA" ]++ssA :: Alignment+ssA = Alignment (map L.pack ["SEQUENCE_1", "SEQUENCE_2", "SEQUENCE_3"]) DNAI ssData++spec :: Spec+spec =+  describe "subSample" $+  it "correctly sub sample an Alignment" $ do+    a <- either error id . fromSequences <$> parseFileWith (fasta DNAI) fastaNucleotideIUPACFN+    let ss = subSample [0,3,5] a+    ss `shouldBe` ssA
− test/ELynx/Data/Sequence/MultiSequenceAlignmentSpec.hs
@@ -1,40 +0,0 @@-{- |-Module      :  ELynx.Data.Sequence.MultiSequenceAlignmentSpec-Copyright   :  (c) Dominik Schrempf 2018-License     :  GPL-3--Maintainer  :  dominik.schrempf@gmail.com-Stability   :  unstable-Portability :  portable--Creation date: Fri Oct  5 14:25:42 2018.---}--module ELynx.Data.Sequence.MultiSequenceAlignmentSpec-  (spec) where--import qualified Data.ByteString.Lazy.Char8                 as L-import qualified Data.Matrix.Unboxed                        as M-import           Test.Hspec--import           ELynx.Data.Alphabet.Alphabet-import           ELynx.Data.Alphabet.Character-import           ELynx.Data.Sequence.MultiSequenceAlignment-import           ELynx.Import.Sequence.Fasta-import           ELynx.Tools.InputOutput-import           Files--ssData :: M.Matrix Character-ssData = M.fromLists $ map (reverse . map fromChar) [ "AAA", "GAA", "TAA" ]--ssMSA :: MultiSequenceAlignment-ssMSA = MultiSequenceAlignment (map L.pack ["SEQUENCE_1", "SEQUENCE_2", "SEQUENCE_3"]) DNAI ssData--spec :: Spec-spec =-  describe "subSample" $-  it "correctly sub sample an MSA" $ do-    msa <- either error id . fromSequenceList <$> parseFileWith (fasta DNAI) fastaNucleotideIUPACFN-    let ss = subSample [0,3,5] msa-    ss `shouldBe` ssMSA
+ test/ELynx/Import/MarkovProcess/SiteprofilesPhylobayesSpec.hs view
@@ -0,0 +1,46 @@+{- |+Module      :  ELynx.Import.MarkovProcess.SiteprofilesPhylobayesSpec+Copyright   :  (c) Dominik Schrempf 2019+License     :  GPL-3++Maintainer  :  dominik.schrempf@gmail.com+Stability   :  unstable+Portability :  portable++Creation date: Wed Sep 18 09:51:35 2019.++-}++module ELynx.Import.MarkovProcess.SiteprofilesPhylobayesSpec+  ( spec+  ) where++import qualified Data.Vector.Storable                              as V+import           Test.Hspec++import           ELynx.Data.MarkovProcess.EDMModel+import           ELynx.Import.MarkovProcess.SiteprofilesPhylobayes+import           ELynx.Tools.Equality+import           ELynx.Tools.InputOutput++fn :: FilePath+fn = "data/HSSPMany.siteprofiles"++getProfiles :: IO [EDMComponent]+getProfiles = parseFileWith siteprofiles fn++firstProfile :: V.Vector Double+firstProfile = V.fromList+  [ 0.0267009, 0.013874, 0.022432, 0.0440502, 0.0485174, 0.0407515+  , 0.0170806, 0.348043, 0.0371379, 0.0715536, 0.0454168, 0.0342213+  , 0.0146872, 0.0239681, 0.0768379, 0.0210387, 0.0123336+  , 0.0512678, 0.0149093, 0.0351776 ]++spec :: Spec+spec = describe "import phylobayes siteprofiles" $+  it "parses a text file with siteprofiles in phylobayes format" $ do+  profiles <- getProfiles+  length profiles `shouldBe` 701+  map fst profiles `shouldBe` replicate 701 1.0+  map (V.sum . snd) profiles `shouldSatisfy` nearlyEqListWith 1e-5 (replicate 701 1.0)+  snd (head profiles) `shouldBe` firstProfile
test/ELynx/Import/Sequence/FastaSpec.hs view
@@ -16,7 +16,7 @@  import           Data.Either import           ELynx.Data.Alphabet.Alphabet-import           ELynx.Data.Sequence.MultiSequenceAlignment+import qualified ELynx.Data.Sequence.Alignment as M import           ELynx.Import.Sequence.Fasta import           ELynx.Tools.InputOutput import           Files@@ -24,27 +24,27 @@  spec :: Spec spec =-  describe "fastaFileMSA" $ do+  describe "fastaFileAlignment" $ do     it "parses a fasta file with nucleotide sequences with equal length" $ do-      msa <- either error id . fromSequenceList <$> parseFileWith (fasta DNA) fastaNucleotideFN-      msaNSequences msa `shouldBe` 3-      msaLength msa `shouldBe` 40+      a <- either error id . M.fromSequences <$> parseFileWith (fasta DNA) fastaNucleotideFN+      M.nSequences a `shouldBe` 3+      M.length a `shouldBe` 40      it "parses a fasta file with nucleotide IUPAC sequences with equal length" $ do-      msa <- either error id . fromSequenceList <$> parseFileWith (fasta DNAI) fastaNucleotideIUPACFN-      msaNSequences msa `shouldBe` 3-      msaLength msa `shouldBe` 40+      a <- either error id . M.fromSequences <$> parseFileWith (fasta DNAI) fastaNucleotideIUPACFN+      M.nSequences a `shouldBe` 3+      M.length a `shouldBe` 40      it "should not parse erroneous files" $ do-      emsa <- runParserOnFile (fasta DNAI) fastaErroneousFN-      emsa  `shouldSatisfy` isLeft+      ea <- runParserOnFile (fasta DNAI) fastaErroneousFN+      ea  `shouldSatisfy` isLeft      it "parses a fasta file with amino acid sequences with equal length" $ do-      msa <- either error id . fromSequenceList <$> parseFileWith (fasta Protein) fastaAminoAcidFN-      msaNSequences msa `shouldBe` 2-      msaLength msa `shouldBe` 237+      a <- either error id . M.fromSequences <$> parseFileWith (fasta Protein) fastaAminoAcidFN+      M.nSequences a `shouldBe` 2+      M.length a `shouldBe` 237      it "should not parse erroneous files" $ do-      msa <- runParserOnFile (fasta ProteinI) fastaErroneousFN-      msa  `shouldSatisfy` isLeft+      a <- runParserOnFile (fasta ProteinI) fastaErroneousFN+      a  `shouldSatisfy` isLeft 
test/ELynx/Simulate/MarkovProcessAlongTreeSpec.hs view
@@ -14,7 +14,6 @@ module ELynx.Simulate.MarkovProcessAlongTreeSpec   (spec) where -import           Control.Lens import           Data.Tree import           System.Random.MWC import           Test.Hspec@@ -28,14 +27,14 @@ -- sampleNewickText :: T.Text -- sampleNewickText = T.pack "(Aeropyrum0:0.5478645225,(((((((((Arabidopsi:0.0701001024,Oryza_sati:0.0765988261):0.0309636193,Gymnosperm:0.0520325624):0.0338982245,Physcomitr:0.0768008916):0.0895714685,(Chlamydomo:0.1136227755,Dunaliella:0.1406347323):0.1117340620):0.0818876186,Rhodophyta:0.3405656487):0.0363527066,((((((Babesia_bo:0.1646969208,Theileria0:0.1519889486):0.1908081096,Plasmodium:0.3250696762):0.0637865908,(Toxoplasma:0.1153570425,Eimeria000:0.1671916078):0.0980136930):0.0518956330,Cryptospor:0.3175062809):0.1607708388,Ciliophora:0.5687502950):0.0624078848,(Phytophtho:0.2016424948,((Thalassios:0.1202730781,Phaeodacty:0.1290341329):0.1772775509,Phaeophyce:0.1989260715):0.0312359673):0.1154768302):0.0311952864):0.0149160316,(((((((((Candida_al:0.1027755272,Saccharomy:0.1190206560):0.1333487870,Neurospora:0.1977309079):0.0522926266,Schizosacc:0.2019603227):0.0567441011,(Cryptococc:0.1948614959,Ustilago_m:0.1564451295):0.0775729694):0.0323959951,Glomus_int:0.1573670796):0.0194701292,Chytridiom:0.2228415254):0.0384370601,Encephalit:1.4622174644):0.0416231688,(((Drosophila:0.2160627753,(Mammalians:0.1080484094,Tunicates0:0.1739253014):0.0289624371):0.0346633757,Hydrozoa00:0.2058137032):0.0480963050,Monosiga_b:0.3020637584):0.0654894239):0.0380915725,(Dictyostel:0.3453588998,Mastigamoe:0.3844779231):0.0478795653):0.0129578395):1.7592083381,((Archaeoglo:0.5402784445,Methanococ:0.4088567459):0.0993669265,Pyrococcus:0.4058713829):0.1734405968):0.2193511807,Pyrobaculu:0.7507718047):0.1646616482,Sulfolobus:0.5404967897);" -testTree :: Tree PhyloIntLabel-testTree = Node (PhyloLabel 0 Nothing 0.0) [ Node (PhyloLabel 1 Nothing 1.0) [], Node (PhyloLabel 2 Nothing 1.0) [] ]+testTree :: Tree (PhyloLabel Int)+testTree = Node (PhyloLabel 0 Nothing (Just 0.0)) [ Node (PhyloLabel 1 Nothing (Just 1.0)) [], Node (PhyloLabel 2 Nothing (Just 1.0)) [] ]  -- testStateTree :: Tree State -- testStateTree = Node 0 [Node 3 [], Node 2 []] -nullTree :: Tree PhyloIntLabel-nullTree = Node (PhyloLabel 0 Nothing 0.0) []+nullTree :: Tree (PhyloLabel Int)+nullTree = Node (PhyloLabel 0 Nothing (Just 0.0)) []  nullStateTree :: Tree State nullStateTree = fmap (const 0) nullTree@@ -48,13 +47,13 @@   describe "simulateNSitesAlongTree" $ do     it "simulates one site along an easy tree" $ do       gen <- create-      tr <- simulateNSitesAlongTree 1 d e nullTree gen+      tr <- simulate 1 d e nullTree gen       fmap head tr `shouldBe` nullStateTree      it "simulates some sites along a harder tree" $ do       gen <- create-      tr <- simulateNSitesAlongTree 10 d e testTree gen+      tr <- simulate 10 d e testTree gen       (length . rootLabel $ tr) `shouldBe` 10-        where d = jc ^. S.stationaryDistribution-              e = jc ^. S.exchangeabilityMatrix+        where d = S.stationaryDistribution jc+              e = S.exchangeabilityMatrix jc