packages feed

slynx 0.3.0 → 0.3.1

raw patch · 8 files changed

+187/−125 lines, 8 filesdep +attoparsecdep −megaparsecdep −scientific

Dependencies added: attoparsec

Dependencies removed: megaparsec, scientific

Files

ChangeLog.md view
@@ -2,7 +2,14 @@ # Changelog for ELynx  -## Version 0.3.1; in development+## Version 0.3.2; in development+++## Version 0.3.1++-   Use Attoparsec.+-   Use ByteString consistently.+-   Remove elynx-tools dependency from libaries.   ## Version 0.3.0
README.md view
@@ -2,7 +2,7 @@  # The ELynx Suite -Version: 0.3.0.+Version: 0.3.1. Reproducible evolution made easy.  <p align="center"><img src="https://travis-ci.org/dschrempf/elynx.svg?branch=master"/></p>@@ -90,9 +90,9 @@      slynx --help | head -n -16 -    ELynx Suite version 0.3.0.+    ELynx Suite version 0.3.1.     Developed by Dominik Schrempf.-    Compiled on July 30, 2020, at 12:40 pm, UTC.+    Compiled on August 3, 2020, at 12:12 pm, UTC.          Usage: slynx [-v|--verbosity VALUE] [-o|--output-file-basename NAME]                   [-f|--force] COMMAND@@ -136,9 +136,9 @@      slynx concatenate --help -    ELynx Suite version 0.3.0.+    ELynx Suite version 0.3.1.     Developed by Dominik Schrempf.-    Compiled on July 30, 2020, at 12:40 pm, UTC.+    Compiled on August 3, 2020, at 12:12 pm, UTC.          Usage: slynx concatenate (-a|--alphabet NAME) INPUT-FILE       Concatenate sequences found in input files.@@ -157,9 +157,9 @@      slynx examine --help -    ELynx Suite version 0.3.0.+    ELynx Suite version 0.3.1.     Developed by Dominik Schrempf.-    Compiled on July 30, 2020, at 12:40 pm, UTC.+    Compiled on August 3, 2020, at 12:12 pm, UTC.          Usage: slynx examine (-a|--alphabet NAME) INPUT-FILE [--per-site]       Examine sequences. If data is a multi sequence alignment, additionally analyze columns.@@ -179,9 +179,9 @@      slynx filter-rows --help -    ELynx Suite version 0.3.0.+    ELynx Suite version 0.3.1.     Developed by Dominik Schrempf.-    Compiled on July 30, 2020, at 12:40 pm, UTC.+    Compiled on August 3, 2020, at 12:12 pm, UTC.          Usage: slynx filter-rows (-a|--alphabet NAME) INPUT-FILE [--longer-than LENGTH]                               [--shorter-than LENGTH] [--standard-characters]@@ -202,9 +202,9 @@      slynx filter-columns --help -    ELynx Suite version 0.3.0.+    ELynx Suite version 0.3.1.     Developed by Dominik Schrempf.-    Compiled on July 30, 2020, at 12:40 pm, UTC.+    Compiled on August 3, 2020, at 12:12 pm, UTC.          Usage: slynx filter-columns (-a|--alphabet NAME) INPUT-FILE                                  [--standard-chars DOUBLE]@@ -226,9 +226,9 @@      slynx simulate --help -    ELynx Suite version 0.3.0.+    ELynx Suite version 0.3.1.     Developed by Dominik Schrempf.-    Compiled on July 30, 2020, at 12:40 pm, UTC.+    Compiled on August 3, 2020, at 12:12 pm, UTC.          Usage: slynx simulate (-t|--tree-file Name) [-s|--substitution-model MODEL]                            [-m|--mixture-model MODEL] [-e|--edm-file NAME] @@ -305,9 +305,9 @@      slynx sub-sample --help -    ELynx Suite version 0.3.0.+    ELynx Suite version 0.3.1.     Developed by Dominik Schrempf.-    Compiled on July 30, 2020, at 12:40 pm, UTC.+    Compiled on August 3, 2020, at 12:12 pm, UTC.          Usage: slynx sub-sample (-a|--alphabet NAME) INPUT-FILE                             (-n|--number-of-sites INT)@@ -335,9 +335,9 @@      slynx translate --help -    ELynx Suite version 0.3.0.+    ELynx Suite version 0.3.1.     Developed by Dominik Schrempf.-    Compiled on July 30, 2020, at 12:40 pm, UTC.+    Compiled on August 3, 2020, at 12:12 pm, UTC.          Usage: slynx translate (-a|--alphabet NAME) INPUT-FILE (-r|--reading-frame INT)                            (-u|--universal-code CODE)@@ -360,9 +360,9 @@      tlynx --help | head -n -16 -    ELynx Suite version 0.3.0.+    ELynx Suite version 0.3.1.     Developed by Dominik Schrempf.-    Compiled on July 30, 2020, at 12:40 pm, UTC.+    Compiled on August 3, 2020, at 12:12 pm, UTC.          Usage: tlynx [-v|--verbosity VALUE] [-o|--output-file-basename NAME]                   [-f|--force] COMMAND@@ -399,9 +399,9 @@      tlynx compare --help -    ELynx Suite version 0.3.0.+    ELynx Suite version 0.3.1.     Developed by Dominik Schrempf.-    Compiled on July 30, 2020, at 12:40 pm, UTC.+    Compiled on August 3, 2020, at 12:12 pm, UTC.          Usage: tlynx compare [-n|--normalize] [-b|--bipartitions] [-t|--intersect]                           [-f|--newick-format FORMAT] NAMES@@ -428,9 +428,9 @@      tlynx examine --help -    ELynx Suite version 0.3.0.+    ELynx Suite version 0.3.1.     Developed by Dominik Schrempf.-    Compiled on July 30, 2020, at 12:40 pm, UTC.+    Compiled on August 3, 2020, at 12:12 pm, UTC.          Usage: tlynx examine INPUT-FILE [-f|--newick-format FORMAT]       Compute summary statistics of phylogenetic trees.@@ -452,9 +452,9 @@      tlynx simulate --help -    ELynx Suite version 0.3.0.+    ELynx Suite version 0.3.1.     Developed by Dominik Schrempf.-    Compiled on July 30, 2020, at 12:40 pm, UTC.+    Compiled on August 3, 2020, at 12:12 pm, UTC.          Usage: tlynx simulate [-t|--nTrees INT] [-n|--nLeaves INT] [-H|--height DOUBLE]                            [-M|--condition-on-mrca] [-l|--lambda DOUBLE] @@ -491,9 +491,9 @@      elynx --help | head -n -16 -    ELynx Suite version 0.3.0.+    ELynx Suite version 0.3.1.     Developed by Dominik Schrempf.-    Compiled on July 30, 2020, at 12:40 pm, UTC.+    Compiled on August 3, 2020, at 12:12 pm, UTC.          Usage: elynx COMMAND       Validate and redo past ELynx analyses
slynx.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 826b98c0606c81f3576251bedb9ae6aa528a2afeb1a782a01a6f17578ce698af+-- hash: 286f8b4edbcbe74a920bfa98bfeb769b685b7591ba79d26c1a024faa2889e888  name:           slynx-version:        0.3.0+version:        0.3.1 synopsis:       Handle molecular sequences description:    Examine, modify, and simulate molecular sequences in a reproducible way. Please see the README on GitHub at <https://github.com/dschrempf/elynx>. category:       Bioinformatics@@ -54,6 +54,7 @@   ghc-options: -Wall -fllvm   build-depends:       async+    , attoparsec     , base >=4.7 && <5     , bytestring     , containers@@ -62,11 +63,9 @@     , elynx-tools     , elynx-tree     , hmatrix-    , megaparsec     , monad-logger     , mwc-random     , optparse-applicative-    , scientific     , text     , transformers     , vector@@ -81,7 +80,5 @@   ghc-options: -Wall -fllvm -threaded -rtsopts -with-rtsopts=-N   build-depends:       base >=4.7 && <5-    , elynx-seq-    , elynx-tools     , slynx   default-language: Haskell2010
src/SLynx/Examine/Examine.hs view
@@ -20,7 +20,7 @@  import Control.Monad.Logger import Control.Monad.Trans.Reader (ask)-import qualified Data.ByteString.Lazy.Char8 as L+import qualified Data.ByteString.Lazy.Char8 as BL import qualified Data.Set as S import qualified ELynx.Data.Alphabet.Alphabet as A import qualified ELynx.Data.Alphabet.Character as C@@ -31,53 +31,53 @@ import SLynx.Tools import Text.Printf -pRow :: String -> String -> L.ByteString+pRow :: String -> String -> BL.ByteString pRow name val = alignLeft 50 n <> alignRight 10 v   where-    n = L.pack name-    v = L.pack val+    n = BL.pack name+    v = BL.pack val -examineAlignment :: Bool -> M.Alignment -> L.ByteString+examineAlignment :: Bool -> M.Alignment -> BL.ByteString examineAlignment perSiteFlag a =-  L.unlines-    [ L.pack+  BL.unlines+    [ BL.pack         "Sequences have equal length (multi sequence alignment, or single sequence).",       pRow "Total number of columns in alignment:" $ show (M.length a),       pRow "Number of columns without gaps:" $ show (M.length aNoGaps),       pRow "Number of columns with standard characters only:" $         show (M.length aOnlyStd),-      L.empty,+      BL.empty,       pRow "Total number of characters:" $ show nTot,       pRow "Standard (i.e., not extended IUPAC) characters:" $         show (nTot - nIUPAC - nGaps - nUnknowns),       pRow "Extended IUPAC characters:" $ show nIUPAC,       pRow "Gaps:" $ show nGaps,       pRow "Unknowns:" $ show nUnknowns,-      L.empty,+      BL.empty,       pRow "Percentage of standard characters:" $         printf "%2.2f" (100.0 - percentIUPAC - percentGaps - percentUnknowns),       pRow "Percentage of extended IUPAC characters:" $         printf "%2.2f" percentIUPAC,       pRow "Percentage of gaps:" $ printf "%2.2f" percentGaps,       pRow "Percentage of unknowns:" $ printf "%2.2f" percentUnknowns,-      L.empty,-      L.pack "Distribution of characters:",+      BL.empty,+      BL.pack "Distribution of characters:",       -- Holy crap.-      L.pack $+      BL.pack $         concatMap ((: "     ") . C.toChar) $           S.toList $             A.std $               A.alphabetSpec $                 M.alphabet a,-      L.pack $ unwords $ map (printf "%.3f") charFreqs,-      L.empty,-      L.pack "Mean effective number of states (measured using entropy):",+      BL.pack $ unwords $ map (printf "%.3f") charFreqs,+      BL.empty,+      BL.pack "Mean effective number of states (measured using entropy):",       pRow "Across whole alignment:" $ printf "%.3f" kEffMean,       pRow "Across columns without gaps:" $ printf "%.3f" kEffMeanNoGaps,       pRow "Across columns without extended IUPAC characters:" $         printf "%.3f" kEffMeanOnlyStd,-      L.empty,-      L.pack "Mean effective number of states (measured using homoplasy):",+      BL.empty,+      BL.pack "Mean effective number of states (measured using homoplasy):",       pRow "Across whole alignment:" $ printf "%.3f" kEffMeanHomo,       pRow "Across columns without gaps:" $ printf "%.3f" kEffMeanNoGapsHomo,       pRow "Across columns without extended IUPAC characters:" $@@ -113,17 +113,17 @@     perSiteBS =       if perSiteFlag         then-          L.unlines-            [ L.pack "Effective number of used states per site:",-              L.pack . show $ kEffs+          BL.unlines+            [ BL.pack "Effective number of used states per site:",+              BL.pack . show $ kEffs             ]-        else L.empty+        else BL.empty -examine :: Bool -> [Seq.Sequence] -> L.ByteString+examine :: Bool -> [Seq.Sequence] -> BL.ByteString examine perSiteFlag ss =   Seq.summarizeSequences ss <> case M.fromSequences ss of-    Left _ -> L.empty-    Right a -> L.pack "\n" <> examineAlignment perSiteFlag a+    Left _ -> BL.empty+    Right a -> BL.pack "\n" <> examineAlignment perSiteFlag a  -- | Examine sequences. examineCmd :: ELynx ExamineArguments ()
src/SLynx/Filter/Filter.hs view
@@ -21,7 +21,7 @@ import Control.Monad (when) import Control.Monad.Logger import Control.Monad.Trans.Reader (ask)-import qualified Data.ByteString.Lazy.Char8 as L+import qualified Data.ByteString.Lazy.Char8 as BL import Data.Maybe (fromMaybe) import qualified Data.Text as T import qualified ELynx.Data.Sequence.Alignment as M@@ -31,7 +31,7 @@ import SLynx.Filter.Options import SLynx.Tools -filterRows :: Maybe Int -> Maybe Int -> Bool -> [S.Sequence] -> L.ByteString+filterRows :: Maybe Int -> Maybe Int -> Bool -> [S.Sequence] -> BL.ByteString filterRows ml ms std ss = sequencesToFasta $ compose filters ss   where     filters' =@@ -62,7 +62,7 @@   let result = filterRows long short std ss   out "filtered sequences" result ".fasta" -filterCols :: Maybe Double -> [S.Sequence] -> L.ByteString+filterCols :: Maybe Double -> [S.Sequence] -> BL.ByteString filterCols ms ss = sequencesToFasta . M.toSequences $ compose filters a   where     a = either error id (M.fromSequences ss)
src/SLynx/Simulate/PhyloModel.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE OverloadedStrings #-}+ -- | -- Module      :  SLynx.Simulate.PhyloModel -- Description :  Parse and interpret the model string@@ -14,14 +16,13 @@   ) where +import Control.Applicative import Control.Monad (when)-import qualified Data.ByteString.Lazy.Char8 as L+import Data.Attoparsec.ByteString.Char8+import qualified Data.ByteString.Char8 as BS import Data.Either (rights) import Data.List.NonEmpty (fromList) import Data.Maybe-import Data.Scientific hiding (scientific)-import Data.Void-import Data.Word (Word8) import ELynx.Data.MarkovProcess.AminoAcid import ELynx.Data.MarkovProcess.CXXModels import qualified ELynx.Data.MarkovProcess.MixtureModel as M@@ -38,15 +39,7 @@     size,     vector,   )-import Text.Megaparsec-import Text.Megaparsec.Byte-import Text.Megaparsec.Byte.Lexer -type Parser = Parsec Void L.ByteString--bs :: String -> L.ByteString-bs = L.pack- nNuc :: Int -- nNuc = length (alphabet :: [Nucleotide]) nNuc = 4@@ -56,53 +49,42 @@ nAA = 20  -- Model parameters between square brackets.-paramsStart :: Word8-paramsStart = c2w '['+paramsStart :: Char+paramsStart = '[' -paramsEnd :: Word8-paramsEnd = c2w ']'+paramsEnd :: Char+paramsEnd = ']'  -- Stationary distribution between curly brackets.-sdStart :: Word8-sdStart = c2w '{'+sdStart :: Char+sdStart = '{' -sdEnd :: Word8-sdEnd = c2w '}'+sdEnd :: Char+sdEnd = '}'  -- Mixture model components between round brackets.-mmStart :: Word8-mmStart = c2w '('+mmStart :: Char+mmStart = '(' -mmEnd :: Word8-mmEnd = c2w ')'+mmEnd :: Char+mmEnd = ')' -separator :: Word8-separator = c2w ','+separator :: Char+separator = ','  name :: Parser String name =-  L.unpack-    <$> takeWhile1P-      (Just "Model name")-      ( `notElem` [paramsStart, paramsEnd, sdStart, sdEnd, mmStart, mmEnd, separator]-      )+  BS.unpack+    <$> takeWhile1 (notInClass [paramsStart, paramsEnd, sdStart, sdEnd, mmStart, mmEnd, separator])  params :: Parser [Double]-params =-  map toRealFloat-    <$> between-      (char paramsStart)-      (char paramsEnd)-      (sepBy1 scientific (char separator))+params = char paramsStart *> double `sepBy1` char separator <* char paramsEnd  stationaryDistribution :: Parser StationaryDistribution stationaryDistribution = do-  f <--    vector . map toRealFloat-      <$> between-        (char sdStart)-        (char sdEnd)-        (sepBy1 scientific (char separator))+  _ <- char sdStart+  f <- vector <$> double `sepBy1` char separator+  _ <- char sdEnd   if nearlyEq (norm_1 f) 1.0     then return f     else@@ -172,7 +154,7 @@  edmModel :: [EDMComponent] -> Maybe [M.Weight] -> Parser M.MixtureModel edmModel cs mws = do-  _ <- chunk (bs "EDM")+  _ <- string "EDM"   _ <- char mmStart   n <- name   mps <- optional params@@ -192,13 +174,13 @@  cxxModel :: Maybe [M.Weight] -> Parser M.MixtureModel cxxModel mws = do-  _ <- char (c2w 'C')+  _ <- char 'C'   n <- decimal :: Parser Int   return $ cxx n mws  standardMixtureModel :: [M.Weight] -> Parser M.MixtureModel standardMixtureModel ws = do-  _ <- chunk (bs "MIXTURE")+  _ <- string "MIXTURE"   _ <- char mmStart   sms <- parseSubstitutionModel `sepBy1` char separator   _ <- char mmEnd@@ -233,7 +215,6 @@   Right $     P.SubstitutionModel $       parseStringWith-        "Substitution model string"         parseSubstitutionModel         s getPhyloModel (Just _) Nothing (Just _) _ =@@ -245,6 +226,5 @@   Right $     P.MixtureModel $       parseStringWith-        "Mixture model string"         (mixtureModel mcs mws)         m
src/SLynx/Simulate/Simulate.hs view
@@ -28,8 +28,8 @@ import Control.Monad.Logger import Control.Monad.Trans.Class import Control.Monad.Trans.Reader (ask)-import qualified Data.ByteString.Lazy as L-import qualified Data.ByteString.Lazy.Char8 as LC+import qualified Data.ByteString.Builder as BB+import qualified Data.ByteString.Lazy.Char8 as BL import Data.List.NonEmpty (toList) import Data.Maybe import qualified Data.Set as Set@@ -48,9 +48,7 @@   ) import ELynx.Data.Tree import ELynx.Export.Sequence.Fasta-import ELynx.Import.MarkovProcess.EDMModelPhylobayes hiding-  ( Parser,-  )+import ELynx.Import.MarkovProcess.EDMModelPhylobayes import ELynx.Import.MarkovProcess.SiteprofilesPhylobayes import ELynx.Import.Tree.Newick import ELynx.Simulate.MarkovProcessAlongTree@@ -62,6 +60,7 @@ import SLynx.Simulate.Options import SLynx.Simulate.PhyloModel import System.Random.MWC+import Text.Printf  -- Simulate a 'Alignment' for a given phylogenetic model, -- phylogenetic tree, and alignment length.@@ -110,9 +109,9 @@   return $ either error id $ A.fromSequences sequences  -- Summarize EDM components; line to be printed to screen or log.-summarizeEDMComponents :: [EDMComponent] -> L.ByteString+summarizeEDMComponents :: [EDMComponent] -> BL.ByteString summarizeEDMComponents cs =-  LC.pack $+  BL.pack $     "Empiricial distribution mixture model with "       ++ show (length cs)       ++ " components."@@ -128,8 +127,88 @@       $(logInfo)         "No output file provided; omit writing machine-readable phylogenetic model."     Just _ ->-      out "model definition (machine readable)" (bShow m <> "\n") ".model.gz"+      out "model definition (machine readable)" (BL.pack (show m) <> "\n") ".model.gz" +pretty :: BranchLength -> String+pretty = printf "%.5f"++prettyRow :: String -> String -> BL.ByteString+prettyRow name val = alignLeft 33 n <> alignRight 8 v+  where+    n = BL.pack name+    v = BL.pack val++-- | Examine branches of a tree.+summarizeBranchLengths :: Measurable e => Tree e a -> BL.ByteString+summarizeBranchLengths t =+  BL.intercalate+    "\n"+    [ prettyRow "Origin height: " $ pretty h,+      prettyRow "Average distance origin to leaves: " $ pretty h',+      prettyRow "Total branch length: " $ pretty b+    ]+  where+    n = length $ leaves t+    h = height t+    h' = sum (distancesOriginLeaves t) / fromIntegral n+    b = totalBranchLength t++-- Summarize a substitution model; lines to be printed to screen or log.+summarizeSM :: SM.SubstitutionModel -> [BL.ByteString]+summarizeSM sm =+  map BL.pack $+    (show (SM.alphabet sm) ++ " substitution model: " ++ SM.name sm ++ ".") :+    ["Parameters: " ++ show (SM.params sm) ++ "." | not (null (SM.params sm))]+      ++ case SM.alphabet sm of+        DNA ->+          [ "Stationary distribution: "+              ++ dispv precision (SM.stationaryDistribution sm)+              ++ ".",+            "Exchangeability matrix:\n"+              ++ dispmi 2 precision (SM.exchangeabilityMatrix sm)+              ++ ".",+            "Scale: " ++ show (roundN precision $ SM.totalRate sm) ++ "."+          ]+        Protein ->+          [ "Stationary distribution: "+              ++ dispv precision (SM.stationaryDistribution sm)+              ++ ".",+            "Scale: " ++ show (roundN precision $ SM.totalRate sm) ++ "."+          ]+        _ ->+          error+            "Extended character sets are not supported with substitution models."++-- Summarize a mixture model component; lines to be printed to screen or log.+summarizeMMComponent :: M.Component -> [BL.ByteString]+summarizeMMComponent c =+  BL.pack "Weight: "+    <> (BB.toLazyByteString . BB.doubleDec $ M.weight c) :+  summarizeSM (M.substModel c)++-- Summarize a mixture model; lines to be printed to screen or log.+summarizeMM :: M.MixtureModel -> [BL.ByteString]+summarizeMM m =+  [ BL.pack $ "Mixture model: " ++ M.name m ++ ".",+    BL.pack $ "Number of components: " ++ show n ++ "."+  ]+    ++ detail+  where+    n = length $ M.components m+    detail =+      if n <= 100+        then+          concat+            [ BL.pack ("Component " ++ show i ++ ":") : summarizeMMComponent c+              | (i, c) <- zip [1 :: Int ..] (toList $ M.components m)+            ]+        else []++-- Summarize a phylogenetic model; lines to be printed to screen or log.+summarizePM :: P.PhyloModel -> [BL.ByteString]+summarizePM (P.MixtureModel mm) = summarizeMM mm+summarizePM (P.SubstitutionModel sm) = summarizeSM sm+ -- | Simulate sequences. simulateCmd :: ELynx SimulateArguments () simulateCmd = do@@ -139,6 +218,7 @@   $(logInfo) $ T.pack $ "Read tree from file '" ++ treeFile ++ "'."   tree <- liftIO $ parseFileWith (newick Standard) treeFile   let t' = either error id $ phyloToLengthTree tree+  $(logInfo) $ T.pack $ "Number of leaves: " ++ show (length $ leaves t')   $(logInfo) $ LT.toStrict $ LT.decodeUtf8 $ summarizeBranchLengths t'   let edmFile = argsEDMFile l   let sProfileFiles = argsSiteprofilesFiles l@@ -185,21 +265,21 @@       $(logInfo) $         LT.toStrict $           LT.decodeUtf8 $-            LC.unlines $-              P.summarize+            BL.unlines $+              summarizePM                 phyloModel'       return phyloModel'     Just (n, alpha) -> do       $(logInfo) $         LT.toStrict $           LT.decodeUtf8 $-            LC.intercalate "\n" $-              P.summarize phyloModel'+            BL.intercalate "\n" $+              summarizePM phyloModel'       $(logInfo) ""       $(logInfo) $         LT.toStrict $           LT.decodeUtf8 $-            LC.intercalate "\n" $+            BL.intercalate "\n" $               summarizeGammaRateHeterogeneity n alpha       return $ expand n alpha phyloModel'   -- -- XXX: Do not report possibly huge empirical distribution mixture models
src/SLynx/Tools.hs view
@@ -26,9 +26,7 @@ import qualified Data.Text as T import ELynx.Data.Alphabet.Alphabet import ELynx.Data.Sequence.Sequence-import ELynx.Import.Sequence.Fasta hiding-  ( Parser,-  )+import ELynx.Import.Sequence.Fasta import ELynx.Tools import Options.Applicative