packages feed

slynx 0.7.1.0 → 0.7.2.0

raw patch · 6 files changed

+102/−75 lines, 6 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ SLynx.Simulate.Options: GlobalNormalization :: MixtureModelGlobalNormalization
+ SLynx.Simulate.Options: LocalNormalization :: MixtureModelGlobalNormalization
+ SLynx.Simulate.Options: [argsMixtureModelGlobalNormalization] :: SimulateArguments -> MixtureModelGlobalNormalization
+ SLynx.Simulate.Options: data MixtureModelGlobalNormalization
+ SLynx.Simulate.Options: instance Data.Aeson.Types.FromJSON.FromJSON SLynx.Simulate.Options.MixtureModelGlobalNormalization
+ SLynx.Simulate.Options: instance Data.Aeson.Types.ToJSON.ToJSON SLynx.Simulate.Options.MixtureModelGlobalNormalization
+ SLynx.Simulate.Options: instance GHC.Classes.Eq SLynx.Simulate.Options.MixtureModelGlobalNormalization
+ SLynx.Simulate.Options: instance GHC.Generics.Generic SLynx.Simulate.Options.MixtureModelGlobalNormalization
+ SLynx.Simulate.Options: instance GHC.Read.Read SLynx.Simulate.Options.MixtureModelGlobalNormalization
+ SLynx.Simulate.Options: instance GHC.Show.Show SLynx.Simulate.Options.MixtureModelGlobalNormalization
- SLynx.Simulate.Options: SimulateArguments :: FilePath -> Maybe String -> Maybe String -> Maybe FilePath -> Maybe [FilePath] -> Maybe [Double] -> Maybe GammaRateHeterogeneityParams -> Int -> SeedOpt -> SimulateArguments
+ SLynx.Simulate.Options: SimulateArguments :: FilePath -> Maybe String -> Maybe String -> MixtureModelGlobalNormalization -> Maybe FilePath -> Maybe [FilePath] -> Maybe [Double] -> Maybe GammaRateHeterogeneityParams -> Int -> SeedOpt -> SimulateArguments
- SLynx.Simulate.PhyloModel: getPhyloModel :: Maybe String -> Maybe String -> Maybe [Weight] -> Maybe [EDMComponent] -> Either String PhyloModel
+ SLynx.Simulate.PhyloModel: getPhyloModel :: Maybe String -> Maybe String -> MixtureModelGlobalNormalization -> Maybe [Weight] -> Maybe [EDMComponent] -> Either String PhyloModel

Files

ChangeLog.md view
@@ -5,6 +5,11 @@ ## Unreleased changes  +## Version 0.7.2.0++-   `slynx`: Allow global normalization of mixture models.++ ## Version 0.7.1.0  -   Be less strict with quoted identifiers/names in phylogenetic trees.
README.md view
@@ -2,7 +2,7 @@  # The ELynx Suite -Version: 0.7.0.0.+Version: 0.7.2.0. Reproducible evolution made easy.  <p align="center"><img src="https://travis-ci.org/dschrempf/elynx.svg?branch=master"/></p>@@ -73,13 +73,13 @@     # OR: stack exec slynx -- --help     # OR: slynx --help -    Up to date-    ELynx Suite version 0.7.0.0.+    ELynx Suite version 0.7.2.0.     Developed by Dominik Schrempf.-    Compiled on July 10, 2022, at 08:48 am, UTC.+    Compiled on May 3, 2023, at 13:18 pm, UTC.          Usage: slynx [-v|--verbosity VALUE] [-o|--output-file-basename NAME]                  [-f|--force] [--no-elynx-file] COMMAND+           Analyze, and simulate multi sequence alignments.          Available options:
slynx.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               slynx-version:            0.7.1.0+version:            0.7.2.0 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>.
src/SLynx/Simulate/Options.hs view
@@ -34,6 +34,7 @@ --   -o,--output-file NAME    Specify output file NAME module SLynx.Simulate.Options   ( GammaRateHeterogeneityParams,+    MixtureModelGlobalNormalization (..),     SimulateArguments (..),     simulateArguments,     simulateFooter,@@ -53,11 +54,19 @@ -- | Number of gamma rate categories and alpha parameter. type GammaRateHeterogeneityParams = (Int, Double) +data MixtureModelGlobalNormalization = GlobalNormalization | LocalNormalization+  deriving (Show, Read, Eq, Generic)++instance FromJSON MixtureModelGlobalNormalization++instance ToJSON MixtureModelGlobalNormalization+ -- | Arguments needed to simulate sequences. data SimulateArguments = SimulateArguments   { argsTreeFile :: FilePath,     argsSubstitutionModelString :: Maybe String,     argsMixtureModelString :: Maybe String,+    argsMixtureModelGlobalNormalization :: MixtureModelGlobalNormalization,     argsEDMFile :: Maybe FilePath,     argsSiteprofilesFiles :: Maybe [FilePath],     argsMixtureWeights :: Maybe [Double],@@ -90,6 +99,7 @@     <$> treeFileOpt     <*> phyloSubstitutionModelOpt     <*> phyloMixtureModelOpt+    <*> globalNormalizationFlag     <*> maybeEDMFileOpt     <*> maybeSiteprofilesFilesOpt     <*> maybeMixtureWeights@@ -126,6 +136,16 @@           <> help             "Set the phylogenetic mixture model; available models are shown below (mutually exclusive with -s option)"       )++globalNormalizationFlag :: Parser MixtureModelGlobalNormalization+globalNormalizationFlag =+  flag+    LocalNormalization+    GlobalNormalization+    ( long "global-normalization"+        <> short 'n'+        <> help "Normalize mixture model globally (one normalization constant for all components)"+    )  maybeEDMFileOpt :: Parser (Maybe FilePath) maybeEDMFileOpt =
src/SLynx/Simulate/PhyloModel.hs view
@@ -35,11 +35,8 @@ import qualified ELynx.MarkovProcess.SubstitutionModel as S import ELynx.Tools.Equality import ELynx.Tools.InputOutput-import Numeric.LinearAlgebra-  ( norm_1,-    size,-    vector,-  )+import Numeric.LinearAlgebra (norm_1, size, vector)+import SLynx.Simulate.Options (MixtureModelGlobalNormalization (..))  nNuc :: Int -- nNuc = length (alphabet :: [Nucleotide])@@ -109,59 +106,61 @@ -- This is the main function that connects the model string, the parameters and -- the stationary distribution. It should check that the model is valid. assembleSubstitutionModel ::+  S.Normalize ->   String ->   Maybe S.Params ->   Maybe StationaryDistribution ->   Either String S.SubstitutionModel -- DNA models.-assembleSubstitutionModel "JC" Nothing Nothing = Right jc-assembleSubstitutionModel "F81" Nothing (Just d) =-  Right $ assertLength d nNuc $ f81 d-assembleSubstitutionModel "HKY" (Just [k]) (Just d) =-  Right $ assertLength d nNuc $ hky k d-assembleSubstitutionModel "GTR4" (Just es) (Just d) =-  Right $ assertLength d nNuc $ gtr4 es d+assembleSubstitutionModel nz "JC" Nothing Nothing = Right $ jc nz+assembleSubstitutionModel nz "F81" Nothing (Just d) =+  Right $ assertLength d nNuc $ f81 nz d+assembleSubstitutionModel nz "HKY" (Just [k]) (Just d) =+  Right $ assertLength d nNuc $ hky nz k d+assembleSubstitutionModel nz "GTR4" (Just es) (Just d) =+  Right $ assertLength d nNuc $ gtr4 nz es d -- Protein models.-assembleSubstitutionModel "Poisson" Nothing Nothing = Right poisson-assembleSubstitutionModel "Poisson-Custom" Nothing (Just d) =-  Right $ assertLength d nAA $ poissonCustom Nothing d-assembleSubstitutionModel "LG" Nothing Nothing = Right lg-assembleSubstitutionModel "LG-Custom" Nothing (Just d) =-  Right $ assertLength d nAA $ lgCustom Nothing d-assembleSubstitutionModel "WAG" Nothing Nothing = Right wag-assembleSubstitutionModel "WAG-Custom" Nothing (Just d) =-  Right $ assertLength d nAA $ wagCustom Nothing d-assembleSubstitutionModel "GTR20" (Just es) (Just d) =-  Right $ assertLength d nAA $ gtr20 es d+assembleSubstitutionModel nz "Poisson" Nothing Nothing = Right $ poisson nz+assembleSubstitutionModel nz "Poisson-Custom" Nothing (Just d) =+  Right $ assertLength d nAA $ poissonCustom Nothing nz d+assembleSubstitutionModel nz "LG" Nothing Nothing = Right $ lg nz+assembleSubstitutionModel nz "LG-Custom" Nothing (Just d) =+  Right $ assertLength d nAA $ lgCustom Nothing nz d+assembleSubstitutionModel nz "WAG" Nothing Nothing = Right $ wag nz+assembleSubstitutionModel nz "WAG-Custom" Nothing (Just d) =+  Right $ assertLength d nAA $ wagCustom Nothing nz d+assembleSubstitutionModel nz "GTR20" (Just es) (Just d) =+  Right $ assertLength d nAA $ gtr20 nz es d -- Ohterwisse, we cannot assemble the model.-assembleSubstitutionModel n mps mf =+assembleSubstitutionModel nz n mps mf =   Left $     unlines       [ "Cannot assemble substitution model.",+        "Normalize: " ++ show nz,         "Name: " ++ show n,         "Parameters: " ++ show mps,         "Stationary distribution: " ++ show mf       ] -parseSubstitutionModel :: Parser S.SubstitutionModel-parseSubstitutionModel = do+parseSubstitutionModel :: S.Normalize -> Parser S.SubstitutionModel+parseSubstitutionModel nz = do   n <- name   mps <- optional params   mf <- optional stationaryDistribution-  let esm = assembleSubstitutionModel n mps mf+  let esm = assembleSubstitutionModel nz n mps mf   case esm of     Left err -> fail err     Right sm -> return sm -edmModel :: [EDMComponent] -> Maybe [M.Weight] -> Parser M.MixtureModel-edmModel cs mws = do+edmModel :: MixtureModelGlobalNormalization -> [EDMComponent] -> Maybe [M.Weight] -> Parser M.MixtureModel+edmModel nz cs mws = do   _ <- string "EDM"   _ <- char mmStart   n <- name   mps <- optional params   _ <- char mmEnd   when (null cs) $ error "edmModel: no EDM components given."-  let sms = map (\c -> assembleSubstitutionModel n mps (Just $ snd c)) cs+  let sms = map (\c -> assembleSubstitutionModel subNz n mps (Just $ snd c)) cs       edmName = "EDM" ++ show (length cs)       ws = fromMaybe (map fst cs) mws       errs = [e | (Left e) <- sms]@@ -171,30 +170,36 @@     then fail $ head errs     else       return $-        M.fromSubstitutionModels edmName (V.fromList ws) (V.fromList $ rights sms)+        M.fromSubstitutionModels edmName mmNz (V.fromList ws) (V.fromList $ rights sms)+  where+    (subNz, mmNz) = case nz of+      GlobalNormalization -> (S.DoNotNormalize, S.DoNormalize)+      LocalNormalization -> (S.DoNormalize, S.DoNotNormalize) -cxxModel :: Maybe [M.Weight] -> Parser M.MixtureModel-cxxModel mws = do+cxxModel :: MixtureModelGlobalNormalization -> Maybe [M.Weight] -> Parser M.MixtureModel+cxxModel LocalNormalization _ = fail "Local normalization impossible with CXX models."+cxxModel _ mws = do   _ <- char 'C'   n <- decimal :: Parser Int   return $ cxx n mws -standardMixtureModel :: [M.Weight] -> Parser M.MixtureModel-standardMixtureModel ws = do+standardMixtureModel :: MixtureModelGlobalNormalization -> [M.Weight] -> Parser M.MixtureModel+standardMixtureModel nz ws = do   _ <- string "MIXTURE"   _ <- char mmStart-  sms <- parseSubstitutionModel `sepBy1` char separator+  sms <- parseSubstitutionModel subNz `sepBy1` char separator   _ <- char mmEnd   -- XXX: The use of `Data.List.NonEmpty.fromList` leads to uninformative error messages.-  return $ M.fromSubstitutionModels "MIXTURE" (V.fromList ws) (V.fromList sms)+  return $ M.fromSubstitutionModels "MIXTURE" mmNz (V.fromList ws) (V.fromList sms)+  where+    (subNz, mmNz) = case nz of+      GlobalNormalization -> (S.DoNotNormalize, S.DoNormalize)+      LocalNormalization -> (S.DoNormalize, S.DoNotNormalize) -mixtureModel ::-  Maybe [EDMComponent] -> Maybe [M.Weight] -> Parser M.MixtureModel-mixtureModel Nothing Nothing =-  try (cxxModel Nothing) <|> fail "No weights provided."-mixtureModel Nothing mws@(Just ws) =-  try (cxxModel mws) <|> standardMixtureModel ws-mixtureModel (Just cs) mws = edmModel cs mws+mixtureModel :: MixtureModelGlobalNormalization -> Maybe [EDMComponent] -> Maybe [M.Weight] -> Parser M.MixtureModel+mixtureModel nz Nothing Nothing = try (cxxModel nz Nothing) <|> fail "No weights provided."+mixtureModel nz Nothing mws@(Just ws) = try (cxxModel nz mws) <|> standardMixtureModel nz ws+mixtureModel nz (Just cs) mws = edmModel nz cs mws  -- | Parse the phylogenetic model string. The argument list is somewhat long, -- but models can have many parameters and we have to check for redundant@@ -206,26 +211,21 @@ getPhyloModel ::   Maybe String ->   Maybe String ->+  MixtureModelGlobalNormalization ->   Maybe [M.Weight] ->   Maybe [EDMComponent] ->   Either String P.PhyloModel-getPhyloModel Nothing Nothing _ _ = Left "No model was given. See help."-getPhyloModel (Just _) (Just _) _ _ =+getPhyloModel Nothing Nothing _ _ _ = Left "No model was given. See help."+getPhyloModel (Just _) (Just _) _ _ _ =   Left "Both, substitution and mixture model string given; use only one."-getPhyloModel (Just s) Nothing Nothing Nothing =-  Right $-    P.SubstitutionModel $-      parseStringWith-        parseSubstitutionModel-        s-getPhyloModel (Just _) Nothing (Just _) _ =+getPhyloModel (Just s) Nothing nz Nothing Nothing+  | nz == GlobalNormalization = Left "Global normalization not possible for substitution models."+  | otherwise = Right $ P.SubstitutionModel $ parseStringWith (parseSubstitutionModel S.DoNormalize) s+getPhyloModel (Just _) Nothing _ (Just _) _ =   Left "Weights given; but cannot be used with substitution model."-getPhyloModel (Just _) Nothing _ (Just _) =-  Left-    "Empirical distribution mixture model components given; but cannot be used with substitution model."-getPhyloModel Nothing (Just m) mws mcs =-  Right $-    P.MixtureModel $-      parseStringWith-        (mixtureModel mcs mws)-        m+getPhyloModel (Just _) Nothing _ _ (Just _) =+  let msg1 = "Empirical distribution mixture model components given;"+      msg2 = " but cannot be used with substitution model."+   in Left $ msg1 <> msg2+getPhyloModel Nothing (Just m) nz mws mcs =+  Right $ P.MixtureModel $ parseStringWith (mixtureModel nz mcs mws) m
src/SLynx/Simulate/Simulate.hs view
@@ -211,9 +211,10 @@     : summarizeSM (MM.substModel c)  -- Summarize a mixture model; lines to be printed to screen or log.-summarizeMM :: MM.MixtureModel -> [BL.ByteString]-summarizeMM m =+summarizeMM :: MixtureModelGlobalNormalization -> MM.MixtureModel -> [BL.ByteString]+summarizeMM nz m =   [ BL.pack $ "Mixture model: " ++ MM.name m ++ ".",+    BL.pack $ "Mixture model normalization: " ++ show nz ++ ".",     BL.pack $ "Number of components: " ++ show n ++ "."   ]     ++ detail@@ -229,9 +230,9 @@         else []  -- Summarize a phylogenetic model; lines to be printed to screen or log.-summarizePM :: MP.PhyloModel -> [BL.ByteString]-summarizePM (MP.MixtureModel mm) = summarizeMM mm-summarizePM (MP.SubstitutionModel sm) = summarizeSM sm+summarizePM :: MixtureModelGlobalNormalization -> MP.PhyloModel -> [BL.ByteString]+summarizePM nz (MP.MixtureModel mm) = summarizeMM nz mm+summarizePM _ (MP.SubstitutionModel sm) = summarizeSM sm  -- | Simulate sequences. simulateCmd :: ELynx SimulateArguments ()@@ -278,17 +279,18 @@   let ms = argsSubstitutionModelString l       mm = argsMixtureModelString l       mws = argsMixtureWeights l-      eitherPhyloModel' = getPhyloModel ms mm mws edmCsOrSiteprofiles+      nz = argsMixtureModelGlobalNormalization l+      eitherPhyloModel' = getPhyloModel ms mm nz mws edmCsOrSiteprofiles   phyloModel' <- case eitherPhyloModel' of     Left err -> lift $ error err     Right pm -> return pm   let maybeGammaParams = argsGammaParams l   phyloModel <- case maybeGammaParams of     Nothing -> do-      logInfoB $ BL.unlines $ summarizePM phyloModel'+      logInfoB $ BL.unlines $ summarizePM nz phyloModel'       return phyloModel'     Just (n, alpha) -> do-      logInfoB $ BL.intercalate "\n" $ summarizePM phyloModel'+      logInfoB $ BL.intercalate "\n" $ summarizePM nz phyloModel'       logInfoS ""       logInfoB $ BL.intercalate "\n" $ summarizeGammaRateHeterogeneity n alpha       return $ expand n alpha phyloModel'