elynx-tools 0.3.0 → 0.3.1
raw patch · 17 files changed
+93/−470 lines, 17 filesdep +attoparsecdep −asyncdep −containersdep −matrices
Dependencies added: attoparsec
Dependencies removed: async, containers, matrices, megaparsec, parallel
Files
- ChangeLog.md +8/−1
- README.md +27/−27
- elynx-tools.cabal +3/−10
- src/ELynx/Tools.hs +0/−6
- src/ELynx/Tools/ByteString.hs +9/−27
- src/ELynx/Tools/Concurrent.hs +0/−21
- src/ELynx/Tools/Definitions.hs +0/−27
- src/ELynx/Tools/InputOutput.hs +24/−59
- src/ELynx/Tools/LinearAlgebra.hs +1/−0
- src/ELynx/Tools/Logger.hs +4/−46
- src/ELynx/Tools/Matrix.hs +0/−101
- src/ELynx/Tools/Misc.hs +1/−10
- src/ELynx/Tools/Numeric.hs +0/−10
- src/ELynx/Tools/Parallel.hs +0/−21
- src/ELynx/Tools/Reproduction.hs +14/−42
- src/ELynx/Tools/Text.hs +2/−2
- src/ELynx/Tools/Vector.hs +0/−60
ChangeLog.md view
@@ -2,7 +2,14 @@ # Changelog for ELynx -## Version 0.3.1; in development+## Version 0.3.2; in development+++## Version 0.3.1++- Use Attoparsec.+- Use ByteString consistently.+- Remove elynx-tools dependency from libaries. ## Version 0.3.0
README.md view
@@ -2,7 +2,7 @@ # The ELynx Suite -Version: 0.3.0.+Version: 0.3.1. Reproducible evolution made easy. <p align="center"><img src="https://travis-ci.org/dschrempf/elynx.svg?branch=master"/></p>@@ -90,9 +90,9 @@ slynx --help | head -n -16 - ELynx Suite version 0.3.0.+ ELynx Suite version 0.3.1. Developed by Dominik Schrempf.- Compiled on July 30, 2020, at 12:40 pm, UTC.+ Compiled on August 3, 2020, at 12:12 pm, UTC. Usage: slynx [-v|--verbosity VALUE] [-o|--output-file-basename NAME] [-f|--force] COMMAND@@ -136,9 +136,9 @@ slynx concatenate --help - ELynx Suite version 0.3.0.+ ELynx Suite version 0.3.1. Developed by Dominik Schrempf.- Compiled on July 30, 2020, at 12:40 pm, UTC.+ Compiled on August 3, 2020, at 12:12 pm, UTC. Usage: slynx concatenate (-a|--alphabet NAME) INPUT-FILE Concatenate sequences found in input files.@@ -157,9 +157,9 @@ slynx examine --help - ELynx Suite version 0.3.0.+ ELynx Suite version 0.3.1. Developed by Dominik Schrempf.- Compiled on July 30, 2020, at 12:40 pm, UTC.+ Compiled on August 3, 2020, at 12:12 pm, UTC. Usage: slynx examine (-a|--alphabet NAME) INPUT-FILE [--per-site] Examine sequences. If data is a multi sequence alignment, additionally analyze columns.@@ -179,9 +179,9 @@ slynx filter-rows --help - ELynx Suite version 0.3.0.+ ELynx Suite version 0.3.1. Developed by Dominik Schrempf.- Compiled on July 30, 2020, at 12:40 pm, UTC.+ Compiled on August 3, 2020, at 12:12 pm, UTC. Usage: slynx filter-rows (-a|--alphabet NAME) INPUT-FILE [--longer-than LENGTH] [--shorter-than LENGTH] [--standard-characters]@@ -202,9 +202,9 @@ slynx filter-columns --help - ELynx Suite version 0.3.0.+ ELynx Suite version 0.3.1. Developed by Dominik Schrempf.- Compiled on July 30, 2020, at 12:40 pm, UTC.+ Compiled on August 3, 2020, at 12:12 pm, UTC. Usage: slynx filter-columns (-a|--alphabet NAME) INPUT-FILE [--standard-chars DOUBLE]@@ -226,9 +226,9 @@ slynx simulate --help - ELynx Suite version 0.3.0.+ ELynx Suite version 0.3.1. Developed by Dominik Schrempf.- Compiled on July 30, 2020, at 12:40 pm, UTC.+ Compiled on August 3, 2020, at 12:12 pm, UTC. Usage: slynx simulate (-t|--tree-file Name) [-s|--substitution-model MODEL] [-m|--mixture-model MODEL] [-e|--edm-file NAME] @@ -305,9 +305,9 @@ slynx sub-sample --help - ELynx Suite version 0.3.0.+ ELynx Suite version 0.3.1. Developed by Dominik Schrempf.- Compiled on July 30, 2020, at 12:40 pm, UTC.+ Compiled on August 3, 2020, at 12:12 pm, UTC. Usage: slynx sub-sample (-a|--alphabet NAME) INPUT-FILE (-n|--number-of-sites INT)@@ -335,9 +335,9 @@ slynx translate --help - ELynx Suite version 0.3.0.+ ELynx Suite version 0.3.1. Developed by Dominik Schrempf.- Compiled on July 30, 2020, at 12:40 pm, UTC.+ Compiled on August 3, 2020, at 12:12 pm, UTC. Usage: slynx translate (-a|--alphabet NAME) INPUT-FILE (-r|--reading-frame INT) (-u|--universal-code CODE)@@ -360,9 +360,9 @@ tlynx --help | head -n -16 - ELynx Suite version 0.3.0.+ ELynx Suite version 0.3.1. Developed by Dominik Schrempf.- Compiled on July 30, 2020, at 12:40 pm, UTC.+ Compiled on August 3, 2020, at 12:12 pm, UTC. Usage: tlynx [-v|--verbosity VALUE] [-o|--output-file-basename NAME] [-f|--force] COMMAND@@ -399,9 +399,9 @@ tlynx compare --help - ELynx Suite version 0.3.0.+ ELynx Suite version 0.3.1. Developed by Dominik Schrempf.- Compiled on July 30, 2020, at 12:40 pm, UTC.+ Compiled on August 3, 2020, at 12:12 pm, UTC. Usage: tlynx compare [-n|--normalize] [-b|--bipartitions] [-t|--intersect] [-f|--newick-format FORMAT] NAMES@@ -428,9 +428,9 @@ tlynx examine --help - ELynx Suite version 0.3.0.+ ELynx Suite version 0.3.1. Developed by Dominik Schrempf.- Compiled on July 30, 2020, at 12:40 pm, UTC.+ Compiled on August 3, 2020, at 12:12 pm, UTC. Usage: tlynx examine INPUT-FILE [-f|--newick-format FORMAT] Compute summary statistics of phylogenetic trees.@@ -452,9 +452,9 @@ tlynx simulate --help - ELynx Suite version 0.3.0.+ ELynx Suite version 0.3.1. Developed by Dominik Schrempf.- Compiled on July 30, 2020, at 12:40 pm, UTC.+ Compiled on August 3, 2020, at 12:12 pm, UTC. Usage: tlynx simulate [-t|--nTrees INT] [-n|--nLeaves INT] [-H|--height DOUBLE] [-M|--condition-on-mrca] [-l|--lambda DOUBLE] @@ -491,9 +491,9 @@ elynx --help | head -n -16 - ELynx Suite version 0.3.0.+ ELynx Suite version 0.3.1. Developed by Dominik Schrempf.- Compiled on July 30, 2020, at 12:40 pm, UTC.+ Compiled on August 3, 2020, at 12:12 pm, UTC. Usage: elynx COMMAND Validate and redo past ELynx analyses
elynx-tools.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: ce20a53fa80c7478a01a9fc6ab5b4549475e79e193a58b3e925239f9513502af+-- hash: a88ba56b54f3dbb5277c662a4a76fedadc3f78e23d8ae3f2132c17f8aee2969e name: elynx-tools-version: 0.3.0+version: 0.3.1 synopsis: Tools for ELynx description: Please see the README on GitHub at <https://github.com/dschrempf/elynx>. category: Bioinformatics@@ -39,13 +39,10 @@ ELynx.Tools.LinearAlgebra ELynx.Tools.List ELynx.Tools.Logger- ELynx.Tools.Matrix ELynx.Tools.Misc ELynx.Tools.Numeric- ELynx.Tools.Parallel ELynx.Tools.Reproduction ELynx.Tools.Text- ELynx.Tools.Vector Paths_elynx_tools autogen-modules: Paths_elynx_tools@@ -54,23 +51,19 @@ ghc-options: -Wall -fllvm build-depends: aeson- , async+ , attoparsec , base >=4.7 && <5 , base16-bytestring , bytestring- , containers , cryptohash-sha256 , deepseq , directory , fast-logger , hmatrix- , matrices- , megaparsec , monad-control , monad-logger , mwc-random , optparse-applicative- , parallel , primitive , template-haskell , text
src/ELynx/Tools.hs view
@@ -20,13 +20,10 @@ module ELynx.Tools.LinearAlgebra, module ELynx.Tools.List, module ELynx.Tools.Logger,- module ELynx.Tools.Matrix, module ELynx.Tools.Misc, module ELynx.Tools.Numeric,- module ELynx.Tools.Parallel, module ELynx.Tools.Reproduction, module ELynx.Tools.Text,- module ELynx.Tools.Vector, ) where @@ -38,10 +35,7 @@ import ELynx.Tools.LinearAlgebra import ELynx.Tools.List import ELynx.Tools.Logger-import ELynx.Tools.Matrix import ELynx.Tools.Misc import ELynx.Tools.Numeric-import ELynx.Tools.Parallel import ELynx.Tools.Reproduction import ELynx.Tools.Text-import ELynx.Tools.Vector
src/ELynx/Tools/ByteString.hs view
@@ -16,51 +16,33 @@ alignRight, alignLeftWith, alignLeft,- summarizeByteString,- c2w,- w2c,- bShow, ) where -import Data.ByteString.Internal- ( c2w,- w2c,- )-import qualified Data.ByteString.Lazy.Char8 as L+import qualified Data.ByteString.Lazy.Char8 as BL -- | For a given width, align string to the right; use given fill character; -- trim on the left if string is longer.-alignRightWith :: Char -> Int -> L.ByteString -> L.ByteString+alignRightWith :: Char -> Int -> BL.ByteString -> BL.ByteString alignRightWith c n s =- L.replicate (fromIntegral n - l) c <> L.take (fromIntegral n) s+ BL.replicate (fromIntegral n - l) c <> BL.take (fromIntegral n) s where- l = L.length s+ l = BL.length s -- | For a given width, align string to the right; trim on the left if string is -- longer.-alignRight :: Int -> L.ByteString -> L.ByteString+alignRight :: Int -> BL.ByteString -> BL.ByteString alignRight = alignRightWith ' ' -- | For a given width, align string to the left; use given fill character; trim -- on the right if string is longer.-alignLeftWith :: Char -> Int -> L.ByteString -> L.ByteString+alignLeftWith :: Char -> Int -> BL.ByteString -> BL.ByteString alignLeftWith c n s =- L.take (fromIntegral n) s <> L.replicate (fromIntegral n - l) c+ BL.take (fromIntegral n) s <> BL.replicate (fromIntegral n - l) c where- l = L.length s+ l = BL.length s -- | For a given width, align string to the left; trim on the right if string is -- longer.-alignLeft :: Int -> L.ByteString -> L.ByteString+alignLeft :: Int -> BL.ByteString -> BL.ByteString alignLeft = alignLeftWith ' '---- | If a string is longer than a given value, trim it and add some dots.-summarizeByteString :: Int -> L.ByteString -> L.ByteString-summarizeByteString l s- | L.length s >= fromIntegral l = L.take (fromIntegral l) s <> L.pack "..."- | otherwise = s---- | Conversion to 'L.ByteString'.-bShow :: Show a => a -> L.ByteString-bShow = L.pack . show
src/ELynx/Tools/Concurrent.hs view
@@ -16,13 +16,10 @@ splitGen, -- * Concurrent calculations- parComp, getChunks, ) where -import Control.Concurrent-import Control.Concurrent.Async import Control.Monad import Control.Monad.Primitive import qualified Data.Vector as V@@ -36,24 +33,6 @@ | otherwise = do seeds :: [V.Vector Word32] <- replicateM (n -1) $ uniformVector gen 256 fmap (gen :) (mapM initialize seeds)---- -- XXX: This just doesn't work... The only thing I found:--- -- https://stackoverflow.com/a/16250010.--- parComp :: (PrimMonad m, Monoid b) => Int -> (Int -> Gen (PrimState m) -> m b)--- -> Gen (PrimState m) -> m b--- parComp num fun gen = do--- let ncap = ceiling (fromIntegral num / fromIntegral chunksize :: Double)--- chunks = getChunks ncap num--- gs <- splitGen ncap gen--- mconcat <$> P.mapM (\(n', g') -> fun n' g') (zip chunks gs)---- | Perform random calculation in parallel. Does only work with 'IO' and the moment.-parComp :: Int -> (Int -> GenIO -> IO b) -> GenIO -> IO [b]-parComp num fun gen = do- ncap <- getNumCapabilities- let chunks = getChunks ncap num- gs <- splitGen ncap gen- mapConcurrently (uncurry fun) (zip chunks gs) -- | For a given number of capabilities and number of calculations, get chunk -- sizes. The chunk sizes will be as evenly distributed as possible and sum up
src/ELynx/Tools/Definitions.hs view
@@ -11,42 +11,15 @@ -- Creation date: Fri Jan 25 17:17:41 2019. module ELynx.Tools.Definitions ( -- * Definitions- chunksize, eps,- eps', precision,- version, ) where -import Data.Version---- TODO: Move back to automatic version handling.---- XXX: Manually handled, because automatic handling with @Paths_...@ modules--- results in errors during source tarball creation and upload.---- Careful, this version number has to be synchronized with the one specified in--- the *.cabal files. This is done with the @bump-version@ script.---- | ELynx version.-version :: Version-version = makeVersion [0, 3, 0]- -- | Required precision when comparing 'Double' values. eps :: Double eps = 1e-12 --- | Relaxed required precision when comparing 'Double' values. Often, input--- files do not provide the required double precision. In this case, it is only--- possible to check input with relaxed bounds.-eps' :: Double-eps' = 1e-5- -- | Default output precision. precision :: Int precision = 3---- | Default chunk size for parallel evaluations.-chunksize :: Int-chunksize = 500
src/ELynx/Tools/InputOutput.hs view
@@ -45,9 +45,9 @@ import Control.Monad.IO.Class import Control.Monad.Logger import Control.Monad.Trans.Reader (ask)-import qualified Data.ByteString.Lazy.Char8 as L+import Data.Attoparsec.ByteString.Lazy+import qualified Data.ByteString.Lazy.Char8 as BL import Data.List (isSuffixOf)-import Data.Maybe import qualified Data.Text as T import ELynx.Tools.Reproduction ( Arguments (..),@@ -59,7 +59,6 @@ ) import System.Directory (doesFileExist) import System.IO-import Text.Megaparsec -- | Get out file path with extension. getOutFilePath ::@@ -91,94 +90,60 @@ -- XXX: For now, all files are read strictly (see help of -- Control.DeepSeq.force).-readFile' :: FilePath -> IO L.ByteString-readFile' fn = withFile fn ReadMode $ (evaluate . force) <=< L.hGetContents+readFile' :: FilePath -> IO BL.ByteString+readFile' fn = withFile fn ReadMode $ (evaluate . force) <=< BL.hGetContents -- | Read file. If file path ends with ".gz", assume gzipped file and decompress -- before read.-readGZFile :: FilePath -> IO L.ByteString+readGZFile :: FilePath -> IO BL.ByteString readGZFile f | ".gz" `isSuffixOf` f = decompress <$> readFile' f | otherwise = readFile' f -- | Write file. If file path ends with ".gz", assume gzipped file and compress -- before write.-writeGZFile :: Force -> FilePath -> L.ByteString -> IO ()+writeGZFile :: Force -> FilePath -> BL.ByteString -> IO () writeGZFile frc f r- | ".gz" `isSuffixOf` f = checkFile frc f >> L.writeFile f (compress r)- | otherwise = checkFile frc f >> L.writeFile f r+ | ".gz" `isSuffixOf` f = checkFile frc f >> BL.writeFile f (compress r)+ | otherwise = checkFile frc f >> BL.writeFile f r -- | Parse a possibly gzipped file.-runParserOnFile ::- Parsec e L.ByteString a ->- FilePath ->- IO (Either (ParseErrorBundle L.ByteString e) a)-runParserOnFile p f = parse p f <$> readGZFile f+runParserOnFile :: Parser a -> FilePath -> IO (Either String a)+runParserOnFile p f = eitherResult . parse p <$> readGZFile f -- | Parse a possibly gzipped file and extract the result.-parseFileWith ::- (ShowErrorComponent e) =>- -- | The parser.- Parsec e L.ByteString a ->- FilePath ->- IO a+parseFileWith :: Parser a -> FilePath -> IO a parseFileWith p f = parseFileOrIOWith p (Just f) -- | Parse standard input.-parseIOWith ::- (ShowErrorComponent e) =>- -- | The parser.- Parsec e L.ByteString a ->- IO a-parseIOWith p = parseByteStringWith "Standard input" p <$> L.getContents+parseIOWith :: Parser a -> IO a+parseIOWith p = parseFileOrIOWith p Nothing -- | Parse a possibly gzipped file, or standard input, and extract the result.-parseFileOrIOWith ::- (ShowErrorComponent e) =>- -- | The parser.- Parsec e L.ByteString a ->- -- | If no file path is given, standard input is used.- Maybe FilePath ->- IO a+parseFileOrIOWith :: Parser a -> Maybe FilePath -> IO a parseFileOrIOWith p mf = do- contents <- maybe L.getContents readGZFile mf- return $ parseByteStringWith (fromMaybe "Standard input" mf) p contents+ s <- maybe BL.getContents readGZFile mf+ return $ parseByteStringWith p s -- | Parse a 'String' and extract the result.-parseStringWith ::- (ShowErrorComponent e) =>- -- | Name of string.- String ->- -- | Parser.- Parsec e L.ByteString a ->- -- | Input.- String ->- a-parseStringWith s p l = parseByteStringWith s p (L.pack l)+parseStringWith :: Parser a -> String -> a+parseStringWith p x = parseByteStringWith p (BL.pack x) --- | Parse a 'L.ByteString' and extract the result.-parseByteStringWith ::- (ShowErrorComponent e) =>- -- | Name of byte string.- String ->- -- | Parser.- Parsec e L.ByteString a ->- -- | Input.- L.ByteString ->- a-parseByteStringWith s p l = case parse p s l of- Left err -> error $ errorBundlePretty err+-- | Parse a 'BL.ByteString' and extract the result.+parseByteStringWith :: Parser a -> BL.ByteString -> a+parseByteStringWith p x = case eitherResult $ parse p x of+ Left err -> error err Right val -> val -- | Write a result with a given name to file with given extension or standard -- output. Supports compression.-out :: Reproducible a => String -> L.ByteString -> String -> ELynx a ()+out :: Reproducible a => String -> BL.ByteString -> String -> ELynx a () out name res ext = do mfp <- getOutFilePath ext case mfp of Nothing -> do $(logInfo) $ T.pack $ "Write " <> name <> " to standard output."- liftIO $ L.putStr res+ liftIO $ BL.putStr res Just fp -> do $(logInfo) $ T.pack $ "Write " <> name <> " to file '" <> fp <> "'." frc <- forceReanalysis . global <$> ask
src/ELynx/Tools/LinearAlgebra.hs view
@@ -34,6 +34,7 @@ -- | Set the diagonal entries of a matrix to zero. matrixSetDiagToZero :: Matrix R -> Matrix R matrixSetDiagToZero m = m - diag (takeDiag m)+{-# INLINE matrixSetDiagToZero #-} -- | Display a vector with given precision. dispv :: Int -> Vector R -> String
src/ELynx/Tools/Logger.hs view
@@ -24,57 +24,15 @@ import Control.Monad.Base (liftBase) import Control.Monad.IO.Class- ( MonadIO,- liftIO,- ) import Control.Monad.Logger- ( Loc,- LogLevel,- LogSource,- LoggingT,- MonadLogger,- filterLogger,- logInfo,- runLoggingT,- ) import Control.Monad.Trans.Control (MonadBaseControl) import Control.Monad.Trans.Reader (ReaderT (runReaderT))-import qualified Data.ByteString.Char8 as B+import qualified Data.ByteString.Char8 as BS import Data.Text- ( Text,- pack,- ) import ELynx.Tools.InputOutput (openFile') import ELynx.Tools.Reproduction- ( Arguments (..),- ELynx,- Force,- GlobalArguments (..),- Reproducible (..),- Seed (..),- ToJSON,- logFooter,- logHeader,- toLogLevel,- writeReproduction,- ) import System.IO- ( BufferMode (LineBuffering),- Handle,- IOMode (WriteMode),- hClose,- hSetBuffering,- stderr,- )-import System.Log.FastLogger- ( LogStr,- fromLogStr,- ) import System.Random.MWC- ( createSystemRandom,- fromSeed,- save,- ) -- | Unified way of creating a new section in the log. logNewSection :: MonadLogger m => Text -> m ()@@ -155,11 +113,11 @@ runELynxStderrLoggingT = (`runLoggingT` output stderr) output :: Handle -> Loc -> LogSource -> LogLevel -> LogStr -> IO ()-output h _ _ _ msg = B.hPutStrLn h ls where ls = fromLogStr msg+output h _ _ _ msg = BS.hPutStrLn h ls where ls = fromLogStr msg output2H :: Handle -> Handle -> Loc -> LogSource -> LogLevel -> LogStr -> IO () output2H h1 h2 _ _ _ msg = do- B.hPutStrLn h1 ls- B.hPutStrLn h2 ls+ BS.hPutStrLn h1 ls+ BS.hPutStrLn h2 ls where ls = fromLogStr msg
− src/ELynx/Tools/Matrix.hs
@@ -1,101 +0,0 @@--- |--- Module : ELynx.Tools.Matrix--- Copyright : (c) Dominik Schrempf 2020--- License : GPL-3.0-or-later------ Maintainer : dominik.schrempf@gmail.com--- Stability : unstable--- Portability : portable------ Creation date: Thu Feb 14 13:33:13 2019.------ Tools for matrices from 'Numeric.LinearAlgebra'.-module ELynx.Tools.Matrix- ( -- * Matrices- fMapRowSeq,- fMapRowPar,- fMapRowParChunk,- fMapColSeq,- fMapColPar,- fMapColParChunk,- (|||),- (===),- subSampleMatrix,- )-where--import Control.Parallel.Strategies-import Data.List-import qualified Data.Matrix.Generic as M-import qualified Data.Vector.Generic as V---- | Map a function on each row of a DIM2 array; sequential version.-fMapRowSeq ::- (V.Vector v a, V.Vector v b) =>- (v a -> v b) ->- M.Matrix v a ->- M.Matrix v b-fMapRowSeq f m = M.fromRows $ map f (M.toRows m)---- | Map a function on each row of a DIM2 array; parallel version.-fMapRowPar ::- (V.Vector v a, V.Vector v b) =>- (v a -> v b) ->- M.Matrix v a ->- M.Matrix v b-fMapRowPar f m = M.fromRows $ parMap rseq f (M.toRows m)---- | Map a function on each row of a DIM2 array; parallel version with given chunk size.-fMapRowParChunk ::- (V.Vector v a, V.Vector v b) =>- Int ->- (v a -> v b) ->- M.Matrix v a ->- M.Matrix v b-fMapRowParChunk n f m =- M.fromRows (map f (M.toRows m) `using` parListChunk n rseq)---- | Map a function on each row of a DIM2 array; sequential version.-fMapColSeq ::- (V.Vector v a, V.Vector v b) =>- (v a -> v b) ->- M.Matrix v a ->- M.Matrix v b-fMapColSeq f m = M.fromColumns $ map f (M.toColumns m)---- | Map a function on each row of a DIM2 array; parallel version.-fMapColPar ::- (V.Vector v a, V.Vector v b) =>- (v a -> v b) ->- M.Matrix v a ->- M.Matrix v b-fMapColPar f m = M.fromColumns $ parMap rseq f (M.toColumns m)---- | Map a function on each row of a DIM2 array; parallel version with given chunk size.-fMapColParChunk ::- (V.Vector v a, V.Vector v b) =>- Int ->- (v a -> v b) ->- M.Matrix v a ->- M.Matrix v b-fMapColParChunk n f m =- M.fromColumns (map f (M.toColumns m) `using` parListChunk n rseq)---- | Horizontal concatenation.-(|||) :: (V.Vector v a) => M.Matrix v a -> M.Matrix v a -> M.Matrix v a-(|||) l r = M.fromColumns $ lCs ++ rCs- where- lCs = M.toColumns l- rCs = M.toColumns r---- | Vertical concatenation.-(===) :: (V.Vector v a) => M.Matrix v a -> M.Matrix v a -> M.Matrix v a-(===) l r = M.fromRows $ lRs ++ rRs- where- lRs = M.toRows l- rRs = M.toRows r---- | Sample the given sites from a matrix.-subSampleMatrix :: (V.Vector v a) => [Int] -> M.Matrix v a -> M.Matrix v a-subSampleMatrix is m =- M.fromColumns $ foldl' (\a i -> M.takeColumn m i : a) [] is
src/ELynx/Tools/Misc.hs view
@@ -11,10 +11,7 @@ -- -- Miscellaneous tools that do not have their own category (yet). module ELynx.Tools.Misc- ( -- * Not yet classified stuff- ensure,-- -- * Weird stuff+ ( -- * Weird stuff compose, allValues, horizontalConcat,@@ -38,9 +35,3 @@ horizontalConcat :: [[[a]]] -> [[a]] horizontalConcat [xs] = xs horizontalConcat xss = foldl' (zipWith (++)) (head xss) (tail xss)---- | Ensure that a value satisfies a given predicate.-ensure :: (a -> Bool) -> a -> Maybe a-ensure p v- | p v = Just v- | otherwise = Nothing
src/ELynx/Tools/Numeric.hs view
@@ -13,24 +13,14 @@ module ELynx.Tools.Numeric ( -- * Numeric harmonic,- xLogX, roundN, ) where -import ELynx.Tools.Equality- -- | Calculate the nth harmonic number. harmonic :: Int -> Double harmonic 1 = 1.0 harmonic n = 1.0 / fromIntegral n + harmonic (n - 1)---- | Calculate x*log(x) but set to 0.0 when x is smaller than 'eps'.-xLogX :: Double -> Double-xLogX x- | x < 0.0 = error "Argument lower than zero."- | x `nearlyEq` 0.0 = 0.0- | otherwise = x * log x -- | Round double to a given precision. roundN :: Int -> Double -> Double
− src/ELynx/Tools/Parallel.hs
@@ -1,21 +0,0 @@--- |--- Module : ELynx.Tools.Parallel--- Description : Utility functions for parallel calculations--- Copyright : (c) Dominik Schrempf 2020--- License : GPL-3.0-or-later------ Maintainer : dominik.schrempf@gmail.com--- Stability : unstable--- Portability : portable------ Creation date: Tue Apr 21 15:19:44 2020.-module ELynx.Tools.Parallel- ( parMapChunk,- )-where--import Control.Parallel.Strategies---- | Parallel map with given chunk size.-parMapChunk :: Int -> (a -> b) -> [a] -> [b]-parMapChunk n f as = map f as `using` parListChunk n rseq
src/ELynx/Tools/Reproduction.hs view
@@ -47,7 +47,6 @@ createCommandReproducible, createCommand, elynxParserInfo,- megaReadM, -- * Re-exports Generic,@@ -56,44 +55,25 @@ ) where -import Control.Monad (void)+import Control.Monad import Control.Monad.Logger- ( LogLevel (..),- LoggingT,- )-import Control.Monad.Trans.Reader (ReaderT)-import Crypto.Hash.SHA256 (hash)-import Data.Aeson- ( FromJSON,- ToJSON,- encodeFile,- )-import Data.ByteString.Base16 (encode)-import qualified Data.ByteString.Char8 as B+import Control.Monad.Trans.Reader hiding (local)+import Crypto.Hash.SHA256+import Data.Aeson hiding (encode)+import Data.ByteString.Base16+import qualified Data.ByteString.Char8 as BS import Data.List hiding (group) import Data.Time import Data.Vector.Unboxed (Vector) import Data.Version- ( Version,- showVersion,- )-import Data.Void import Data.Word-import ELynx.Tools.Definitions (version)-import ELynx.Tools.Misc (allValues)-import GHC.Generics (Generic)+import ELynx.Tools.Misc+import GHC.Generics import Language.Haskell.TH import Options.Applicative hiding (empty) import Options.Applicative.Help.Pretty import System.Environment- ( getArgs,- getProgName,- )-import Text.Megaparsec- ( Parsec,- errorBundlePretty,- runParser,- )+import Paths_elynx_tools -- Be careful; it is necessary to synchronize the version numbers across packages. versionString :: String@@ -340,10 +320,10 @@ -- | A unique hash of the reproduction data type. getReproductionHash :: forall a. Reproducible a => Reproduction a -> String getReproductionHash r =- B.unpack $+ BS.unpack $ encode $ hash $- B.pack $+ BS.pack $ unlines $ -- Reproduction. progName r :@@ -387,8 +367,8 @@ instance ToJSON a => ToJSON (Reproduction a) -- | Helper function.-hashFile :: FilePath -> IO B.ByteString-hashFile f = encode . hash <$> B.readFile f+hashFile :: FilePath -> IO BS.ByteString+hashFile f = encode . hash <$> BS.readFile f -- | Write an ELynx reproduction file. writeReproduction ::@@ -403,7 +383,7 @@ let outFs = map (bn ++) (outSuffixes r) let fs = inFiles r ++ outFs cs <- mapM hashFile fs- let cs' = map B.unpack cs+ let cs' = map BS.unpack cs s = Reproduction pn as version Nothing fs cs' r void $ encodeFile (bn <> ".elynx") (setHash s) @@ -451,14 +431,6 @@ (fullDesc <> headerDoc (Just hdr') <> progDescDoc dsc <> footerDoc ftr) where hdr' = vsep $ map pretty hdr---- | See 'eitherReader', but for Megaparsec.-megaReadM :: Parsec Void String a -> ReadM a-megaReadM p = eitherReader $ \input ->- let eea = runParser p "" input- in case eea of- Left eb -> Left $ errorBundlePretty eb- Right a -> Right a -- | Fill a string so that it becomes a paragraph with line breaks. Useful for -- descriptions, headers and footers.
src/ELynx/Tools/Text.hs view
@@ -17,7 +17,7 @@ ) where -import Data.ByteString.Lazy (ByteString)+import qualified Data.ByteString.Lazy.Char8 as BL import Data.Text ( Text, pack,@@ -30,5 +30,5 @@ tShow = pack . show -- | Conversion to 'Text' from bytestring.-fromBs :: ByteString -> Text+fromBs :: BL.ByteString -> Text fromBs = toStrict . decodeUtf8
− src/ELynx/Tools/Vector.hs
@@ -1,60 +0,0 @@--- |--- Module : ELynx.Tools.Vector--- Copyright : (c) Dominik Schrempf 2020--- License : GPL-3.0-or-later------ Maintainer : dominik.schrempf@gmail.com--- Stability : unstable--- Portability : portable------ Creation date: Thu Feb 14 13:33:13 2019.------ Tools for vectors from 'Data.Vector.Generic'.-module ELynx.Tools.Vector- ( -- * Vectors- sumVec,- normalizeSumVec,- uniformVec,- meanVec,- chopVec,- randomInsertVec,- )-where--import Control.Monad.Primitive-import qualified Data.Vector.Generic as V-import System.Random.MWC---- | Sum of elements.-sumVec :: (Num a, V.Vector v a) => v a -> a-sumVec = V.foldl' (+) 0---- | Normalize a vector such that elements sum to a given value.-normalizeSumVec :: (Fractional a, V.Vector v a) => a -> v a -> v a-normalizeSumVec c v = V.map (* c') v- where- s = sumVec v- c' = c / s---- | A uniform vector of given length.-uniformVec :: (Fractional a, V.Vector v a) => Int -> v a-uniformVec n = V.replicate n (1 / fromIntegral n)---- | Mean of a vector.-meanVec :: (Fractional a, V.Vector v a) => v a -> a-meanVec v = sumVec v / fromIntegral (V.length v)---- | Chop list into chunks of given length. If the last chop is shorter than--- length, it is dropped.-chopVec :: V.Vector v a => Int -> v a -> [v a]-chopVec n xs- | V.length xs < n = []- | otherwise = V.take n xs : chopVec n (V.drop n xs)---- | Insert element into random position of vector.-randomInsertVec ::- (PrimMonad m, V.Vector v a) => a -> v a -> Gen (PrimState m) -> m (v a)-randomInsertVec e v g = do- let l = V.length v- i <- uniformR (0, l) g- return $ V.take i v V.++ V.singleton e V.++ V.drop i v