slynx 0.2.2 → 0.3.0
raw patch · 20 files changed
+1140/−1354 lines, 20 filesdep ~asyncdep ~basedep ~bytestring
Dependency ranges changed: async, base, bytestring, containers, elynx-markov, elynx-seq, elynx-tools, elynx-tree, hmatrix, megaparsec, monad-logger, mwc-random, optparse-applicative, scientific, text, transformers, vector
Files
- ChangeLog.md +11/−0
- README.md +68/−274
- app/Main.hs +12/−15
- slynx.cabal +78/−80
- src/SLynx/Concatenate/Concatenate.hs +20/−25
- src/SLynx/Concatenate/Options.hs +23/−27
- src/SLynx/Examine/Examine.hs +105/−108
- src/SLynx/Examine/Options.hs +24/−27
- src/SLynx/Filter/Filter.hs +44/−49
- src/SLynx/Filter/Options.hs +54/−51
- src/SLynx/Options.hs +66/−69
- src/SLynx/SLynx.hs +47/−44
- src/SLynx/Simulate/Options.hs +158/−151
- src/SLynx/Simulate/PhyloModel.hs +123/−111
- src/SLynx/Simulate/Simulate.hs +134/−138
- src/SLynx/SubSample/Options.hs +46/−48
- src/SLynx/SubSample/SubSample.hs +30/−35
- src/SLynx/Tools.hs +36/−36
- src/SLynx/Translate/Options.hs +38/−38
- src/SLynx/Translate/Translate.hs +23/−28
ChangeLog.md view
@@ -2,6 +2,17 @@ # Changelog for ELynx +## Version 0.3.1; in development+++## Version 0.3.0++- **`elynx-nexus`:** library to import and export Nexus files.+- **`elynx-tree`:** major refactor and big cleanup; use rose trees with branch+ labels.+- **`elynx-tree`:** provide zippers.++ ## Version 0.2.2 - Validation and repetition of previous analyses is finally possible with the
README.md view
@@ -2,9 +2,11 @@ # The ELynx Suite -Version: 0.2.2.+Version: 0.3.0. Reproducible evolution made easy. +<p align="center"><img src="https://travis-ci.org/dschrempf/elynx.svg?branch=master"/></p>+ A Haskell library and tool set for computational biology. The goal of ELynx is reproducible research. Evolutionary sequences and phylogenetic trees can be read, viewed, modified and simulated. The command line with all arguments is@@ -12,11 +14,12 @@ sums so that validation of past analyses is possible without the need to recompute the result. -The Elynx Suite consists of four library packages and three executables providing-a range of sub commands.+The Elynx Suite consists of library packages and executables providing a range+of sub commands. The library packages are: +- **elynx-nexus:** Nexus file support. - **elynx-markov:** Simulate multi sequence alignments along phylogenetic trees. - **elynx-seq:** Handle evolutionary sequences and multi sequence alignments. - **elynx-tools:** Tools for the provided executables.@@ -43,7 +46,7 @@ 2. Clone the ELynx repository. - git clone clone https://github.com/dschrempf/elynx+ git clone https://github.com/dschrempf/elynx 3. Navigate to the newly created `elynx` folder and build the binaries. This will take a while.@@ -62,15 +65,34 @@ [PATH](https://en.wikipedia.org/wiki/PATH_(variable)) environment variable. Then, they can be used directly. +# Documentation++Documentation is available on [Hackage](https://hackage.haskell.org/).++Libraries:++- [elynx-nexus](https://hackage.haskell.org/package/elynx-nexus)+- [elynx-markov](https://hackage.haskell.org/package/elynx-markov)+- [elynx-seq](https://hackage.haskell.org/package/elynx-seq)+- [elynx-tools](https://hackage.haskell.org/package/elynx-tools)+- [elynx-tree](https://hackage.haskell.org/package/elynx-tree)++Executables:++- [elynx](https://hackage.haskell.org/package/elynx)+- [slynx](https://hackage.haskell.org/package/slynx)+- [tlynx](https://hackage.haskell.org/package/tlynx)++ # SLynx Handle evolutionary sequences. - slynx --help+ slynx --help | head -n -16 - ELynx Suite version 0.2.1.+ ELynx Suite version 0.3.0. Developed by Dominik Schrempf.- Compiled on April 27, 2020, at 12:08 pm, UTC.+ Compiled on July 30, 2020, at 12:40 pm, UTC. Usage: slynx [-v|--verbosity VALUE] [-o|--output-file-basename NAME] [-f|--force] COMMAND@@ -95,6 +117,7 @@ sub-sample Sub-sample columns from multi sequence alignments. translate Translate from DNA to Protein or DNAX to ProteinX. + Available sequence file formats: - FASTA @@ -105,23 +128,6 @@ - Protein (amino acids) - ProteinX (amino acids; including gaps) - ProteinS (amino acids; including gaps, and translation stops)- - ProteinI (amino acids; including gaps, translation stops, and IUPAC codes)- - ELynx- ------ A Haskell library and tool set for computational biology. The goal of ELynx is- reproducible research. Evolutionary sequences and phylogenetic trees can be- read, viewed, modified and simulated. The command line with all arguments is- logged consistently, and automatically. Data integrity is verified using SHA256- sums so that validation of past analyses is possible without the need to- recompute the result.- - slynx Analyze, modify, and simulate evolutionary sequences.- tlynx Analyze, modify, and simulate phylogenetic trees.- elynx Validate and redo past analyses.- - Get help for sub commands:- slynx examine --help ## Concatenate@@ -130,9 +136,9 @@ slynx concatenate --help - ELynx Suite version 0.2.1.+ ELynx Suite version 0.3.0. Developed by Dominik Schrempf.- Compiled on April 27, 2020, at 12:08 pm, UTC.+ Compiled on July 30, 2020, at 12:40 pm, UTC. Usage: slynx concatenate (-a|--alphabet NAME) INPUT-FILE Concatenate sequences found in input files.@@ -143,23 +149,6 @@ -a,--alphabet NAME Specify alphabet type NAME INPUT-FILE Read sequences from INPUT-FILE -h,--help Show this help text- - - ELynx- ------ A Haskell library and tool set for computational biology. The goal of ELynx is- reproducible research. Evolutionary sequences and phylogenetic trees can be- read, viewed, modified and simulated. The command line with all arguments is- logged consistently, and automatically. Data integrity is verified using SHA256- sums so that validation of past analyses is possible without the need to- recompute the result.- - slynx Analyze, modify, and simulate evolutionary sequences.- tlynx Analyze, modify, and simulate phylogenetic trees.- elynx Validate and redo past analyses.- - Get help for sub commands:- slynx examine --help ## Examine@@ -168,9 +157,9 @@ slynx examine --help - ELynx Suite version 0.2.1.+ ELynx Suite version 0.3.0. Developed by Dominik Schrempf.- Compiled on April 27, 2020, at 12:08 pm, UTC.+ Compiled on July 30, 2020, at 12:40 pm, UTC. Usage: slynx examine (-a|--alphabet NAME) INPUT-FILE [--per-site] Examine sequences. If data is a multi sequence alignment, additionally analyze columns.@@ -182,23 +171,6 @@ INPUT-FILE Read sequences from INPUT-FILE --per-site Report per site summary statistics -h,--help Show this help text- - - ELynx- ------ A Haskell library and tool set for computational biology. The goal of ELynx is- reproducible research. Evolutionary sequences and phylogenetic trees can be- read, viewed, modified and simulated. The command line with all arguments is- logged consistently, and automatically. Data integrity is verified using SHA256- sums so that validation of past analyses is possible without the need to- recompute the result.- - slynx Analyze, modify, and simulate evolutionary sequences.- tlynx Analyze, modify, and simulate phylogenetic trees.- elynx Validate and redo past analyses.- - Get help for sub commands:- slynx examine --help ## Filter@@ -207,9 +179,9 @@ slynx filter-rows --help - ELynx Suite version 0.2.1.+ ELynx Suite version 0.3.0. Developed by Dominik Schrempf.- Compiled on April 27, 2020, at 12:08 pm, UTC.+ Compiled on July 30, 2020, at 12:40 pm, UTC. Usage: slynx filter-rows (-a|--alphabet NAME) INPUT-FILE [--longer-than LENGTH] [--shorter-than LENGTH] [--standard-characters]@@ -225,31 +197,14 @@ --standard-characters Only keep sequences containing at least one standard (i.e., non-IUPAC) character -h,--help Show this help text- - - ELynx- ------ A Haskell library and tool set for computational biology. The goal of ELynx is- reproducible research. Evolutionary sequences and phylogenetic trees can be- read, viewed, modified and simulated. The command line with all arguments is- logged consistently, and automatically. Data integrity is verified using SHA256- sums so that validation of past analyses is possible without the need to- recompute the result.- - slynx Analyze, modify, and simulate evolutionary sequences.- tlynx Analyze, modify, and simulate phylogenetic trees.- elynx Validate and redo past analyses.- - Get help for sub commands:- slynx examine --help Filter columns of multi sequence alignments with `filter-columns`. slynx filter-columns --help - ELynx Suite version 0.2.1.+ ELynx Suite version 0.3.0. Developed by Dominik Schrempf.- Compiled on April 27, 2020, at 12:08 pm, UTC.+ Compiled on July 30, 2020, at 12:40 pm, UTC. Usage: slynx filter-columns (-a|--alphabet NAME) INPUT-FILE [--standard-chars DOUBLE]@@ -263,23 +218,6 @@ --standard-chars DOUBLE Keep columns with a proportion standard (non-IUPAC) characters larger than DOUBLE in [0,1] -h,--help Show this help text- - - ELynx- ------ A Haskell library and tool set for computational biology. The goal of ELynx is- reproducible research. Evolutionary sequences and phylogenetic trees can be- read, viewed, modified and simulated. The command line with all arguments is- logged consistently, and automatically. Data integrity is verified using SHA256- sums so that validation of past analyses is possible without the need to- recompute the result.- - slynx Analyze, modify, and simulate evolutionary sequences.- tlynx Analyze, modify, and simulate phylogenetic trees.- elynx Validate and redo past analyses.- - Get help for sub commands:- slynx examine --help ## Simulate@@ -288,9 +226,9 @@ slynx simulate --help - ELynx Suite version 0.2.1.+ ELynx Suite version 0.3.0. Developed by Dominik Schrempf.- Compiled on April 27, 2020, at 12:08 pm, UTC.+ Compiled on July 30, 2020, at 12:40 pm, UTC. Usage: slynx simulate (-t|--tree-file Name) [-s|--substitution-model MODEL] [-m|--mixture-model MODEL] [-e|--edm-file NAME] @@ -352,27 +290,13 @@ where XX is 10, 20, 30, 40, 50, or 60; CXX models, Quang et al., 2008. -m "EDM(EXCHANGEABILITIES)" Arbitrary empirical distribution mixture (EDM) models.- Stationary distributions have to be provided with the -e option.+ Stationary distributions have to be provided with the -e or -p option. For example, LG exchangeabilities with stationary distributions given in FILE. -m "EDM(LG-Custom)" -e FILE+ LG exchangeabilities with site profiles (Phylobayes) given in FILES.+ -m "EDM(LG-Custom)" -p FILES For special mixture models, mixture weights are optional.- - ELynx- ------ A Haskell library and tool set for computational biology. The goal of ELynx is- reproducible research. Evolutionary sequences and phylogenetic trees can be- read, viewed, modified and simulated. The command line with all arguments is- logged consistently, and automatically. Data integrity is verified using SHA256- sums so that validation of past analyses is possible without the need to- recompute the result.- - slynx Analyze, modify, and simulate evolutionary sequences.- tlynx Analyze, modify, and simulate phylogenetic trees.- elynx Validate and redo past analyses.- - Get help for sub commands:- slynx examine --help ## Sub-sample@@ -381,9 +305,9 @@ slynx sub-sample --help - ELynx Suite version 0.2.1.+ ELynx Suite version 0.3.0. Developed by Dominik Schrempf.- Compiled on April 27, 2020, at 12:08 pm, UTC.+ Compiled on July 30, 2020, at 12:40 pm, UTC. Usage: slynx sub-sample (-a|--alphabet NAME) INPUT-FILE (-n|--number-of-sites INT)@@ -403,22 +327,6 @@ -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.- - ELynx- ------ A Haskell library and tool set for computational biology. The goal of ELynx is- reproducible research. Evolutionary sequences and phylogenetic trees can be- read, viewed, modified and simulated. The command line with all arguments is- logged consistently, and automatically. Data integrity is verified using SHA256- sums so that validation of past analyses is possible without the need to- recompute the result.- - slynx Analyze, modify, and simulate evolutionary sequences.- tlynx Analyze, modify, and simulate phylogenetic trees.- elynx Validate and redo past analyses.- - Get help for sub commands:- slynx examine --help ## Translate@@ -427,9 +335,9 @@ slynx translate --help - ELynx Suite version 0.2.1.+ ELynx Suite version 0.3.0. Developed by Dominik Schrempf.- Compiled on April 27, 2020, at 12:08 pm, UTC.+ Compiled on July 30, 2020, at 12:40 pm, UTC. Usage: slynx translate (-a|--alphabet NAME) INPUT-FILE (-r|--reading-frame INT) (-u|--universal-code CODE)@@ -444,34 +352,17 @@ -u,--universal-code CODE universal code; one of: Standard, VertebrateMitochondrial. -h,--help Show this help text- - - ELynx- ------ A Haskell library and tool set for computational biology. The goal of ELynx is- reproducible research. Evolutionary sequences and phylogenetic trees can be- read, viewed, modified and simulated. The command line with all arguments is- logged consistently, and automatically. Data integrity is verified using SHA256- sums so that validation of past analyses is possible without the need to- recompute the result.- - slynx Analyze, modify, and simulate evolutionary sequences.- tlynx Analyze, modify, and simulate phylogenetic trees.- elynx Validate and redo past analyses.- - Get help for sub commands:- slynx examine --help # TLynx Handle phylogenetic trees in Newick format. - tlynx --help+ tlynx --help | head -n -16 - ELynx Suite version 0.2.1.+ ELynx Suite version 0.3.0. Developed by Dominik Schrempf.- Compiled on April 27, 2020, at 12:08 pm, UTC.+ Compiled on July 30, 2020, at 12:40 pm, UTC. Usage: tlynx [-v|--verbosity VALUE] [-o|--output-file-basename NAME] [-f|--force] COMMAND@@ -496,26 +387,10 @@ shuffle Shuffle a phylogenetic tree (keep coalescent times, but shuffle topology and leaves). simulate Simulate phylogenetic trees using birth and death processes (see also the 'coalesce' command for simulations using the coalescent process). + Available tree file formats: - Newick Standard: Branch support values are stored in square brackets after branch lengths. - Newick IqTree: Branch support values are stored as node names after the closing bracket of forests.- - Newick RevBayes Key-value pairs is provided in square brackets after node names as well as branch lengths. XXX: Key value pairs are IGNORED at the moment.- - ELynx- ------ A Haskell library and tool set for computational biology. The goal of ELynx is- reproducible research. Evolutionary sequences and phylogenetic trees can be- read, viewed, modified and simulated. The command line with all arguments is- logged consistently, and automatically. Data integrity is verified using SHA256- sums so that validation of past analyses is possible without the need to- recompute the result.- - slynx Analyze, modify, and simulate evolutionary sequences.- tlynx Analyze, modify, and simulate phylogenetic trees.- elynx Validate and redo past analyses.- - Get help for sub commands:- slynx examine --help ## Compare@@ -524,12 +399,12 @@ tlynx compare --help - ELynx Suite version 0.2.1.+ ELynx Suite version 0.3.0. Developed by Dominik Schrempf.- Compiled on April 27, 2020, at 12:08 pm, UTC.+ Compiled on July 30, 2020, at 12:40 pm, UTC. Usage: tlynx compare [-n|--normalize] [-b|--bipartitions] [-t|--intersect] - [-f|--newick-format FORMAT] NAME+ [-f|--newick-format FORMAT] NAMES Compare two phylogenetic trees (compute distances and branch-wise differences). Available options:@@ -540,27 +415,11 @@ -t,--intersect Compare intersections; i.e., before comparison, drop leaves that are not present in the other tree -f,--newick-format FORMAT- Newick tree format; see 'tlynx- --help' (default: Standard)- NAME Tree file+ Newick tree format: Standard, IqTree, or RevBayes;+ default: Standard; for detailed help, see 'tlynx+ --help'+ NAMES Tree files -h,--help Show this help text- - - ELynx- ------ A Haskell library and tool set for computational biology. The goal of ELynx is- reproducible research. Evolutionary sequences and phylogenetic trees can be- read, viewed, modified and simulated. The command line with all arguments is- logged consistently, and automatically. Data integrity is verified using SHA256- sums so that validation of past analyses is possible without the need to- recompute the result.- - slynx Analyze, modify, and simulate evolutionary sequences.- tlynx Analyze, modify, and simulate phylogenetic trees.- elynx Validate and redo past analyses.- - Get help for sub commands:- slynx examine --help ## Examine@@ -569,9 +428,9 @@ tlynx examine --help - ELynx Suite version 0.2.1.+ ELynx Suite version 0.3.0. Developed by Dominik Schrempf.- Compiled on April 27, 2020, at 12:08 pm, UTC.+ Compiled on July 30, 2020, at 12:40 pm, UTC. Usage: tlynx examine INPUT-FILE [-f|--newick-format FORMAT] Compute summary statistics of phylogenetic trees.@@ -581,26 +440,10 @@ -V,--version Show version INPUT-FILE Read trees from INPUT-FILE -f,--newick-format FORMAT- Newick tree format; see 'tlynx- --help' (default: Standard)+ Newick tree format: Standard, IqTree, or RevBayes;+ default: Standard; for detailed help, see 'tlynx+ --help' -h,--help Show this help text- - - ELynx- ------ A Haskell library and tool set for computational biology. The goal of ELynx is- reproducible research. Evolutionary sequences and phylogenetic trees can be- read, viewed, modified and simulated. The command line with all arguments is- logged consistently, and automatically. Data integrity is verified using SHA256- sums so that validation of past analyses is possible without the need to- recompute the result.- - slynx Analyze, modify, and simulate evolutionary sequences.- tlynx Analyze, modify, and simulate phylogenetic trees.- elynx Validate and redo past analyses.- - Get help for sub commands:- slynx examine --help ## Simulate@@ -609,9 +452,9 @@ tlynx simulate --help - ELynx Suite version 0.2.1.+ ELynx Suite version 0.3.0. Developed by Dominik Schrempf.- Compiled on April 27, 2020, at 12:08 pm, UTC.+ Compiled on July 30, 2020, at 12:40 pm, UTC. Usage: tlynx simulate [-t|--nTrees INT] [-n|--nLeaves INT] [-H|--height DOUBLE] [-M|--condition-on-mrca] [-l|--lambda DOUBLE] @@ -640,33 +483,17 @@ 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- ------ A Haskell library and tool set for computational biology. The goal of ELynx is- reproducible research. Evolutionary sequences and phylogenetic trees can be- read, viewed, modified and simulated. The command line with all arguments is- logged consistently, and automatically. Data integrity is verified using SHA256- sums so that validation of past analyses is possible without the need to- recompute the result.- - slynx Analyze, modify, and simulate evolutionary sequences.- tlynx Analyze, modify, and simulate phylogenetic trees.- elynx Validate and redo past analyses.- - Get help for sub commands:- slynx examine --help # ELynx Validate and (optionally) redo past ELynx analyses. - elynx --help+ elynx --help | head -n -16 - ELynx Suite version 0.2.1.+ ELynx Suite version 0.3.0. Developed by Dominik Schrempf.- Compiled on April 27, 2020, at 12:08 pm, UTC.+ Compiled on July 30, 2020, at 12:40 pm, UTC. Usage: elynx COMMAND Validate and redo past ELynx analyses@@ -678,37 +505,4 @@ Available commands: validate Validate an ELynx analysis redo Redo an ELynx analysis- - - ELynx- ------ A Haskell library and tool set for computational biology. The goal of ELynx is- reproducible research. Evolutionary sequences and phylogenetic trees can be- read, viewed, modified and simulated. The command line with all arguments is- logged consistently, and automatically. Data integrity is verified using SHA256- sums so that validation of past analyses is possible without the need to- recompute the result.- - slynx Analyze, modify, and simulate evolutionary sequences.- tlynx Analyze, modify, and simulate phylogenetic trees.- elynx Validate and redo past analyses.- - Get help for sub commands:- slynx examine --help---# Library documentation--Documentation of the libraries can be found on [Hackage](https://hackage.haskell.org/):--- [elynx-markov](https://hackage.haskell.org/package/elynx-markov)-- [elynx-seq](https://hackage.haskell.org/package/elynx-seq)-- [elynx-tools](https://hackage.haskell.org/package/elynx-tools)-- [elynx-tree](https://hackage.haskell.org/package/elynx-tree)--Documentation of the executables is also available:--- [elynx](https://hackage.haskell.org/package/elynx)-- [slynx](https://hackage.haskell.org/package/slynx)-- [tlynx](https://hackage.haskell.org/package/tlynx)
app/Main.hs view
@@ -1,20 +1,17 @@-{- |-Module : Main-Description : Work with molecular sequence data-Copyright : (c) Dominik Schrempf 2020-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Thu Sep 5 21:53:07 2019.---}-+-- |+-- Module : Main+-- Description : Work with molecular sequence data+-- Copyright : (c) Dominik Schrempf 2020+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Thu Sep 5 21:53:07 2019. module Main where -import SLynx.SLynx+import SLynx.SLynx main :: IO () main = rSLynx
slynx.cabal view
@@ -1,89 +1,87 @@-cabal-version: 1.12-name: slynx-version: 0.2.2-license: GPL-3-license-file: LICENSE-copyright: Dominik Schrempf (2020)-maintainer: dominik.schrempf@gmail.com-author: Dominik Schrempf-homepage: https://github.com/dschrempf/elynx#readme-bug-reports: https://github.com/dschrempf/elynx/issues-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-build-type: Simple+cabal-version: 2.2++-- This file has been generated from package.yaml by hpack version 0.34.2.+--+-- see: https://github.com/sol/hpack+--+-- hash: 826b98c0606c81f3576251bedb9ae6aa528a2afeb1a782a01a6f17578ce698af++name: slynx+version: 0.3.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>.+category: Bioinformatics+homepage: https://github.com/dschrempf/elynx#readme+bug-reports: https://github.com/dschrempf/elynx/issues+author: Dominik Schrempf+maintainer: dominik.schrempf@gmail.com+copyright: Dominik Schrempf (2020)+license: GPL-3.0-or-later+license-file: LICENSE+build-type: Simple extra-source-files: README.md ChangeLog.md source-repository head- type: git- location: https://github.com/dschrempf/elynx+ type: git+ location: https://github.com/dschrempf/elynx library- exposed-modules:- SLynx.Concatenate.Concatenate- SLynx.Concatenate.Options- SLynx.Examine.Examine- SLynx.Examine.Options- SLynx.Filter.Filter- SLynx.Filter.Options- SLynx.Options- SLynx.Simulate.Options- SLynx.Simulate.PhyloModel- SLynx.Simulate.Simulate- SLynx.SLynx- SLynx.SubSample.Options- SLynx.SubSample.SubSample- SLynx.Tools- SLynx.Translate.Options- SLynx.Translate.Translate- hs-source-dirs: src- other-modules:- Paths_slynx- default-language: Haskell2010- ghc-options: -Wall -fllvm- build-depends:- async >=2.2.2 && <2.3,- base >=4.13.0.0 && <4.14,- bytestring >=0.10.10.0 && <0.11,- containers >=0.6.2.1 && <0.7,- elynx-markov >=0.2.2 && <0.3,- elynx-seq >=0.2.1 && <0.3,- elynx-tools >=0.2.2 && <0.3,- elynx-tree >=0.2.2 && <0.3,- hmatrix >=0.20.0.0 && <0.21,- megaparsec >=8.0.0 && <8.1,- monad-logger >=0.3.32 && <0.4,- mwc-random >=0.14.0.0 && <0.15,- optparse-applicative >=0.15.1.0 && <0.16,- scientific >=0.3.6.2 && <0.4,- text >=1.2.4.0 && <1.3,- transformers >=0.5.6.2 && <0.6,- vector >=0.12.1.2 && <0.13+ exposed-modules:+ SLynx.Concatenate.Concatenate+ SLynx.Concatenate.Options+ SLynx.Examine.Examine+ SLynx.Examine.Options+ SLynx.Filter.Filter+ SLynx.Filter.Options+ SLynx.Options+ SLynx.Simulate.Options+ SLynx.Simulate.PhyloModel+ SLynx.Simulate.Simulate+ SLynx.SLynx+ SLynx.SubSample.Options+ SLynx.SubSample.SubSample+ SLynx.Tools+ SLynx.Translate.Options+ SLynx.Translate.Translate+ other-modules:+ Paths_slynx+ autogen-modules:+ Paths_slynx+ hs-source-dirs:+ src+ ghc-options: -Wall -fllvm+ build-depends:+ async+ , base >=4.7 && <5+ , bytestring+ , containers+ , elynx-markov+ , elynx-seq+ , elynx-tools+ , elynx-tree+ , hmatrix+ , megaparsec+ , monad-logger+ , mwc-random+ , optparse-applicative+ , scientific+ , text+ , transformers+ , vector+ default-language: Haskell2010 executable slynx- main-is: Main.hs- hs-source-dirs: app- other-modules:- Paths_slynx- default-language: Haskell2010- ghc-options: -Wall -fllvm -threaded -rtsopts -with-rtsopts=-N- build-depends:- async >=2.2.2 && <2.3,- base >=4.13.0.0 && <4.14,- bytestring >=0.10.10.0 && <0.11,- containers >=0.6.2.1 && <0.7,- elynx-seq >=0.2.1 && <0.3,- elynx-tools >=0.2.2 && <0.3,- hmatrix >=0.20.0.0 && <0.21,- megaparsec >=8.0.0 && <8.1,- monad-logger >=0.3.32 && <0.4,- mwc-random >=0.14.0.0 && <0.15,- optparse-applicative >=0.15.1.0 && <0.16,- scientific >=0.3.6.2 && <0.4,- slynx -any,- text >=1.2.4.0 && <1.3,- transformers >=0.5.6.2 && <0.6,- vector >=0.12.1.2 && <0.13+ main-is: Main.hs+ other-modules:+ Paths_slynx+ hs-source-dirs:+ app+ 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/Concatenate/Concatenate.hs view
@@ -1,34 +1,29 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}--{- |-Module : Analyze.Analyze-Description : Parse sequence file formats and analyze them-Copyright : (c) Dominik Schrempf 2018-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Fri Oct 5 08:41:05 2018.---}+{-# LANGUAGE TemplateHaskell #-} +-- |+-- Module : Analyze.Analyze+-- Description : Parse sequence file formats and analyze them+-- Copyright : (c) Dominik Schrempf 2018+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Fri Oct 5 08:41:05 2018. module SLynx.Concatenate.Concatenate- ( concatenateCmd+ ( concatenateCmd, ) where -import Control.Monad.Logger-import Control.Monad.Trans.Reader ( ask )--import SLynx.Concatenate.Options-import SLynx.Tools--import qualified ELynx.Data.Sequence.Sequence as S-import ELynx.Export.Sequence.Fasta-import ELynx.Tools+import Control.Monad.Logger+import Control.Monad.Trans.Reader (ask)+import qualified ELynx.Data.Sequence.Sequence as S+import ELynx.Export.Sequence.Fasta+import ELynx.Tools+import SLynx.Concatenate.Options+import SLynx.Tools -- | Concatenate sequences. concatenateCmd :: ELynx ConcatenateArguments ()
src/SLynx/Concatenate/Options.hs view
@@ -1,37 +1,33 @@ {-# LANGUAGE DeriveGeneric #-} -{- |-Module : SLynx.Concatenate.Options-Description : ELynxSeq argument parsing-Copyright : (c) Dominik Schrempf 2018-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Sun Oct 7 17:29:45 2018.---}-+-- |+-- Module : SLynx.Concatenate.Options+-- Description : ELynxSeq argument parsing+-- Copyright : (c) Dominik Schrempf 2018+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Sun Oct 7 17:29:45 2018. module SLynx.Concatenate.Options- ( ConcatenateArguments(..)- , concatenateArguments+ ( ConcatenateArguments (..),+ concatenateArguments, ) where -import Control.Applicative-import Options.Applicative--import SLynx.Tools--import ELynx.Data.Alphabet.Alphabet-import ELynx.Tools+import Control.Applicative+import ELynx.Data.Alphabet.Alphabet+import ELynx.Tools+import Options.Applicative+import SLynx.Tools -- | Arguments needed to concatenate multi sequence alignments. data ConcatenateArguments = ConcatenateArguments- { ccAlphabet :: Alphabet- , ccInFiles :: [FilePath] }+ { ccAlphabet :: Alphabet,+ ccInFiles :: [FilePath]+ } deriving (Eq, Show, Generic) instance Reproducible ConcatenateArguments where@@ -39,9 +35,9 @@ outSuffixes _ = [".fasta"] getSeed _ = Nothing setSeed = const- parser = concatenateArguments+ parser = concatenateArguments cmdName = "concatenate"- cmdDsc = ["Concatenate sequences found in input files."]+ cmdDsc = ["Concatenate sequences found in input files."] instance FromJSON ConcatenateArguments
src/SLynx/Examine/Examine.hs view
@@ -1,131 +1,128 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}--{- |--Module : Analyze.Analyze-Description : Parse sequence file formats and analyze them-Copyright : (c) Dominik Schrempf 2018-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Fri Oct 5 08:41:05 2018.---}+{-# LANGUAGE TemplateHaskell #-} +-- |+--+-- Module : Analyze.Analyze+-- Description : Parse sequence file formats and analyze them+-- Copyright : (c) Dominik Schrempf 2018+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Fri Oct 5 08:41:05 2018. module SLynx.Examine.Examine- ( examineCmd+ ( examineCmd, ) where -import Control.Monad.Logger-import Control.Monad.Trans.Reader ( ask )-import qualified Data.ByteString.Lazy.Char8 as L-import qualified Data.Set as S-import Text.Printf--import SLynx.Examine.Options-import SLynx.Tools--import qualified ELynx.Data.Alphabet.Alphabet as A+import Control.Monad.Logger+import Control.Monad.Trans.Reader (ask)+import qualified Data.ByteString.Lazy.Char8 as L+import qualified Data.Set as S+import qualified ELynx.Data.Alphabet.Alphabet as A import qualified ELynx.Data.Alphabet.Character as C import qualified ELynx.Data.Sequence.Alignment as M-import qualified ELynx.Data.Sequence.Sequence as Seq-import ELynx.Tools+import qualified ELynx.Data.Sequence.Sequence as Seq+import ELynx.Tools+import SLynx.Examine.Options+import SLynx.Tools+import Text.Printf pRow :: String -> String -> L.ByteString pRow name val = alignLeft 50 n <> alignRight 10 v- where- n = L.pack name- v = L.pack val+ where+ n = L.pack name+ v = L.pack val examineAlignment :: Bool -> M.Alignment -> L.ByteString examineAlignment perSiteFlag a = L.unlines- [ L.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- , 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- , 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:"- -- Holy crap.- , L.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):"- , 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):"- , pRow "Across whole alignment:" $ printf "%.3f" kEffMeanHomo- , pRow "Across columns without gaps:" $ printf "%.3f" kEffMeanNoGapsHomo- , pRow "Across columns without extended IUPAC characters:"- $ printf "%.3f" kEffMeanOnlyStdHomo- ]+ [ L.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,+ 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,+ 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:",+ -- Holy crap.+ L.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):",+ 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):",+ pRow "Across whole alignment:" $ printf "%.3f" kEffMeanHomo,+ pRow "Across columns without gaps:" $ printf "%.3f" kEffMeanNoGapsHomo,+ pRow "Across columns without extended IUPAC characters:" $+ printf "%.3f" kEffMeanOnlyStdHomo+ ] <> perSiteBS- where- nTot = M.length a * M.nSequences a- nIUPAC = M.countIUPACChars a- nGaps = M.countGaps a- nUnknowns = M.countUnknowns a- percentIUPAC = 100 * fromIntegral nIUPAC / fromIntegral nTot :: Double- percentGaps = 100 * fromIntegral nGaps / fromIntegral nTot :: Double- percentUnknowns = 100 * fromIntegral nUnknowns / fromIntegral nTot :: Double- aNoGaps = M.filterColsNoGaps a- aOnlyStd = M.filterColsOnlyStd aNoGaps- charFreqsPerSite = M.toFrequencyData a- charFreqs = M.distribution charFreqsPerSite- kEffs = M.kEffEntropy charFreqsPerSite- kEffsNoGaps = M.kEffEntropy . M.toFrequencyData $ aNoGaps- kEffsOnlyStd = M.kEffEntropy . M.toFrequencyData $ aOnlyStd- kEffMean = sum kEffs / fromIntegral (length kEffs)- kEffMeanNoGaps = sum kEffsNoGaps / fromIntegral (length kEffsNoGaps)- kEffMeanOnlyStd = sum kEffsOnlyStd / fromIntegral (length kEffsOnlyStd)- kEffsHomo = M.kEffHomoplasy charFreqsPerSite- kEffsNoGapsHomo = M.kEffHomoplasy . M.toFrequencyData $ aNoGaps- kEffsOnlyStdHomo = M.kEffHomoplasy . M.toFrequencyData $ aOnlyStd- kEffMeanHomo = sum kEffsHomo / fromIntegral (length kEffsHomo)- kEffMeanNoGapsHomo =- sum kEffsNoGapsHomo / fromIntegral (length kEffsNoGapsHomo)- kEffMeanOnlyStdHomo =- sum kEffsOnlyStdHomo / fromIntegral (length kEffsOnlyStdHomo)- perSiteBS = if perSiteFlag- then L.unlines- [ L.pack "Effective number of used states per site:"- , L.pack . show $ kEffs- ]- else L.empty+ where+ nTot = M.length a * M.nSequences a+ nIUPAC = M.countIUPACChars a+ nGaps = M.countGaps a+ nUnknowns = M.countUnknowns a+ percentIUPAC = 100 * fromIntegral nIUPAC / fromIntegral nTot :: Double+ percentGaps = 100 * fromIntegral nGaps / fromIntegral nTot :: Double+ percentUnknowns = 100 * fromIntegral nUnknowns / fromIntegral nTot :: Double+ aNoGaps = M.filterColsNoGaps a+ aOnlyStd = M.filterColsOnlyStd aNoGaps+ charFreqsPerSite = M.toFrequencyData a+ charFreqs = M.distribution charFreqsPerSite+ kEffs = M.kEffEntropy charFreqsPerSite+ kEffsNoGaps = M.kEffEntropy . M.toFrequencyData $ aNoGaps+ kEffsOnlyStd = M.kEffEntropy . M.toFrequencyData $ aOnlyStd+ kEffMean = sum kEffs / fromIntegral (length kEffs)+ kEffMeanNoGaps = sum kEffsNoGaps / fromIntegral (length kEffsNoGaps)+ kEffMeanOnlyStd = sum kEffsOnlyStd / fromIntegral (length kEffsOnlyStd)+ kEffsHomo = M.kEffHomoplasy charFreqsPerSite+ kEffsNoGapsHomo = M.kEffHomoplasy . M.toFrequencyData $ aNoGaps+ kEffsOnlyStdHomo = M.kEffHomoplasy . M.toFrequencyData $ aOnlyStd+ kEffMeanHomo = sum kEffsHomo / fromIntegral (length kEffsHomo)+ kEffMeanNoGapsHomo =+ sum kEffsNoGapsHomo / fromIntegral (length kEffsNoGapsHomo)+ kEffMeanOnlyStdHomo =+ sum kEffsOnlyStdHomo / fromIntegral (length kEffsOnlyStdHomo)+ perSiteBS =+ if perSiteFlag+ then+ L.unlines+ [ L.pack "Effective number of used states per site:",+ L.pack . show $ kEffs+ ]+ else L.empty examine :: Bool -> [Seq.Sequence] -> L.ByteString examine perSiteFlag ss = Seq.summarizeSequences ss <> case M.fromSequences ss of- Left _ -> L.empty+ Left _ -> L.empty Right a -> L.pack "\n" <> examineAlignment perSiteFlag a -- | Examine sequences.
src/SLynx/Examine/Options.hs view
@@ -1,46 +1,43 @@ {-# LANGUAGE DeriveGeneric #-} -{- |-Module : SLynx.Examine.Options-Description : ELynxSeq argument parsing-Copyright : (c) Dominik Schrempf 2018-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Sun Oct 7 17:29:45 2018.---}-+-- |+-- Module : SLynx.Examine.Options+-- Description : ELynxSeq argument parsing+-- Copyright : (c) Dominik Schrempf 2018+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Sun Oct 7 17:29:45 2018. module SLynx.Examine.Options- ( ExamineArguments(..)- , examineArguments+ ( ExamineArguments (..),+ examineArguments, ) where -import Options.Applicative--import SLynx.Tools--import ELynx.Data.Alphabet.Alphabet-import ELynx.Tools+import ELynx.Data.Alphabet.Alphabet+import ELynx.Tools+import Options.Applicative+import SLynx.Tools -- | Arguments needed to examine sequences. data ExamineArguments = ExamineArguments- { exAlphabet :: Alphabet- , exInFile :: FilePath- , exPerSite :: Bool }+ { exAlphabet :: Alphabet,+ exInFile :: FilePath,+ exPerSite :: Bool+ } deriving (Eq, Show, Generic) instance Reproducible ExamineArguments where inFiles = pure . exInFile outSuffixes _ = [".out"] getSeed _ = Nothing--- XXX: Probably throw error when seed is set.++ -- XXX: Probably throw error when seed is set. setSeed = const- parser = examineArguments+ parser = examineArguments cmdName = "examine" cmdDsc = [ "Examine sequences. If data is a multi sequence alignment, additionally analyze columns."
src/SLynx/Filter/Filter.hs view
@@ -1,47 +1,42 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}--{- |-Module : Analyze.Analyze-Description : Parse sequence file formats and analyze them-Copyright : (c) Dominik Schrempf 2018-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Fri Oct 5 08:41:05 2018.---}+{-# LANGUAGE TemplateHaskell #-} +-- |+-- Module : Analyze.Analyze+-- Description : Parse sequence file formats and analyze them+-- Copyright : (c) Dominik Schrempf 2018+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Fri Oct 5 08:41:05 2018. module SLynx.Filter.Filter- ( filterRowsCmd- , filterColsCmd+ ( filterRowsCmd,+ filterColsCmd, ) where -import Control.Monad ( when )-import Control.Monad.Logger-import Control.Monad.Trans.Reader ( ask )-import qualified Data.ByteString.Lazy.Char8 as L-import Data.Maybe ( fromMaybe )-import qualified Data.Text as T--import SLynx.Filter.Options-import SLynx.Tools-+import Control.Monad (when)+import Control.Monad.Logger+import Control.Monad.Trans.Reader (ask)+import qualified Data.ByteString.Lazy.Char8 as L+import Data.Maybe (fromMaybe)+import qualified Data.Text as T import qualified ELynx.Data.Sequence.Alignment as M-import qualified ELynx.Data.Sequence.Sequence as S-import ELynx.Export.Sequence.Fasta-import ELynx.Tools+import qualified ELynx.Data.Sequence.Sequence as S+import ELynx.Export.Sequence.Fasta+import ELynx.Tools+import SLynx.Filter.Options+import SLynx.Tools filterRows :: Maybe Int -> Maybe Int -> Bool -> [S.Sequence] -> L.ByteString filterRows ml ms std ss = sequencesToFasta $ compose filters ss- where- filters' =- map (fromMaybe id) [S.filterLongerThan <$> ml, S.filterShorterThan <$> ms]- filters = if std then S.filterStandard : filters' else filters'+ where+ filters' =+ map (fromMaybe id) [S.filterLongerThan <$> ml, S.filterShorterThan <$> ms]+ filters = if std then S.filterStandard : filters' else filters' -- | Filter sequences. filterRowsCmd :: ELynx FilterRowsArguments ()@@ -50,28 +45,28 @@ $(logInfo) "Command: Filter sequences of a list of sequences." maybe (return ())- (\val ->- $(logInfo) $ T.pack $ " Keep sequences longer than " <> show val <> "."+ ( \val ->+ $(logInfo) $ T.pack $ " Keep sequences longer than " <> show val <> "." ) long maybe (return ())- (\val ->- $(logInfo) $ T.pack $ " Keep sequences shorter than " <> show val <> "."+ ( \val ->+ $(logInfo) $ T.pack $ " Keep sequences shorter than " <> show val <> "." ) short- when std- $ $(logInfo)- " Keep sequences containing at least one standard (i.e., non-IUPAC) character."+ when std $+ $(logInfo)+ " Keep sequences containing at least one standard (i.e., non-IUPAC) character." ss <- readSeqs al inFile let result = filterRows long short std ss out "filtered sequences" result ".fasta" filterCols :: Maybe Double -> [S.Sequence] -> L.ByteString filterCols ms ss = sequencesToFasta . M.toSequences $ compose filters a- where- a = either error id (M.fromSequences ss)- filters = map (fromMaybe id) [M.filterColsStd <$> ms]+ where+ a = either error id (M.fromSequences ss)+ filters = map (fromMaybe id) [M.filterColsStd <$> ms] -- | Filter columns. filterColsCmd :: ELynx FilterColsArguments ()@@ -81,11 +76,11 @@ case standard of Nothing -> return () Just p ->- $(logInfo)- $ T.pack- $ " Keep columns with a proportion of standard (non-IUPAC) characters larger than "- ++ show p- ++ "."+ $(logInfo) $+ T.pack $+ " Keep columns with a proportion of standard (non-IUPAC) characters larger than "+ ++ show p+ ++ "." ss <- readSeqs al inFile let result = filterCols standard ss out "filtered sequences" result ".fasta"
src/SLynx/Filter/Options.hs view
@@ -1,42 +1,38 @@ {-# LANGUAGE DeriveGeneric #-} -{- |-Module : SLynx.Filter.Options-Description : ELynxSeq argument parsing-Copyright : (c) Dominik Schrempf 2018-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Sun Oct 7 17:29:45 2018.---}-+-- |+-- Module : SLynx.Filter.Options+-- Description : ELynxSeq argument parsing+-- Copyright : (c) Dominik Schrempf 2018+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Sun Oct 7 17:29:45 2018. module SLynx.Filter.Options- ( FilterRowsArguments(..)- , FilterColsArguments(..)- , filterRowsArguments- , filterColsArguments+ ( FilterRowsArguments (..),+ FilterColsArguments (..),+ filterRowsArguments,+ filterColsArguments, ) where -import Control.Applicative-import Options.Applicative--import SLynx.Tools--import ELynx.Data.Alphabet.Alphabet-import ELynx.Tools+import Control.Applicative+import ELynx.Data.Alphabet.Alphabet+import ELynx.Tools+import Options.Applicative+import SLynx.Tools -- | Arguments needed for filtering sequences. data FilterRowsArguments = FilterRowsArguments- { frAlphabet :: Alphabet- , frInFile :: FilePath- , frLonger :: Maybe Int- , frShorter :: Maybe Int- , frStandard :: Bool }+ { frAlphabet :: Alphabet,+ frInFile :: FilePath,+ frLonger :: Maybe Int,+ frShorter :: Maybe Int,+ frStandard :: Bool+ } deriving (Eq, Show, Generic) instance Reproducible FilterRowsArguments where@@ -44,9 +40,9 @@ outSuffixes _ = [".fasta"] getSeed _ = Nothing setSeed = const- parser = filterRowsArguments+ parser = filterRowsArguments cmdName = "filter-rows"- cmdDsc = ["Filter rows (or sequences) found in input files."]+ cmdDsc = ["Filter rows (or sequences) found in input files."] instance FromJSON FilterRowsArguments @@ -54,9 +50,10 @@ -- | Arguments needed for filtering columns of a multi sequence alignment. data FilterColsArguments = FilterColsArguments- { fcAlphabet :: Alphabet- , fcInFile :: FilePath- , fcStandard :: Maybe Double }+ { fcAlphabet :: Alphabet,+ fcInFile :: FilePath,+ fcStandard :: Maybe Double+ } deriving (Eq, Show, Generic) instance Reproducible FilterColsArguments where@@ -64,9 +61,9 @@ outSuffixes _ = [".fasta"] getSeed _ = Nothing setSeed = const- parser = filterColsArguments+ parser = filterColsArguments cmdName = "filter-columns"- cmdDsc = ["Filter columns of multi sequence alignments."]+ cmdDsc = ["Filter columns of multi sequence alignments."] instance FromJSON FilterColsArguments @@ -84,20 +81,26 @@ filterLongerThanOpt :: Parser (Maybe Int) filterLongerThanOpt =- optional $ option auto $ long "longer-than" <> metavar "LENGTH" <> help- "Only keep sequences longer than LENGTH"+ optional $+ option auto $+ long "longer-than" <> metavar "LENGTH"+ <> help+ "Only keep sequences longer than LENGTH" filterShorterThanOpt :: Parser (Maybe Int) filterShorterThanOpt =- optional $ option auto $ long "shorter-than" <> metavar "LENGTH" <> help- "Only keep sequences shorter than LENGTH"+ optional $+ option auto $+ long "shorter-than" <> metavar "LENGTH"+ <> help+ "Only keep sequences shorter than LENGTH" filterStandardChars :: Parser Bool filterStandardChars =- switch- $ long "standard-characters"- <> help- "Only keep sequences containing at least one standard (i.e., non-IUPAC) character"+ switch $+ long "standard-characters"+ <> help+ "Only keep sequences containing at least one standard (i.e., non-IUPAC) character" -- | Command line parser. filterColsArguments :: Parser FilterColsArguments@@ -106,12 +109,12 @@ filterStandardOpt :: Parser (Maybe Double) filterStandardOpt =- optional- $ option auto- $ long "standard-chars"- <> metavar "DOUBLE"- <> help- "Keep columns with a proportion standard (non-IUPAC) characters larger than DOUBLE in [0,1]"+ optional $+ option auto $+ long "standard-chars"+ <> metavar "DOUBLE"+ <> help+ "Keep columns with a proportion standard (non-IUPAC) characters larger than DOUBLE in [0,1]" inFileArg :: Parser FilePath inFileArg =
src/SLynx/Options.hs view
@@ -1,41 +1,36 @@ {-# LANGUAGE DeriveGeneric #-} -{- |-Module : SLynx.Options-Description : SLynx general options-Copyright : (c) Dominik Schrempf 2020-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Sat Sep 7 18:55:03 2019.---}-+-- |+-- Module : SLynx.Options+-- Description : SLynx general options+-- Copyright : (c) Dominik Schrempf 2020+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Sat Sep 7 18:55:03 2019. module SLynx.Options- ( Arguments(..)- , CommandArguments(..)- , parseArguments+ ( Arguments (..),+ CommandArguments (..),+ parseArguments, ) where -import Options.Applicative--import ELynx.Data.Alphabet.Alphabet-import ELynx.Tools--import SLynx.Concatenate.Options-import SLynx.Examine.Options-import SLynx.Filter.Options-import SLynx.Simulate.Options-import SLynx.SubSample.Options-import SLynx.Translate.Options+import ELynx.Data.Alphabet.Alphabet+import ELynx.Tools+import Options.Applicative+import SLynx.Concatenate.Options+import SLynx.Examine.Options+import SLynx.Filter.Options+import SLynx.Simulate.Options+import SLynx.SubSample.Options+import SLynx.Translate.Options -- | The different SLynx commands and their arguments.-data CommandArguments =- Concatenate ConcatenateArguments+data CommandArguments+ = Concatenate ConcatenateArguments | Examine ExamineArguments | FilterCols FilterColsArguments | FilterRows FilterRowsArguments@@ -46,52 +41,54 @@ instance Reproducible CommandArguments where inFiles (Concatenate a) = inFiles a- inFiles (Examine a) = inFiles a- inFiles (FilterCols a) = inFiles a- inFiles (FilterRows a) = inFiles a- inFiles (Simulate a) = inFiles a- inFiles (SubSample a) = inFiles a- inFiles (Translate a) = inFiles a+ inFiles (Examine a) = inFiles a+ inFiles (FilterCols a) = inFiles a+ inFiles (FilterRows a) = inFiles a+ inFiles (Simulate a) = inFiles a+ inFiles (SubSample a) = inFiles a+ inFiles (Translate a) = inFiles a outSuffixes (Concatenate a) = outSuffixes a- outSuffixes (Examine a) = outSuffixes a- outSuffixes (FilterCols a) = outSuffixes a- outSuffixes (FilterRows a) = outSuffixes a- outSuffixes (Simulate a) = outSuffixes a- outSuffixes (SubSample a) = outSuffixes a- outSuffixes (Translate a) = outSuffixes a+ outSuffixes (Examine a) = outSuffixes a+ outSuffixes (FilterCols a) = outSuffixes a+ outSuffixes (FilterRows a) = outSuffixes a+ outSuffixes (Simulate a) = outSuffixes a+ outSuffixes (SubSample a) = outSuffixes a+ outSuffixes (Translate a) = outSuffixes a getSeed (Concatenate a) = getSeed a- getSeed (Examine a) = getSeed a- getSeed (FilterCols a) = getSeed a- getSeed (FilterRows a) = getSeed a- getSeed (Simulate a) = getSeed a- getSeed (SubSample a) = getSeed a- getSeed (Translate a) = getSeed a+ getSeed (Examine a) = getSeed a+ getSeed (FilterCols a) = getSeed a+ getSeed (FilterRows a) = getSeed a+ getSeed (Simulate a) = getSeed a+ getSeed (SubSample a) = getSeed a+ getSeed (Translate a) = getSeed a setSeed (Concatenate a) = Concatenate . setSeed a- setSeed (Examine a) = Examine . setSeed a- setSeed (FilterCols a) = FilterCols . setSeed a- setSeed (FilterRows a) = FilterRows . setSeed a- setSeed (Simulate a) = Simulate . setSeed a- setSeed (SubSample a) = SubSample . setSeed a- setSeed (Translate a) = Translate . setSeed a+ setSeed (Examine a) = Examine . setSeed a+ setSeed (FilterCols a) = FilterCols . setSeed a+ setSeed (FilterRows a) = FilterRows . setSeed a+ setSeed (Simulate a) = Simulate . setSeed a+ setSeed (SubSample a) = SubSample . setSeed a+ setSeed (Translate a) = Translate . setSeed a - parser = commandArguments+ parser = commandArguments cmdName = "slynx" - cmdDsc = ["Analyze, and simulate multi sequence alignments."]+ cmdDsc = ["Analyze, and simulate multi sequence alignments."] cmdFtr =- ["Available sequence file formats:"]+ [ "",+ "Available sequence file formats:"+ ] ++ fs ++ ["", "Available alphabets:"] ++ as- where- toListItem = (" - " ++)- fs = map toListItem ["FASTA"]- as = map (toListItem . alphabetDescription) (allValues :: [Alphabet])+ where+ toListItem = (" - " ++)+ fs = map toListItem ["FASTA"]+ as = map (toListItem . alphabetDescription) (allValues :: [Alphabet]) instance FromJSON CommandArguments @@ -120,11 +117,11 @@ commandArguments :: Parser CommandArguments commandArguments =- hsubparser- $ concatenateCommand- <> examineCommand- <> filterColumnsCommand- <> filterRowsCommand- <> simulateCommand- <> subSampleCommand- <> translateCommand+ hsubparser $+ concatenateCommand+ <> examineCommand+ <> filterColumnsCommand+ <> filterRowsCommand+ <> simulateCommand+ <> subSampleCommand+ <> translateCommand
src/SLynx/SLynx.hs view
@@ -1,60 +1,63 @@-{- |-Module : SLynx.SLynx-Description : SLynx module-Copyright : (c) Dominik Schrempf 2020-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Thu Apr 23 16:38:55 2020.---}-+-- |+-- Module : SLynx.SLynx+-- Description : SLynx module+-- Copyright : (c) Dominik Schrempf 2020+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Thu Apr 23 16:38:55 2020. module SLynx.SLynx- ( slynx- , rSLynx+ ( slynx,+ rSLynx, ) where -import SLynx.Options--import SLynx.Concatenate.Concatenate-import SLynx.Examine.Examine-import SLynx.Filter.Filter-import SLynx.Simulate.Simulate-import SLynx.SubSample.SubSample-import SLynx.Translate.Translate--import ELynx.Tools+import ELynx.Tools+import SLynx.Concatenate.Concatenate+import SLynx.Examine.Examine+import SLynx.Filter.Filter+import SLynx.Options+import SLynx.Simulate.Simulate+import SLynx.SubSample.SubSample+import SLynx.Translate.Translate -- TODO: Use a class here (e.g., elynx-wrappable) which defines the extractor function.+ -- | Run SLynx with given arguments. slynx :: Arguments CommandArguments -> IO () slynx c = case local c of- Concatenate _ -> eLynxWrapper- c- (\(Arguments g (Concatenate l)) -> Arguments g l)- concatenateCmd+ Concatenate _ ->+ eLynxWrapper+ c+ (\(Arguments g (Concatenate l)) -> Arguments g l)+ concatenateCmd Examine _ -> eLynxWrapper c (\(Arguments g (Examine l)) -> Arguments g l) examineCmd- FilterCols _ -> eLynxWrapper- c- (\(Arguments g (FilterCols l)) -> Arguments g l)- filterColsCmd- FilterRows _ -> eLynxWrapper- c- (\(Arguments g (FilterRows l)) -> Arguments g l)- filterRowsCmd+ FilterCols _ ->+ eLynxWrapper+ c+ (\(Arguments g (FilterCols l)) -> Arguments g l)+ filterColsCmd+ FilterRows _ ->+ eLynxWrapper+ c+ (\(Arguments g (FilterRows l)) -> Arguments g l)+ filterRowsCmd Simulate _ -> eLynxWrapper c (\(Arguments g (Simulate l)) -> Arguments g l) simulateCmd- SubSample _ -> eLynxWrapper c- (\(Arguments g (SubSample l)) -> Arguments g l)- subSampleCmd- Translate _ -> eLynxWrapper c- (\(Arguments g (Translate l)) -> Arguments g l)- translateCmd+ SubSample _ ->+ eLynxWrapper+ c+ (\(Arguments g (SubSample l)) -> Arguments g l)+ subSampleCmd+ Translate _ ->+ eLynxWrapper+ c+ (\(Arguments g (Translate l)) -> Arguments g l)+ translateCmd -- | Run SLynx, parse arguments from command line. rSLynx :: IO ()
src/SLynx/Simulate/Options.hs view
@@ -1,85 +1,80 @@ {-# LANGUAGE DeriveGeneric #-} -{- |-Module : SLynx.Simulate.Options-Description : ELynxSim argument parsing-Copyright : (c) Dominik Schrempf 2018-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Sun Oct 7 17:29:45 2018.--Available options:- -h,--help Show this help text- -v,--version Show version- -t,--tree-file NAME Specify tree file NAME- -s,--substitution-model MODEL- Set the phylogenetic substitution model; available- models are shown below- -m,--mixture-model MODEL Set the phylogenetic mixture model; available models- are shown below- -l,--length NUMBER Set alignment length to NUMBER- -e,--edm-file NAME empirical distribution model file NAME in Phylobayes- format- -w,--mixture-model-weights [DOUBLE,DOUBLE,...]- weights of mixture model components- -g,--gamma-rate-heterogeneity (NCAT, SHAPE)- number of gamma rate categories and shape parameter- -e,--seed [INT] Set seed for the random number generator; list of 32- bit integers with up to 256 elements (default: [0])- -q,--quiet Be quiet- -o,--output-file NAME Specify output file NAME----}--+-- |+-- Module : SLynx.Simulate.Options+-- Description : ELynxSim argument parsing+-- Copyright : (c) Dominik Schrempf 2018+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Sun Oct 7 17:29:45 2018.+--+-- Available options:+-- -h,--help Show this help text+-- -v,--version Show version+-- -t,--tree-file NAME Specify tree file NAME+-- -s,--substitution-model MODEL+-- Set the phylogenetic substitution model; available+-- models are shown below+-- -m,--mixture-model MODEL Set the phylogenetic mixture model; available models+-- are shown below+-- -l,--length NUMBER Set alignment length to NUMBER+-- -e,--edm-file NAME empirical distribution model file NAME in Phylobayes+-- format+-- -w,--mixture-model-weights [DOUBLE,DOUBLE,...]+-- weights of mixture model components+-- -g,--gamma-rate-heterogeneity (NCAT, SHAPE)+-- number of gamma rate categories and shape parameter+-- -e,--seed [INT] Set seed for the random number generator; list of 32+-- bit integers with up to 256 elements (default: [0])+-- -q,--quiet Be quiet+-- -o,--output-file NAME Specify output file NAME module SLynx.Simulate.Options- ( GammaRateHeterogeneityParams- , SimulateArguments(..)- , simulateArguments- , simulateFooter+ ( GammaRateHeterogeneityParams,+ SimulateArguments (..),+ simulateArguments,+ simulateFooter, ) where -import Data.Maybe ( maybeToList- , fromMaybe- )-import Options.Applicative--import ELynx.Tools+import Data.Maybe+ ( fromMaybe,+ maybeToList,+ )+import ELynx.Tools+import Options.Applicative -- | Number of gamma rate categories and alpha parameter. type GammaRateHeterogeneityParams = (Int, Double) -- | Arguments needed to simulate sequences. data SimulateArguments = SimulateArguments- { argsTreeFile :: FilePath- , argsSubstitutionModelString :: Maybe String- , argsMixtureModelString :: Maybe String- , argsEDMFile :: Maybe FilePath- , argsSiteprofilesFiles :: Maybe [FilePath]- , argsMixtureWeights :: Maybe [Double]- , argsGammaParams :: Maybe GammaRateHeterogeneityParams- , argsLength :: Int- , argsSeed :: Seed+ { argsTreeFile :: FilePath,+ argsSubstitutionModelString :: Maybe String,+ argsMixtureModelString :: Maybe String,+ argsEDMFile :: Maybe FilePath,+ argsSiteprofilesFiles :: Maybe [FilePath],+ argsMixtureWeights :: Maybe [Double],+ argsGammaParams :: Maybe GammaRateHeterogeneityParams,+ argsLength :: Int,+ argsSeed :: Seed } deriving (Eq, Show, Generic) instance Reproducible SimulateArguments where inFiles a =- argsTreeFile a- : (maybeToList (argsEDMFile a) ++ fromMaybe [] (argsSiteprofilesFiles a))+ argsTreeFile a :+ (maybeToList (argsEDMFile a) ++ fromMaybe [] (argsSiteprofilesFiles a)) outSuffixes _ = [".model.gz", ".fasta"] getSeed = Just . argsSeed- setSeed a s = a { argsSeed = Fixed s }- parser = simulateArguments+ setSeed a s = a {argsSeed = Fixed s}+ parser = simulateArguments cmdName = "simulate"- cmdDsc = ["Simulate multi sequence alignments."]- cmdFtr = simulateFooter+ cmdDsc = ["Simulate multi sequence alignments."]+ cmdFtr = simulateFooter instance FromJSON SimulateArguments @@ -101,112 +96,124 @@ treeFileOpt :: Parser FilePath treeFileOpt =- strOption $ long "tree-file" <> short 't' <> metavar "Name" <> help- "Read tree from Newick file NAME"+ strOption $+ long "tree-file" <> short 't' <> metavar "Name"+ <> help+ "Read tree from Newick file NAME" phyloSubstitutionModelOpt :: Parser (Maybe String) phyloSubstitutionModelOpt =- optional- $ strOption- $ long "substitution-model"- <> short 's'- <> metavar "MODEL"- <> help- "Set the phylogenetic substitution model; available models are shown below (mutually exclusive with -m option)"+ optional $+ strOption $+ long "substitution-model"+ <> short 's'+ <> metavar "MODEL"+ <> help+ "Set the phylogenetic substitution model; available models are shown below (mutually exclusive with -m option)" phyloMixtureModelOpt :: Parser (Maybe String)-phyloMixtureModelOpt = optional $ strOption- ( long "mixture-model"- <> short 'm'- <> metavar "MODEL"- <> help- "Set the phylogenetic mixture model; available models are shown below (mutually exclusive with -s option)"- )+phyloMixtureModelOpt =+ optional $+ strOption+ ( long "mixture-model"+ <> short 'm'+ <> metavar "MODEL"+ <> help+ "Set the phylogenetic mixture model; available models are shown below (mutually exclusive with -s option)"+ ) maybeEDMFileOpt :: Parser (Maybe FilePath)-maybeEDMFileOpt = optional $ strOption- (long "edm-file" <> short 'e' <> metavar "NAME" <> help- "Empirical distribution model file NAME in Phylobayes format"- )---- fn :: Parsec Void String FilePath--- fn = space *> takeWhile1P () <* space---- fns :: Parsec Void String [FilePath]--- fns = do--- many string+maybeEDMFileOpt =+ optional $+ strOption+ ( long "edm-file" <> short 'e' <> metavar "NAME"+ <> help+ "Empirical distribution model file NAME in Phylobayes format"+ ) maybeSiteprofilesFilesOpt :: Parser (Maybe [FilePath])-maybeSiteprofilesFilesOpt = optional $ words <$> strOption- (long "siteprofile-files" <> short 'p' <> metavar "NAMES" <> help- "File names of site profiles in Phylobayes format"- )+maybeSiteprofilesFilesOpt =+ optional $+ words+ <$> strOption+ ( long "siteprofile-files" <> short 'p' <> metavar "NAMES"+ <> help+ "File names of site profiles in Phylobayes format"+ ) maybeMixtureWeights :: Parser (Maybe [Double])-maybeMixtureWeights = optional $ option- auto- ( long "mixture-model-weights"- <> short 'w'- <> metavar "\"[DOUBLE,DOUBLE,...]\""- <> help "Weights of mixture model components"- )+maybeMixtureWeights =+ optional $+ option+ auto+ ( long "mixture-model-weights"+ <> short 'w'+ <> metavar "\"[DOUBLE,DOUBLE,...]\""+ <> help "Weights of mixture model components"+ ) maybeGammaParams :: Parser (Maybe GammaRateHeterogeneityParams)-maybeGammaParams = optional $ option- auto- ( long "gamma-rate-heterogeneity"- <> short 'g'- <> metavar "\"(NCAT,SHAPE)\""- <> help "Number of gamma rate categories and shape parameter"- )+maybeGammaParams =+ optional $+ option+ auto+ ( long "gamma-rate-heterogeneity"+ <> short 'g'+ <> metavar "\"(NCAT,SHAPE)\""+ <> help "Number of gamma rate categories and shape parameter"+ ) lengthOpt :: Parser Int-lengthOpt = option- auto- (long "length" <> short 'l' <> metavar "NUMBER" <> help- "Set alignment length to NUMBER"- )+lengthOpt =+ option+ auto+ ( long "length" <> short 'l' <> metavar "NUMBER"+ <> help+ "Set alignment length to NUMBER"+ ) -- | The model specification is somewhat complicated, so we need to provide -- additional help. simulateFooter :: [String] simulateFooter = sms ++ mms- where- sms =- [ "Substitution models:"- , "-s \"MODEL[PARAMETER,PARAMETER,...]{STATIONARY_DISTRIBUTION}\""- , " Supported DNA models: JC, F81, HKY, GTR4."- , " For example,"- , " -s HKY[KAPPA]{DOUBLE,DOUBLE,DOUBLE,DOUBLE}"- , " -s GTR4[e_AC,e_AG,e_AT,e_CG,e_CT,e_GT]{DOUBLE,DOUBLE,DOUBLE,DOUBLE}"- , " where the 'e_XY' are the exchangeabilities from nucleotide X to Y."- , " Supported Protein models: Poisson, Poisson-Custom, LG, LG-Custom, WAG, WAG-Custom, GTR20."- , " MODEL-Custom means that only the exchangeabilities of MODEL are used,"- , " and a custom stationary distribution is provided."- , " For example,"- , " -s LG"- , " -s LG-Custom{...}"- , " -s GTR20[e_AR,e_AN,...]{...}"- , " the 'e_XY' are the exchangeabilities from amino acid X to Y (alphabetical order)."- , " Notes: The F81 model for DNA is equivalent to the Poisson-Custom for proteins."- , " The GTR4 model for DNA is equivalent to the GTR20 for proteins."- ]- mms =- [ ""- , "Mixture models:"- , "-m \"MIXTURE(SUBSTITUTION_MODEL_1,SUBSTITUTION_MODEL_2[PARAMETERS]{STATIONARY_DISTRIBUTION},...)\""- , " For example,"- , " -m \"MIXTURE(JC,HKY[6.0]{0.3,0.2,0.2,0.3})\""- , "Mixture weights have to be provided with the -w option."- , ""- , "Special mixture models:"- , "-m CXX"- , " where XX is 10, 20, 30, 40, 50, or 60; CXX models, Quang et al., 2008."- , "-m \"EDM(EXCHANGEABILITIES)\""- , " Arbitrary empirical distribution mixture (EDM) models."- , " Stationary distributions have to be provided with the -e option."- , " For example,"- , " LG exchangeabilities with stationary distributions given in FILE."- , " -m \"EDM(LG-Custom)\" -e FILE"- , "For special mixture models, mixture weights are optional."- ]+ where+ sms =+ [ "Substitution models:",+ "-s \"MODEL[PARAMETER,PARAMETER,...]{STATIONARY_DISTRIBUTION}\"",+ " Supported DNA models: JC, F81, HKY, GTR4.",+ " For example,",+ " -s HKY[KAPPA]{DOUBLE,DOUBLE,DOUBLE,DOUBLE}",+ " -s GTR4[e_AC,e_AG,e_AT,e_CG,e_CT,e_GT]{DOUBLE,DOUBLE,DOUBLE,DOUBLE}",+ " where the 'e_XY' are the exchangeabilities from nucleotide X to Y.",+ " Supported Protein models: Poisson, Poisson-Custom, LG, LG-Custom, WAG, WAG-Custom, GTR20.",+ " MODEL-Custom means that only the exchangeabilities of MODEL are used,",+ " and a custom stationary distribution is provided.",+ " For example,",+ " -s LG",+ " -s LG-Custom{...}",+ " -s GTR20[e_AR,e_AN,...]{...}",+ " the 'e_XY' are the exchangeabilities from amino acid X to Y (alphabetical order).",+ " Notes: The F81 model for DNA is equivalent to the Poisson-Custom for proteins.",+ " The GTR4 model for DNA is equivalent to the GTR20 for proteins."+ ]+ mms =+ [ "",+ "Mixture models:",+ "-m \"MIXTURE(SUBSTITUTION_MODEL_1,SUBSTITUTION_MODEL_2[PARAMETERS]{STATIONARY_DISTRIBUTION},...)\"",+ " For example,",+ " -m \"MIXTURE(JC,HKY[6.0]{0.3,0.2,0.2,0.3})\"",+ "Mixture weights have to be provided with the -w option.",+ "",+ "Special mixture models:",+ "-m CXX",+ " where XX is 10, 20, 30, 40, 50, or 60; CXX models, Quang et al., 2008.",+ "-m \"EDM(EXCHANGEABILITIES)\"",+ " Arbitrary empirical distribution mixture (EDM) models.",+ " Stationary distributions have to be provided with the -e or -p option.",+ " For example,",+ " LG exchangeabilities with stationary distributions given in FILE.",+ " -m \"EDM(LG-Custom)\" -e FILE",+ " LG exchangeabilities with site profiles (Phylobayes) given in FILES.",+ " -m \"EDM(LG-Custom)\" -p FILES",+ "For special mixture models, mixture weights are optional."+ ]
src/SLynx/Simulate/PhyloModel.hs view
@@ -1,51 +1,46 @@-{- |-Module : SLynx.Simulate.PhyloModel-Description : Parse and interpret the model string-Copyright : (c) Dominik Schrempf 2020-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Fri Feb 1 13:32:16 2019.---}-+-- |+-- Module : SLynx.Simulate.PhyloModel+-- Description : Parse and interpret the model string+-- Copyright : (c) Dominik Schrempf 2020+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Fri Feb 1 13:32:16 2019. module SLynx.Simulate.PhyloModel- ( getPhyloModel+ ( getPhyloModel, ) where -import Control.Monad ( when )-import qualified Data.ByteString.Lazy.Char8 as L-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 Numeric.LinearAlgebra ( norm_1- , size- , vector- )-import Text.Megaparsec-import Text.Megaparsec.Byte-import Text.Megaparsec.Byte.Lexer--import ELynx.Data.MarkovProcess.AminoAcid-import ELynx.Data.MarkovProcess.CXXModels-import qualified ELynx.Data.MarkovProcess.MixtureModel- as M-import ELynx.Data.MarkovProcess.Nucleotide-import qualified ELynx.Data.MarkovProcess.PhyloModel- as P-import ELynx.Data.MarkovProcess.RateMatrix-import qualified ELynx.Data.MarkovProcess.SubstitutionModel- as S-import ELynx.Import.MarkovProcess.EDMModelPhylobayes- ( EDMComponent )-import ELynx.Tools+import Control.Monad (when)+import qualified Data.ByteString.Lazy.Char8 as L+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+import ELynx.Data.MarkovProcess.Nucleotide+import qualified ELynx.Data.MarkovProcess.PhyloModel as P+import ELynx.Data.MarkovProcess.RateMatrix+import qualified ELynx.Data.MarkovProcess.SubstitutionModel as S+import ELynx.Import.MarkovProcess.EDMModelPhylobayes+ ( EDMComponent,+ )+import ELynx.Tools+import Numeric.LinearAlgebra+ ( norm_1,+ size,+ vector,+ )+import Text.Megaparsec+import Text.Megaparsec.Byte+import Text.Megaparsec.Byte.Lexer type Parser = Parsec Void L.ByteString @@ -85,48 +80,56 @@ separator = c2w ',' name :: Parser String-name = L.unpack <$> takeWhile1P- (Just "Model name")- (`notElem` [paramsStart, paramsEnd, sdStart, sdEnd, mmStart, mmEnd, separator]- )+name =+ L.unpack+ <$> takeWhile1P+ (Just "Model name")+ ( `notElem` [paramsStart, paramsEnd, sdStart, sdEnd, mmStart, mmEnd, separator]+ ) params :: Parser [Double]-params = map toRealFloat <$> between (char paramsStart)- (char paramsEnd)- (sepBy1 scientific (char separator))+params =+ map toRealFloat+ <$> between+ (char paramsStart)+ (char paramsEnd)+ (sepBy1 scientific (char separator)) stationaryDistribution :: Parser StationaryDistribution stationaryDistribution = do- f <- vector . map toRealFloat <$> between- (char sdStart)- (char sdEnd)- (sepBy1 scientific (char separator))+ f <-+ vector . map toRealFloat+ <$> between+ (char sdStart)+ (char sdEnd)+ (sepBy1 scientific (char separator)) if nearlyEq (norm_1 f) 1.0 then return f else- error- $ "Sum of stationary distribution is "- ++ show (norm_1 f)- ++ " but should be 1.0."+ error $+ "Sum of stationary distribution is "+ ++ show (norm_1 f)+ ++ " but should be 1.0." assertLength :: StationaryDistribution -> Int -> a -> a-assertLength d n r = if size d /= n- then- error- $ "Length of stationary distribution is "- ++ show (size d)- ++ " but should be "- ++ show n- ++ "."- else r+assertLength d n r =+ if size d /= n+ then+ error $+ "Length of stationary distribution is "+ ++ show (size d)+ ++ " but should be "+ ++ show n+ ++ "."+ else r -- 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- :: String- -> Maybe S.Params- -> Maybe StationaryDistribution- -> Either String S.SubstitutionModel+assembleSubstitutionModel ::+ String ->+ Maybe S.Params ->+ Maybe StationaryDistribution ->+ Either String S.SubstitutionModel -- DNA models. assembleSubstitutionModel "JC" Nothing Nothing = Right jc assembleSubstitutionModel "F81" Nothing (Just d) =@@ -148,41 +151,44 @@ assembleSubstitutionModel "GTR20" (Just es) (Just d) = Right $ assertLength d nAA $ gtr20 es d -- Ohterwisse, we cannot assemble the model.-assembleSubstitutionModel n mps mf = Left $ unlines- [ "Cannot assemble substitution model."- , "Name: " ++ show n- , "Parameters: " ++ show mps- , "Stationary distribution: " ++ show mf- ]+assembleSubstitutionModel n mps mf =+ Left $+ unlines+ [ "Cannot assemble substitution model.",+ "Name: " ++ show n,+ "Parameters: " ++ show mps,+ "Stationary distribution: " ++ show mf+ ] parseSubstitutionModel :: Parser S.SubstitutionModel parseSubstitutionModel = do- n <- name+ n <- name mps <- optional params- mf <- optional stationaryDistribution+ mf <- optional stationaryDistribution let esm = assembleSubstitutionModel n mps mf case esm of- Left err -> fail err- Right sm -> return sm+ Left err -> fail err+ Right sm -> return sm edmModel :: [EDMComponent] -> Maybe [M.Weight] -> Parser M.MixtureModel edmModel cs mws = do- _ <- chunk (bs "EDM")- _ <- char mmStart- n <- name+ _ <- chunk (bs "EDM")+ _ <- char mmStart+ n <- name mps <- optional params- _ <- char mmEnd+ _ <- 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 n mps (Just $ snd c)) cs edmName = "EDM" ++ show (length cs)- ws = fromMaybe (map fst cs) mws- errs = [ e | (Left e) <- sms ]- when (length sms /= length ws)- $ error "edmModel: number of substitution models and weights differs."+ ws = fromMaybe (map fst cs) mws+ errs = [e | (Left e) <- sms]+ when (length sms /= length ws) $+ error "edmModel: number of substitution models and weights differs." if not $ null errs then fail $ head errs- else return- $ M.fromSubstitutionModels edmName (fromList ws) (fromList $ rights sms)+ else+ return $+ M.fromSubstitutionModels edmName (fromList ws) (fromList $ rights sms) cxxModel :: Maybe [M.Weight] -> Parser M.MixtureModel cxxModel mws = do@@ -192,15 +198,15 @@ standardMixtureModel :: [M.Weight] -> Parser M.MixtureModel standardMixtureModel ws = do- _ <- chunk (bs "MIXTURE")- _ <- char mmStart+ _ <- chunk (bs "MIXTURE")+ _ <- char mmStart sms <- parseSubstitutionModel `sepBy1` char separator- _ <- char mmEnd+ _ <- char mmEnd -- XXX: The use of `Data.List.NonEmpty.fromList` leads to uninformative error messages. return $ M.fromSubstitutionModels "MIXTURE" (fromList ws) (fromList sms) -mixtureModel- :: Maybe [EDMComponent] -> Maybe [M.Weight] -> Parser M.MixtureModel+mixtureModel ::+ Maybe [EDMComponent] -> Maybe [M.Weight] -> Parser M.MixtureModel mixtureModel Nothing Nothing = try (cxxModel Nothing) <|> fail "No weights provided." mixtureModel Nothing mws@(Just ws) =@@ -214,25 +220,31 @@ -- @ -- getPhyloModel maybeSubstitutionModelString maybeMixtureModelString maybeEDMComponents -- @-getPhyloModel- :: Maybe String- -> Maybe String- -> Maybe [M.Weight]- -> Maybe [EDMComponent]- -> Either String P.PhyloModel+getPhyloModel ::+ Maybe String ->+ Maybe String ->+ Maybe [M.Weight] ->+ Maybe [EDMComponent] ->+ Either String P.PhyloModel 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 "Substitution model string"- parseSubstitutionModel- s+ Right $+ P.SubstitutionModel $+ parseStringWith+ "Substitution model string"+ parseSubstitutionModel+ 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 "Mixture model string"- (mixtureModel mcs mws)- m+ Right $+ P.MixtureModel $+ parseStringWith+ "Mixture model string"+ (mixtureModel mcs mws)+ m
src/SLynx/Simulate/Simulate.hs view
@@ -1,126 +1,121 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}--{- |-Module : SLynx.Simulate.Simulate-Description : Simulate multiple sequence alignments-Copyright : (c) Dominik Schrempf 2020-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Mon Jan 28 14:12:52 2019.---}+{-# LANGUAGE TemplateHaskell #-} +-- |+-- Module : SLynx.Simulate.Simulate+-- Description : Simulate multiple sequence alignments+-- Copyright : (c) Dominik Schrempf 2020+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Mon Jan 28 14:12:52 2019. module SLynx.Simulate.Simulate- ( simulateCmd+ ( simulateCmd, ) where -import Control.Applicative ( (<|>) )-import Control.Concurrent-import Control.Concurrent.Async-import Control.Monad ( unless- , when- )-import Control.Monad.IO.Class-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 Data.List.NonEmpty ( toList )-import Data.Maybe-import qualified Data.Set as Set-import qualified Data.Text as T-import qualified Data.Text.Lazy as LT-import qualified Data.Text.Lazy.Encoding as LT-import Data.Tree-import qualified Data.Vector.Unboxed as V-import Numeric.LinearAlgebra hiding ( (<>)- , toList- )-import System.Random.MWC--import SLynx.Simulate.Options-import SLynx.Simulate.PhyloModel--import ELynx.Data.Alphabet.Alphabet as A-import ELynx.Data.MarkovProcess.GammaRateHeterogeneity-import qualified ELynx.Data.MarkovProcess.MixtureModel- as M-import qualified ELynx.Data.MarkovProcess.PhyloModel- as P-import qualified ELynx.Data.MarkovProcess.SubstitutionModel- as SM+import Control.Applicative ((<|>))+import Control.Concurrent+import Control.Concurrent.Async+import Control.Monad+ ( unless,+ when,+ )+import Control.Monad.IO.Class+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 Data.List.NonEmpty (toList)+import Data.Maybe+import qualified Data.Set as Set+import qualified Data.Text as T+import qualified Data.Text.Lazy as LT+import qualified Data.Text.Lazy.Encoding as LT+import qualified Data.Vector.Unboxed as V+import ELynx.Data.Alphabet.Alphabet as A+import ELynx.Data.MarkovProcess.GammaRateHeterogeneity+import qualified ELynx.Data.MarkovProcess.MixtureModel as M+import qualified ELynx.Data.MarkovProcess.PhyloModel as P+import qualified ELynx.Data.MarkovProcess.SubstitutionModel as SM import qualified ELynx.Data.Sequence.Alignment as A-import qualified ELynx.Data.Sequence.Sequence as Seq- hiding ( name )-import ELynx.Data.Tree-import ELynx.Export.Sequence.Fasta-import ELynx.Import.MarkovProcess.EDMModelPhylobayes- hiding ( Parser )-import ELynx.Import.MarkovProcess.SiteprofilesPhylobayes-import ELynx.Import.Tree.Newick- hiding ( name )-import ELynx.Simulate.MarkovProcessAlongTree--import ELynx.Tools+import qualified ELynx.Data.Sequence.Sequence as Seq hiding+ ( name,+ )+import ELynx.Data.Tree+import ELynx.Export.Sequence.Fasta+import ELynx.Import.MarkovProcess.EDMModelPhylobayes hiding+ ( Parser,+ )+import ELynx.Import.MarkovProcess.SiteprofilesPhylobayes+import ELynx.Import.Tree.Newick+import ELynx.Simulate.MarkovProcessAlongTree+import ELynx.Tools+import Numeric.LinearAlgebra hiding+ ( toList,+ (<>),+ )+import SLynx.Simulate.Options+import SLynx.Simulate.PhyloModel+import System.Random.MWC -- Simulate a 'Alignment' for a given phylogenetic model, -- phylogenetic tree, and alignment length.-simulateAlignment- :: (Measurable a, Named a)- => P.PhyloModel- -> Tree a- -> Int- -> GenIO- -> IO A.Alignment-simulateAlignment pm t n g = do- c <- getNumCapabilities+simulateAlignment ::+ (Measurable e, Named a) =>+ P.PhyloModel ->+ Tree e a ->+ Int ->+ GenIO ->+ IO A.Alignment+simulateAlignment pm t' n g = do+ let t = getLen <$> toTreeBranchLabels t'+ c <- getNumCapabilities gs <- splitGen c g let chunks = getChunks c n leafStatesS <- case pm of- -- XXX @performace: This parallelization is not very intelligent, because- -- the matrices exponentiation is done in all threads. So ten threads will+ -- TODO @performace: This parallelization is not very intelligent, because+ -- the matrix exponentiation is done in all threads. So ten threads will -- exponentiate the same matrix ten times.- P.SubstitutionModel sm -> mapConcurrently- (\(num, gen) -> simulateAndFlatten num d e t gen)- (zip chunks gs)- where- d = SM.stationaryDistribution sm- e = SM.exchangeabilityMatrix sm+ P.SubstitutionModel sm ->+ mapConcurrently+ (\(num, gen) -> simulateAndFlatten num d e t gen)+ (zip chunks gs)+ where+ d = SM.stationaryDistribution sm+ e = SM.exchangeabilityMatrix sm -- P.MixtureModel mm -> mapConcurrently -- (\(num, gen) -> simulateAndFlattenNSitesAlongTreeMixtureModel num ws ds es t gen) (zip chunks gs) P.MixtureModel mm -> simulateAndFlattenMixtureModelPar n ws ds es t g- where- ws = vector . toList $ M.getWeights mm- ds = map SM.stationaryDistribution $ toList $ M.getSubstitutionModels mm- es = map SM.exchangeabilityMatrix $ toList $ M.getSubstitutionModels mm+ where+ ws = vector . toList $ M.getWeights mm+ ds = map SM.stationaryDistribution $ toList $ M.getSubstitutionModels mm+ es = map SM.exchangeabilityMatrix $ toList $ M.getSubstitutionModels mm -- XXX @performace. The horizontal concatenation might be slow. If so, -- 'concatenateSeqs' or 'concatenateAlignments' can be used, which directly -- appends vectors. let leafStates = horizontalConcat leafStatesS- leafNames = map getName $ leaves t- code = P.getAlphabet pm+ leafNames = map getName $ leaves t'+ code = P.getAlphabet pm -- XXX: Probably use type safe stuff here?- alph = A.all $ alphabetSpec code+ alph = A.all $ alphabetSpec code sequences = [ Seq.Sequence sName "" code (V.fromList $ map (`Set.elemAt` alph) ss)- | (sName, ss) <- zip leafNames leafStates+ | (sName, ss) <- zip leafNames leafStates ] return $ either error id $ A.fromSequences sequences -- Summarize EDM components; line to be printed to screen or log. summarizeEDMComponents :: [EDMComponent] -> L.ByteString summarizeEDMComponents cs =- LC.pack- $ "Empiricial distribution mixture model with "- ++ show (length cs)- ++ " components."+ LC.pack $+ "Empiricial distribution mixture model with "+ ++ show (length cs)+ ++ " components." -- XXX. Maybe provide human readable model file. But then, why is this -- necessary. A human readable summary is reported anyways, and for Protein@@ -140,81 +135,82 @@ simulateCmd = do l <- local <$> ask let treeFile = argsTreeFile l- $(logInfo) "" $(logInfo) $ T.pack $ "Read tree from file '" ++ treeFile ++ "'." tree <- liftIO $ parseFileWith (newick Standard) treeFile- $(logInfo) $ LT.toStrict $ LT.decodeUtf8 $ summarize tree-- let edmFile = argsEDMFile l+ let t' = either error id $ phyloToLengthTree tree+ $(logInfo) $ LT.toStrict $ LT.decodeUtf8 $ summarizeBranchLengths t'+ let edmFile = argsEDMFile l let sProfileFiles = argsSiteprofilesFiles l $(logInfo) "" $(logDebug) "Read EDM file or siteprofile files."- when (isJust edmFile && isJust sProfileFiles)- $ error "Got both: --edm-file and --siteprofile-files."+ when (isJust edmFile && isJust sProfileFiles) $+ error "Got both: --edm-file and --siteprofile-files." edmCs <- case edmFile of- Nothing -> return Nothing+ Nothing -> return Nothing Just edmF -> do $(logInfo) "Read EDM file." liftIO $ Just <$> parseFileWith phylobayes edmF- maybe (return ())- ($(logInfo) . LT.toStrict . LT.decodeUtf8 . summarizeEDMComponents)- edmCs+ maybe+ (return ())+ ($(logInfo) . LT.toStrict . LT.decodeUtf8 . summarizeEDMComponents)+ edmCs sProfiles <- case sProfileFiles of- Nothing -> return Nothing+ Nothing -> return Nothing Just fns -> do- $(logInfo)- $ T.pack- $ "Read siteprofiles from "- ++ show (length fns)- ++ " file(s)."+ $(logInfo) $+ T.pack $+ "Read siteprofiles from "+ ++ show (length fns)+ ++ " file(s)." $(logDebug) $ T.pack $ "The file names are:" ++ show fns xs <- liftIO $ mapM (parseFileWith siteprofiles) fns return $ Just $ concat xs- maybe (return ())- ($(logInfo) . LT.toStrict . LT.decodeUtf8 . summarizeEDMComponents)- sProfiles+ maybe+ (return ())+ ($(logInfo) . LT.toStrict . LT.decodeUtf8 . summarizeEDMComponents)+ sProfiles let edmCsOrSiteprofiles = edmCs <|> sProfiles- $(logInfo) "Read model string."- let ms = argsSubstitutionModelString l- mm = argsMixtureModelString l- mws = argsMixtureWeights l+ let ms = argsSubstitutionModelString l+ mm = argsMixtureModelString l+ mws = argsMixtureWeights l eitherPhyloModel' = getPhyloModel ms mm mws edmCsOrSiteprofiles phyloModel' <- case eitherPhyloModel' of- Left err -> lift $ error err- Right pm -> return pm-+ Left err -> lift $ error err+ Right pm -> return pm let maybeGammaParams = argsGammaParams l phyloModel <- case maybeGammaParams of Nothing -> do- $(logInfo) $ LT.toStrict $ LT.decodeUtf8 $ LC.unlines $ P.summarize- phyloModel'+ $(logInfo) $+ LT.toStrict $+ LT.decodeUtf8 $+ LC.unlines $+ P.summarize+ phyloModel' return phyloModel' Just (n, alpha) -> do- $(logInfo)- $ LT.toStrict- $ LT.decodeUtf8- $ LC.intercalate "\n"- $ P.summarize phyloModel'+ $(logInfo) $+ LT.toStrict $+ LT.decodeUtf8 $+ LC.intercalate "\n" $+ P.summarize phyloModel' $(logInfo) ""- $(logInfo)- $ LT.toStrict- $ LT.decodeUtf8- $ LC.intercalate "\n"- $ summarizeGammaRateHeterogeneity n alpha+ $(logInfo) $+ LT.toStrict $+ LT.decodeUtf8 $+ LC.intercalate "\n" $+ summarizeGammaRateHeterogeneity n alpha return $ expand n alpha phyloModel'- -- -- XXX: Do not report possibly huge empirical distribution mixture models -- -- for now, because it takes too long and uses too much disk space :). unless (isJust sProfiles)- (do- $(logInfo) ""- reportModel phyloModel- $(logInfo) ""+ ( do+ $(logInfo) ""+ reportModel phyloModel+ $(logInfo) "" )- $(logInfo) "Simulate alignment." let alignmentLength = argsLength l $(logInfo) $ T.pack $ "Length: " <> show alignmentLength <> "."@@ -222,7 +218,7 @@ Random -> error "simulateCmd: seed not available; please contact maintainer." Fixed s -> liftIO $ initialize s- alignment <- liftIO $ simulateAlignment phyloModel tree alignmentLength gen+ alignment <- liftIO $ simulateAlignment phyloModel t' alignmentLength gen let output = (sequencesToFasta . A.toSequences) alignment $(logInfo) "" out "simulated multi sequence alignment" output ".fasta"
src/SLynx/SubSample/Options.hs view
@@ -1,44 +1,40 @@ {-# LANGUAGE DeriveGeneric #-} -{- |-Module : SLynx.SubSample.Options-Description : ELynxSeq argument parsing-Copyright : (c) Dominik Schrempf 2018-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Sun Oct 7 17:29:45 2018.---}-+-- |+-- Module : SLynx.SubSample.Options+-- Description : ELynxSeq argument parsing+-- Copyright : (c) Dominik Schrempf 2018+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Sun Oct 7 17:29:45 2018. module SLynx.SubSample.Options- ( SubSampleArguments(..)- , subSampleArguments- , getOutSuffixes+ ( SubSampleArguments (..),+ subSampleArguments,+ getOutSuffixes, ) where -import Options.Applicative-import qualified Data.Text as T-import qualified Data.Text.Lazy as LT-import qualified Data.Text.Lazy.Builder as LT-import qualified Data.Text.Lazy.Builder.Int as LT--import SLynx.Tools--import ELynx.Data.Alphabet.Alphabet-import ELynx.Tools+import qualified Data.Text as T+import qualified Data.Text.Lazy as LT+import qualified Data.Text.Lazy.Builder as LT+import qualified Data.Text.Lazy.Builder.Int as LT+import ELynx.Data.Alphabet.Alphabet+import ELynx.Tools+import Options.Applicative+import SLynx.Tools -- | Data structure holding the Command line arguments. data SubSampleArguments = SubSampleArguments- { ssAlphabet :: Alphabet- , ssInFile :: FilePath- , ssNSites :: Int- , ssNAlignments :: Int- , ssMbSeed :: Seed }+ { ssAlphabet :: Alphabet,+ ssInFile :: FilePath,+ ssNSites :: Int,+ ssNAlignments :: Int,+ ssMbSeed :: Seed+ } deriving (Eq, Show, Generic) -- | Get a given number of output file suffixes.@@ -48,21 +44,21 @@ -- Will result in @.00.fasta@ up to @.10.fasta@. getOutSuffixes :: Int -> String -> [String] getOutSuffixes n suffix =- [ "." ++ digitStr i ++ "." ++ suffix | i <- [0 .. n - 1] ]- where- nDigits = ceiling $ logBase (10 :: Double) (fromIntegral n)- digitStr i = T.unpack- $ T.justifyRight nDigits '0' (LT.toStrict $ LT.toLazyText $ LT.decimal i)-+ ["." ++ digitStr i ++ "." ++ suffix | i <- [0 .. n - 1]]+ where+ nDigits = ceiling $ logBase (10 :: Double) (fromIntegral n)+ digitStr i =+ T.unpack $+ T.justifyRight nDigits '0' (LT.toStrict $ LT.toLazyText $ LT.decimal i) instance Reproducible SubSampleArguments where inFiles = pure . ssInFile outSuffixes a = getOutSuffixes (ssNAlignments a) "fasta" getSeed = Just . ssMbSeed- setSeed a s = a { ssMbSeed = Fixed s }- parser = subSampleArguments+ setSeed a s = a {ssMbSeed = Fixed s}+ parser = subSampleArguments cmdName = "sub-sample"- cmdDsc = ["Sub-sample columns from multi sequence alignments."]+ cmdDsc = ["Sub-sample columns from multi sequence alignments."] cmdFtr = [ "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." ]@@ -83,16 +79,18 @@ subSampleNSitesOpt :: Parser Int subSampleNSitesOpt =- option auto $ long "number-of-sites" <> short 'n' <> metavar "INT" <> help- "Number of sites randomly drawn with replacement"+ option auto $+ long "number-of-sites" <> short 'n' <> metavar "INT"+ <> help+ "Number of sites randomly drawn with replacement" subSampleNAlignmentsOpt :: Parser Int subSampleNAlignmentsOpt =- option auto- $ long "number-of-alignments"- <> short 'm'- <> metavar "INT"- <> help "Number of multi sequence alignments to be created"+ option auto $+ long "number-of-alignments"+ <> short 'm'+ <> metavar "INT"+ <> help "Number of multi sequence alignments to be created" filePathArg :: Parser FilePath filePathArg =
src/SLynx/SubSample/SubSample.hs view
@@ -1,38 +1,33 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}--{- |-Module : Analyze.Analyze-Description : Parse sequence file formats and analyze them-Copyright : (c) Dominik Schrempf 2018-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Fri Oct 5 08:41:05 2018.---}+{-# LANGUAGE TemplateHaskell #-} +-- |+-- Module : Analyze.Analyze+-- Description : Parse sequence file formats and analyze them+-- Copyright : (c) Dominik Schrempf 2018+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Fri Oct 5 08:41:05 2018. module SLynx.SubSample.SubSample- ( subSampleCmd+ ( subSampleCmd, ) where -import Control.Monad-import Control.Monad.IO.Class-import Control.Monad.Logger-import Control.Monad.Trans.Reader ( ask )-import qualified Data.Text as T-import System.Random.MWC--import SLynx.SubSample.Options-import SLynx.Tools-+import Control.Monad+import Control.Monad.IO.Class+import Control.Monad.Logger+import Control.Monad.Trans.Reader (ask)+import qualified Data.Text as T import qualified ELynx.Data.Sequence.Alignment as M-import ELynx.Export.Sequence.Fasta-import ELynx.Tools+import ELynx.Export.Sequence.Fasta+import ELynx.Tools+import SLynx.SubSample.Options+import SLynx.Tools+import System.Random.MWC -- | Sub sample sequences. subSampleCmd :: ELynx SubSampleArguments ()@@ -40,15 +35,15 @@ (SubSampleArguments al inFile nSites nAlignments (Fixed s)) <- local <$> ask $(logInfo) "Command: Sub sample from a multi sequence alignment." $(logInfo) $ T.pack $ " Sample " <> show nSites <> " sites."- $(logInfo)- $ T.pack- $ " Sample "- <> show nAlignments- <> " multi sequence alignments."- ss <- readSeqs al inFile+ $(logInfo) $+ T.pack $+ " Sample "+ <> show nAlignments+ <> " multi sequence alignments."+ ss <- readSeqs al inFile gen <- liftIO $ initialize s let a = either error id (M.fromSequences ss) samples <- liftIO $ replicateM nAlignments $ M.randomSubSample nSites a gen let results = map (sequencesToFasta . M.toSequences) samples- sfxs = getOutSuffixes nAlignments "fasta"+ sfxs = getOutSuffixes nAlignments "fasta" zipWithM_ (out "sub sampled multi sequence alignments") results sfxs
src/SLynx/Tools.hs view
@@ -1,38 +1,36 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}--{- |-Module : SLynx.Tools-Description : Common tools for sequence lynx-Copyright : (c) Dominik Schrempf 2020-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Sat Sep 7 06:24:22 2019.---}+{-# LANGUAGE TemplateHaskell #-} +-- |+-- Module : SLynx.Tools+-- Description : Common tools for sequence lynx+-- Copyright : (c) Dominik Schrempf 2020+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Sat Sep 7 06:24:22 2019. module SLynx.Tools ( -- * SLynx.Tools- readSeqs+ readSeqs,+ -- * Options- , alphabetOpt+ alphabetOpt, ) where -import Control.Monad.IO.Class-import Control.Monad.Logger-import qualified Data.Text as T-import Options.Applicative--import ELynx.Data.Alphabet.Alphabet-import ELynx.Data.Sequence.Sequence-import ELynx.Import.Sequence.Fasta- hiding ( Parser )-import ELynx.Tools+import Control.Monad.IO.Class+import Control.Monad.Logger+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.Tools+import Options.Applicative -- -- | Read sequences of given alphabet from file or standard input. -- readSeqs@@ -58,17 +56,19 @@ -- | Read sequences of given alphabet from file or standard input. readSeqs :: (MonadIO m, MonadLogger m) => Alphabet -> FilePath -> m [Sequence] readSeqs a fp = do- $(logInfo)- $ T.pack- $ "Read sequences from file "- <> fp- <> "; alphabet "- <> show a- <> "."+ $(logInfo) $+ T.pack $+ "Read sequences from file "+ <> fp+ <> "; alphabet "+ <> show a+ <> "." liftIO $ parseFileWith (fasta a) fp -- | Command line option to specify the alphabet. Used by various commands. alphabetOpt :: Parser Alphabet alphabetOpt =- option auto $ long "alphabet" <> short 'a' <> metavar "NAME" <> help- "Specify alphabet type NAME"+ option auto $+ long "alphabet" <> short 'a' <> metavar "NAME"+ <> help+ "Specify alphabet type NAME"
src/SLynx/Translate/Options.hs view
@@ -1,40 +1,36 @@ {-# LANGUAGE DeriveGeneric #-} -{- |-Module : SLynx.Translate.Options-Description : ELynxSeq argument parsing-Copyright : (c) Dominik Schrempf 2018-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Sun Oct 7 17:29:45 2018.---}-+-- |+-- Module : SLynx.Translate.Options+-- Description : ELynxSeq argument parsing+-- Copyright : (c) Dominik Schrempf 2018+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Sun Oct 7 17:29:45 2018. module SLynx.Translate.Options- ( TranslateArguments(..)- , translateArguments+ ( TranslateArguments (..),+ translateArguments, ) where -import Data.List-import Options.Applicative--import SLynx.Tools--import ELynx.Data.Alphabet.Alphabet-import ELynx.Data.Character.Codon-import ELynx.Tools+import Data.List+import ELynx.Data.Alphabet.Alphabet+import ELynx.Data.Character.Codon+import ELynx.Tools+import Options.Applicative+import SLynx.Tools -- | Arguments needed to translate sequences. data TranslateArguments = TranslateArguments- { trAlphabet :: Alphabet- , trInFile :: FilePath- , trReadingFrame :: Int- , trUniversalCode :: UniversalCode }+ { trAlphabet :: Alphabet,+ trInFile :: FilePath,+ trReadingFrame :: Int,+ trUniversalCode :: UniversalCode+ } deriving (Eq, Show, Generic) instance Reproducible TranslateArguments where@@ -42,9 +38,9 @@ outSuffixes _ = [".fasta"] getSeed _ = Nothing setSeed = const- parser = translateArguments+ parser = translateArguments cmdName = "translate"- cmdDsc = ["Translate from DNA to Protein or DNAX to ProteinX."]+ cmdDsc = ["Translate from DNA to Protein or DNAX to ProteinX."] instance FromJSON TranslateArguments @@ -61,17 +57,21 @@ readingFrameOpt :: Parser Int readingFrameOpt =- option auto $ long "reading-frame" <> short 'r' <> metavar "INT" <> help- "Reading frame [0|1|2]."+ option auto $+ long "reading-frame" <> short 'r' <> metavar "INT"+ <> help+ "Reading frame [0|1|2]." universalCodeOpt :: Parser UniversalCode universalCodeOpt =- option auto $ long "universal-code" <> short 'u' <> metavar "CODE" <> help- ("universal code; one of: " ++ codeStr ++ ".")- where- codes = allValues :: [UniversalCode]- codeWords = map show codes- codeStr = intercalate ", " codeWords+ option auto $+ long "universal-code" <> short 'u' <> metavar "CODE"+ <> help+ ("universal code; one of: " ++ codeStr ++ ".")+ where+ codes = allValues :: [UniversalCode]+ codeWords = map show codes+ codeStr = intercalate ", " codeWords inFileArg :: Parser FilePath inFileArg =
src/SLynx/Translate/Translate.hs view
@@ -1,37 +1,32 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}--{- |-Module : Analyze.Analyze-Description : Parse sequence file formats and analyze them-Copyright : (c) Dominik Schrempf 2018-License : GPL-3.0-or-later--Maintainer : dominik.schrempf@gmail.com-Stability : unstable-Portability : portable--Creation date: Fri Oct 5 08:41:05 2018.---}+{-# LANGUAGE TemplateHaskell #-} +-- |+-- Module : Analyze.Analyze+-- Description : Parse sequence file formats and analyze them+-- Copyright : (c) Dominik Schrempf 2018+-- License : GPL-3.0-or-later+--+-- Maintainer : dominik.schrempf@gmail.com+-- Stability : unstable+-- Portability : portable+--+-- Creation date: Fri Oct 5 08:41:05 2018. module SLynx.Translate.Translate- ( translateCmd+ ( translateCmd, ) where -import Control.Monad.Logger-import Control.Monad.Trans.Reader ( ask )-import qualified Data.Text as T--import SLynx.Tools-import SLynx.Translate.Options--import ELynx.Data.Character.Codon-import ELynx.Data.Sequence.Sequence-import ELynx.Data.Sequence.Translate-import ELynx.Export.Sequence.Fasta-import ELynx.Tools+import Control.Monad.Logger+import Control.Monad.Trans.Reader (ask)+import qualified Data.Text as T+import ELynx.Data.Character.Codon+import ELynx.Data.Sequence.Sequence+import ELynx.Data.Sequence.Translate+import ELynx.Export.Sequence.Fasta+import ELynx.Tools+import SLynx.Tools+import SLynx.Translate.Options translateSeqs :: Int -> UniversalCode -> [Sequence] -> [Sequence] translateSeqs rf uc = map (translateSeq uc rf)