RNAlien 1.0.0 → 1.1.0
raw patch · 7 files changed
+720/−380 lines, 7 filesdep +aesondep +http-conduitdep +hxtdep ~EntrezHTTPdep ~ViennaRNAParserPVP ok
version bump matches the API change (PVP)
Dependencies added: aeson, http-conduit, hxt, network, pureMD5, text, transformers
Dependency ranges changed: EntrezHTTP, ViennaRNAParser
API changes (from Hackage documentation)
- Bio.RNAlienData: [sequenceOrigin] :: SequenceRecord -> Char
+ Bio.InfernalParser: parseCMSearch :: String -> Either ParseError CMsearch
+ Bio.InfernalParser: parseCMSearches :: String -> Either ParseError CMsearch
+ Bio.InfernalParser: parseCMstat :: String -> Either ParseError CMstat
+ Bio.InfernalParser: readCMSearch :: String -> IO (Either ParseError CMsearch)
+ Bio.InfernalParser: readCMSearches :: String -> IO (Either ParseError CMsearch)
+ Bio.InfernalParser: readCMstat :: String -> IO (Either ParseError CMstat)
+ Bio.RNAcentralHTTP: buildSequenceViaMD5Query :: Sequence -> String
+ Bio.RNAcentralHTTP: data RNAcentralEntry
+ Bio.RNAcentralHTTP: data RNAcentralEntryResponse
+ Bio.RNAcentralHTTP: getRNACentralEntries :: [String] -> IO [(Either String RNAcentralEntryResponse)]
+ Bio.RNAcentralHTTP: instance Data.Aeson.Types.Class.FromJSON Bio.RNAcentralHTTP.RNAcentralEntry
+ Bio.RNAcentralHTTP: instance Data.Aeson.Types.Class.FromJSON Bio.RNAcentralHTTP.RNAcentralEntryResponse
+ Bio.RNAcentralHTTP: instance Data.Aeson.Types.Class.ToJSON Bio.RNAcentralHTTP.RNAcentralEntry
+ Bio.RNAcentralHTTP: instance Data.Aeson.Types.Class.ToJSON Bio.RNAcentralHTTP.RNAcentralEntryResponse
+ Bio.RNAcentralHTTP: instance GHC.Classes.Eq Bio.RNAcentralHTTP.RNAcentralEntry
+ Bio.RNAcentralHTTP: instance GHC.Classes.Eq Bio.RNAcentralHTTP.RNAcentralEntryResponse
+ Bio.RNAcentralHTTP: instance GHC.Generics.Constructor Bio.RNAcentralHTTP.C1_0RNAcentralEntry
+ Bio.RNAcentralHTTP: instance GHC.Generics.Constructor Bio.RNAcentralHTTP.C1_0RNAcentralEntryResponse
+ Bio.RNAcentralHTTP: instance GHC.Generics.Datatype Bio.RNAcentralHTTP.D1RNAcentralEntry
+ Bio.RNAcentralHTTP: instance GHC.Generics.Datatype Bio.RNAcentralHTTP.D1RNAcentralEntryResponse
+ Bio.RNAcentralHTTP: instance GHC.Generics.Generic Bio.RNAcentralHTTP.RNAcentralEntry
+ Bio.RNAcentralHTTP: instance GHC.Generics.Generic Bio.RNAcentralHTTP.RNAcentralEntryResponse
+ Bio.RNAcentralHTTP: instance GHC.Generics.Selector Bio.RNAcentralHTTP.S1_0_0RNAcentralEntry
+ Bio.RNAcentralHTTP: instance GHC.Generics.Selector Bio.RNAcentralHTTP.S1_0_0RNAcentralEntryResponse
+ Bio.RNAcentralHTTP: instance GHC.Generics.Selector Bio.RNAcentralHTTP.S1_0_1RNAcentralEntry
+ Bio.RNAcentralHTTP: instance GHC.Generics.Selector Bio.RNAcentralHTTP.S1_0_1RNAcentralEntryResponse
+ Bio.RNAcentralHTTP: instance GHC.Generics.Selector Bio.RNAcentralHTTP.S1_0_2RNAcentralEntry
+ Bio.RNAcentralHTTP: instance GHC.Generics.Selector Bio.RNAcentralHTTP.S1_0_2RNAcentralEntryResponse
+ Bio.RNAcentralHTTP: instance GHC.Generics.Selector Bio.RNAcentralHTTP.S1_0_3RNAcentralEntry
+ Bio.RNAcentralHTTP: instance GHC.Generics.Selector Bio.RNAcentralHTTP.S1_0_3RNAcentralEntryResponse
+ Bio.RNAcentralHTTP: instance GHC.Generics.Selector Bio.RNAcentralHTTP.S1_0_4RNAcentralEntry
+ Bio.RNAcentralHTTP: instance GHC.Generics.Selector Bio.RNAcentralHTTP.S1_0_5RNAcentralEntry
+ Bio.RNAcentralHTTP: instance GHC.Generics.Selector Bio.RNAcentralHTTP.S1_0_6RNAcentralEntry
+ Bio.RNAcentralHTTP: instance GHC.Show.Show Bio.RNAcentralHTTP.RNAcentralEntry
+ Bio.RNAcentralHTTP: instance GHC.Show.Show Bio.RNAcentralHTTP.RNAcentralEntryResponse
+ Bio.RNAcentralHTTP: rnaCentralHTTP :: String -> IO (Either String RNAcentralEntryResponse)
+ Bio.RNAcentralHTTP: showRNAcentralAlienEvaluation :: [(Either String RNAcentralEntryResponse)] -> String
+ Bio.RNAlienData: [queryNumber] :: StaticOptions -> Int
+ Bio.RNAlienData: [querySelectionMethod] :: StaticOptions -> String
+ Bio.RNAlienLibrary: readCMSearches :: String -> IO (Either ParseError CMsearch)
- Bio.RNAlienData: SearchResult :: [(Sequence, Int, String, Char)] -> Maybe Double -> SearchResult
+ Bio.RNAlienData: SearchResult :: [(Sequence, Int, ByteString)] -> Maybe Double -> SearchResult
- Bio.RNAlienData: SequenceRecord :: Sequence -> Int -> String -> Char -> SequenceRecord
+ Bio.RNAlienData: SequenceRecord :: Sequence -> Int -> ByteString -> SequenceRecord
- Bio.RNAlienData: StaticOptions :: String -> String -> Double -> Maybe Int -> Bool -> Bool -> Bool -> Int -> Maybe String -> Maybe String -> Bool -> StaticOptions
+ Bio.RNAlienData: StaticOptions :: String -> String -> Double -> Maybe Int -> Bool -> String -> Int -> Bool -> Bool -> Int -> Maybe String -> Maybe String -> Bool -> StaticOptions
- Bio.RNAlienData: [candidates] :: SearchResult -> [(Sequence, Int, String, Char)]
+ Bio.RNAlienData: [candidates] :: SearchResult -> [(Sequence, Int, ByteString)]
- Bio.RNAlienData: [recordDescription] :: SequenceRecord -> String
+ Bio.RNAlienData: [recordDescription] :: SequenceRecord -> ByteString
- Bio.RNAlienLibrary: checkTools :: [String] -> String -> IO (Either String String)
+ Bio.RNAlienLibrary: checkTools :: [String] -> String -> String -> IO (Either String String)
- Bio.RNAlienLibrary: compareCM :: String -> String -> String -> IO Double
+ Bio.RNAlienLibrary: compareCM :: String -> String -> String -> IO (Either String Double)
- Bio.RNAlienLibrary: evaluateConstructionResult :: StaticOptions -> Int -> IO String
+ Bio.RNAlienLibrary: evaluateConstructionResult :: StaticOptions -> ModelConstruction -> IO String
- Bio.RNAlienLibrary: evaluePartitionTrimCMsearchHits :: Double -> [(CMsearch, (Sequence, Int, String, Char))] -> ([(CMsearch, (Sequence, Int, String, Char))], [(CMsearch, (Sequence, Int, String, Char))], [(CMsearch, (Sequence, Int, String, Char))])
+ Bio.RNAlienLibrary: evaluePartitionTrimCMsearchHits :: Double -> [(CMsearch, (Sequence, Int, ByteString))] -> ([(CMsearch, (Sequence, Int, ByteString))], [(CMsearch, (Sequence, Int, ByteString))], [(CMsearch, (Sequence, Int, ByteString))])
Files
- RNAlien.cabal +15/−4
- src/Bio/InfernalParser.hs +340/−0
- src/Bio/RNAcentralHTTP.hs +111/−0
- src/Bio/RNAlien.hs +10/−7
- src/Bio/RNAlienData.hs +8/−9
- src/Bio/RNAlienLibrary.hs +182/−327
- src/Bio/RNAlienStatistics.hs +54/−33
RNAlien.cabal view
@@ -2,7 +2,7 @@ -- see http://haskell.org/cabal/users-guide/ name: RNAlien-version: 1.0.0+version: 1.1.0 synopsis: Unsupervized construction of RNA family models description: RNAlien is a tool for automatic construction of RNAfamily models from a single sequence. .@@ -26,11 +26,11 @@ . * <http://infernal.janelia.org/ Infernal> .- * <http://www.clustal.org/omega/#Download clustal-omega>- . * <http://www.bioinf.uni-freiburg.de/Software/LocARNA/#download Locarna> . * <https://www.tbi.univie.ac.at/~wash/RNAz/ RNAz>+ .+ * <http://wash.github.io/rnacode/ RNAcode> . * <http://www.tbi.univie.ac.at/RNA/index.html#download ViennaRNA package> .@@ -47,6 +47,15 @@ build-type: Simple cabal-version: >=1.8 +source-repository head+ type: git+ location: https://github.com/eggzilla/RNAlien++source-repository this+ type: git+ location: https://github.com/eggzilla/RNAlien/tree/1.1.0+ tag: 1.1.0+ executable RNAlien Hs-Source-Dirs: ./src/Bio/ main-is: RNAlien.hs @@ -68,8 +77,10 @@ Library Hs-Source-Dirs: ./src/ ghc-options: -Wall -O2 -fno-warn-unused-do-bind- build-depends: base >=4.5 && <5, cmdargs, ViennaRNAParser>=1.2.6, process, directory, blastxml>=0.3.2, biofasta, parsec, random, BlastHTTP, biocore, bytestring, Taxonomy >= 1.0.1, either-unwrap, containers, ClustalParser>=1.1.0, EntrezHTTP>=1.0.0, split, vector, edit-distance, cassava, matrix, hierarchical-clustering, filepath, HTTP+ build-depends: base >=4.5 && <5, cmdargs, ViennaRNAParser>=1.2.8, process, directory, blastxml>=0.3.2, biofasta, parsec, random, BlastHTTP, biocore, bytestring, Taxonomy >= 1.0.1, either-unwrap, containers, ClustalParser>=1.1.0, EntrezHTTP>=1.0.1, vector, edit-distance, cassava, matrix, hierarchical-clustering, filepath, HTTP, http-conduit, hxt, network, aeson, text, transformers >= 0.4 && <0.5, pureMD5 Exposed-Modules: Bio.RNAlienData Bio.RNAlienLibrary+ Bio.RNAcentralHTTP+ Bio.InfernalParser
+ src/Bio/InfernalParser.hs view
@@ -0,0 +1,340 @@+-- | This module contains parsing functions for Infernal programs++module Bio.InfernalParser (+ module Bio.RNAlienData, + readCMSearch,+ readCMSearches,+ parseCMSearch,+ parseCMSearches,+ parseCMstat,+ readCMstat+ )+where++import Text.ParserCombinators.Parsec +import Bio.RNAlienData+import qualified Data.ByteString.Lazy.Char8 as L+import qualified Control.Exception.Base as CE++-- | parse from input filePath +parseCMSearch :: String -> Either ParseError CMsearch+parseCMSearch = parse genParserCMSearch "parseCMsearch" ++-- | parse from input filePath +parseCMSearches :: String -> Either ParseError CMsearch+parseCMSearches = parse genParserCMSearches "parseCMsearch"++-- | parse from input filePath +readCMSearch :: String -> IO (Either ParseError CMsearch) +readCMSearch filePath = do + parsedFile <- parseFromFile genParserCMSearch filePath+ CE.evaluate parsedFile ++-- | parse from input filePath +readCMSearches :: String -> IO (Either ParseError CMsearch) +readCMSearches filePath = do + parsedFile <- parseFromFile genParserCMSearches filePath+ CE.evaluate parsedFile ++genParserCMSearches :: GenParser Char st CMsearch+genParserCMSearches = do+ string "# cmsearch :: search CM(s) against a sequence database"+ newline+ string "# INFERNAL "+ many1 (noneOf "\n")+ newline + string "# Copyright (C) 201"+ many1 (noneOf "\n")+ newline + string "# Freely distributed under the GNU General Public License (GPLv3)."+ newline + string "# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"+ newline+ string "# query CM file:"+ many1 space+ queryCMfile' <- many1 (noneOf "\n")+ newline+ string "# target sequence database:"+ many1 space + targetSequenceDatabase' <- many1 (noneOf "\n")+ newline+ optional (try (genParserCMsearchHeaderField "# CM configuration"))+ optional (try (genParserCMsearchHeaderField "# database size is set to"))+ optional (try (genParserCMsearchHeaderField "# truncated sequence detection"))+ string "# number of worker threads:"+ many1 space+ numberOfWorkerThreads' <- many1 (noneOf "\n")+ newline+ string "# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"+ newline+ optional newline+ cmSearchesHits <- many1 (try genParserMultipleCMSearch)+ optional (string "[ok]\n")+ eof+ return $ CMsearch queryCMfile' targetSequenceDatabase' numberOfWorkerThreads' (concat cmSearchesHits)+ +genParserCMSearch :: GenParser Char st CMsearch+genParserCMSearch = do+ string "# cmsearch :: search CM(s) against a sequence database"+ newline+ string "# INFERNAL "+ many1 (noneOf "\n")+ newline + string "# Copyright (C) 201"+ many1 (noneOf "\n")+ newline + string "# Freely distributed under the GNU General Public License (GPLv3)."+ newline + string "# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"+ newline+ string "# query CM file:"+ many1 space+ queryCMfile' <- many1 (noneOf "\n")+ newline+ string "# target sequence database:"+ many1 space + targetSequenceDatabase' <- many1 (noneOf "\n")+ newline+ optional (try (genParserCMsearchHeaderField "# CM configuration"))+ optional (try (genParserCMsearchHeaderField "# database size is set to"))+ optional (try (genParserCMsearchHeaderField "# truncated sequence detection"))+ string "# number of worker threads:"+ many1 space+ numberOfWorkerThreads' <- many1 (noneOf "\n")+ newline+ string "# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"+ newline+ optional newline+ string "Query:"+ many1 (noneOf "\n") + newline+ optional (try (genParserCMsearchHeaderField "Accession"))+ optional (try (genParserCMsearchHeaderField "Description"))+ string "Hit scores:"+ newline+ choice [try (string " rank"), try (string " rank") , try (string " rank"), try (string " rank"),try (string " rank"),try (string " rank")]+ many1 space + string "E-value"+ many1 space + string "score"+ many1 space + string "bias"+ many1 space + string "sequence"+ many1 space + string "start"+ many1 space + string "end"+ many1 space + string "mdl"+ many1 space + string "trunc"+ many1 space + string "gc"+ many1 space + string "description"+ newline+ string " -"+ many1 (try (oneOf " -"))+ newline+ optional (try (string " ------ inclusion threshold ------"))+ many newline+ hitScores' <- many (try genParserCMsearchHit) --`endBy` (try (string "Hit alignments:"))+ optional (try genParserCMsearchEmptyHit)+ -- this is followed by hit alignments and internal cmsearch statistics which are not parsed+ many anyChar+ eof+ return $ CMsearch queryCMfile' targetSequenceDatabase' numberOfWorkerThreads' hitScores'++-- | Parsing function for CMSearches with multiple querymodels in one modelfile, e.g. clans+genParserMultipleCMSearch :: GenParser Char st [CMsearchHit]+genParserMultipleCMSearch = do+ --optional newline+ --optional string "//"+ string "Query:"+ many1 (noneOf "\n") + newline+ optional (try (genParserCMsearchHeaderField "Accession"))+ optional (try (genParserCMsearchHeaderField "Description"))+ string "Hit scores:"+ newline+ choice [try (string " rank"), try (string " rank") , try (string " rank"), try (string " rank"),try (string " rank"),try (string " rank")]+ many1 space + string "E-value"+ many1 space + string "score"+ many1 space + string "bias"+ many1 space + string "sequence"+ many1 space + string "start"+ many1 space + string "end"+ many1 space + string "mdl"+ many1 space + string "trunc"+ many1 space + string "gc"+ many1 space + string "description"+ newline+ string " -"+ many1 (try (oneOf " -"))+ newline+ optional (try (string " ------ inclusion threshold ------"))+ many newline+ hitScores' <- many (try genParserCMsearchHit) --`endBy` (try (string "Hit alignments:"))+ optional (try genParserCMsearchEmptyHit)+ -- this is followed by hit alignments and internal cmsearch statistics which are not parsed+ --many anyChar+ manyTill anyChar (try (string "//\n"))+ return hitScores'++genParserCMsearchHeaderField :: String -> GenParser Char st String+genParserCMsearchHeaderField fieldname = do+ string (fieldname ++ ":")+ many1 space+ many1 (noneOf "\n")+ newline+ return []++genParserCMsearchEmptyHit :: GenParser Char st [CMsearchHit]+genParserCMsearchEmptyHit = do+ string " [No hits detected that satisfy reporting thresholds]"+ newline+ optional (try newline)+ return []++genParserCMsearchHit :: GenParser Char st CMsearchHit+genParserCMsearchHit = do+ many1 space+ string "(" + hitRank' <- many1 digit+ string ")"+ many1 space+ hitSignificant' <- choice [char '!', char '?']+ many1 space + hitEValue' <- many1 (oneOf "0123456789.e-")+ many1 space + hitScore' <- many1 (oneOf "0123456789.e-")+ many1 space + hitBias' <- many1 (oneOf "0123456789.e-")+ many1 space+ hitSequenceHeader' <- many1 (noneOf " ")+ many1 space + hitStart' <- many1 digit+ many1 space+ hitEnd' <- many1 digit+ many1 space + hitStrand' <- choice [char '+', char '-', char '.']+ many1 space + hitModel' <- many1 letter+ many1 space + hitTruncation' <- many1 (choice [alphaNum, char '\''])+ many1 space + hitGCcontent' <- many1 (oneOf "0123456789.e-")+ many1 space + hitDescription' <- many1 (noneOf "\n") + newline+ optional (try (string " ------ inclusion threshold ------"))+ optional (try newline)+ return $ CMsearchHit (readInt hitRank') hitSignificant' (readDouble hitEValue') (readDouble hitScore') (readDouble hitBias') (L.pack hitSequenceHeader') (readInt hitStart') (readInt hitEnd') hitStrand' (L.pack hitModel') (L.pack hitTruncation') (readDouble hitGCcontent') (L.pack hitDescription')++-- | parse from input filePath +parseCMstat :: String -> Either ParseError CMstat+parseCMstat = parse genParserCMstat "parseCMstat"++-- | parse from input filePath +readCMstat :: String -> IO (Either ParseError CMstat) +readCMstat filePath = do + parsedFile <- parseFromFile genParserCMstat filePath+ CE.evaluate parsedFile + +genParserCMstat :: GenParser Char st CMstat+genParserCMstat = do+ string "# cmstat :: display summary statistics for CMs"+ newline+ string "# INFERNAL "+ many1 (noneOf "\n")+ newline + string "# Copyright (C) 201"+ many1 (noneOf "\n")+ newline + string "# Freely distributed under the GNU General Public License (GPLv3)."+ newline + string "# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"+ newline+ char '#'+ many1 (char ' ')+ string "rel entropy"+ newline+ char '#'+ many1 (char ' ')+ many1 (char '-')+ newline+ char '#'+ many1 space + string "idx"+ many1 space + string "name"+ many1 space + string "accession"+ many1 space + string "nseq"+ many1 space + string "eff_nseq"+ many1 space + string "clen"+ many1 space + string "W"+ many1 space + string "bps"+ many1 space + string "bifs"+ many1 space + string "model"+ many1 space + string "cm"+ many1 space+ string "hmm"+ newline+ string "#"+ many1 (try (oneOf " -"))+ newline+ many1 space + _statIndex <- many1 digit+ many1 space+ _statName <- many1 letter+ many1 space + _statAccession <- many1 (noneOf " ")+ many1 space + _statSequenceNumber <- many1 digit+ many1 space + _statEffectiveSequences <- many1 (oneOf "0123456789.e-")+ many1 space+ _statConsensusLength <- many digit+ many1 space + _statW <- many1 digit+ many1 space+ _statBasepaires <- many1 digit+ many1 space + _statBifurcations <- many1 digit+ many1 space + _statModel <- many1 letter+ many1 space + _relativeEntropyCM <- many1 (oneOf "0123456789.e-")+ many1 space + _relativeEntropyHMM <- many1 (oneOf "0123456789.e-")+ newline+ char '#'+ newline+ eof + return $ CMstat (readInt _statIndex) _statName _statAccession (readInt _statSequenceNumber) (readDouble _statEffectiveSequences) (readInt _statConsensusLength) (readInt _statW) (readInt _statBasepaires) (readInt _statBifurcations) _statModel (readDouble _relativeEntropyCM) (readDouble _relativeEntropyHMM)+-- +readInt :: String -> Int+readInt = read++readDouble :: String -> Double+readDouble = read
+ src/Bio/RNAcentralHTTP.hs view
@@ -0,0 +1,111 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Arrows #-}+{-# LANGUAGE DeriveGeneric #-}++-- | Interface for the RNAcentral REST webservice.+-- +module Bio.RNAcentralHTTP (rnaCentralHTTP,+ buildSequenceViaMD5Query,+ getRNACentralEntries,+ showRNAcentralAlienEvaluation,+ RNAcentralEntryResponse,+ RNAcentralEntry+ ) where++import Network.HTTP.Conduit +import qualified Data.ByteString.Lazy.Char8 as L8 +import Network+import Control.Concurrent+import Data.Text+import Data.Aeson+import GHC.Generics+import qualified Data.Digest.Pure.MD5 as M+import Bio.Core.Sequence +import Bio.Sequence.Fasta+import Data.Either+import Data.Aeson.Types++--Datatypes+-- | Data structure for RNAcentral entry response+data RNAcentralEntryResponse = RNAcentralEntryResponse+ {+ _count :: Int,+ _next :: Maybe Text,+ _previous :: Maybe Text,+ results :: [RNAcentralEntry]+ }+ deriving (Show, Eq, Generic)++instance ToJSON RNAcentralEntryResponse where+ toJSON = genericToJSON defaultOptions+ --toEncoding = genericToEncoding defaultOptions++instance FromJSON RNAcentralEntryResponse ++data RNAcentralEntry = RNAcentralEntry+ {+ _url :: Text,+ rnacentral_id :: Text,+ md5 :: Text,+ _sequence :: Text,+ length :: Int,+ _xrefs :: Text,+ _publications :: Text+ }+ deriving (Show, Eq, Generic)++instance ToJSON RNAcentralEntry where+ toJSON = genericToJSON defaultOptions+ --toEncoding = genericToEncoding defaultOptions++instance FromJSON RNAcentralEntry ++-- | Send query and parse return XML +startSession :: String -> IO (Either String RNAcentralEntryResponse)+startSession query' = do+ requestXml <- withSocketsDo+ $ sendQuery query'+ let eitherErrorResponse = eitherDecode requestXml :: Either String RNAcentralEntryResponse+ return eitherErrorResponse+ +-- | Send query and return response XML+sendQuery :: String -> IO L8.ByteString+sendQuery query' = simpleHttp ("http://rnacentral.org/api/v1/rna/" ++ query')++-- | Function for querying the RNAcentral REST interface.+rnaCentralHTTP :: String -> IO (Either String RNAcentralEntryResponse)+rnaCentralHTTP query' = do+ startSession query'++-- | Function for delayed queries to the RNAcentral REST interface. Enforces the maximum 20 requests per second policy.+delayedRNACentralHTTP :: String -> IO (Either String RNAcentralEntryResponse)+delayedRNACentralHTTP query' = do+ threadDelay 55000+ startSession query'++getRNACentralEntries :: [String] -> IO [(Either String RNAcentralEntryResponse)]+getRNACentralEntries queries = do+ responses <- mapM delayedRNACentralHTTP queries+ return responses++buildSequenceViaMD5Query :: Sequence -> String+buildSequenceViaMD5Query s = qString+ where querySequence = unSD (seqdata s)+ querySequenceUreplacedwithT = L8.map bsreplaceUT querySequence+ md5Sequence = M.md5 querySequenceUreplacedwithT+ qString = "?md5=" ++ (show md5Sequence)++showRNAcentralAlienEvaluation :: [(Either String RNAcentralEntryResponse)] -> String+showRNAcentralAlienEvaluation responses = output+ where resultEntries = Prelude.concatMap results (rights responses)+ resulthead = "rnacentral_id\tmd5\tlength\n"+ resultentries = Prelude.concatMap showRNAcentralAlienEvaluationLine resultEntries+ output = if resultentries == [] then resulthead ++ "No matching sequences found in RNAcentral\n" else resulthead ++ resultentries+ +showRNAcentralAlienEvaluationLine :: RNAcentralEntry -> String+showRNAcentralAlienEvaluationLine entry = unpack (rnacentral_id entry) ++ "\t" ++ unpack (md5 entry) ++ "\t" ++ show (Bio.RNAcentralHTTP.length entry) ++"\n"++bsreplaceUT :: Char -> Char+bsreplaceUT a+ | a == 'U' = 'T'+ | otherwise = a
src/Bio/RNAlien.hs view
@@ -26,6 +26,8 @@ lengthFilter :: Bool, coverageFilter :: Bool, singleHitperTax :: Bool,+ inputQuerySelectionMethod :: String,+ inputQueryNumber :: Int, threads :: Int, taxonomyRestriction :: Maybe String, sessionIdentificator :: Maybe String@@ -41,11 +43,13 @@ inputBlastDatabase = Just "nt" &= name "b" &= help "Specify name of blast database to use. Default: nt", lengthFilter = True &= name "l" &= help "Filter blast hits per genomic length. Default: True", coverageFilter = True &= name "a" &= help "Filter blast hits by coverage of at least 80%. Default: True",- singleHitperTax = True &= name "s" &= help "Only the best blast hit per taxonomic entry is considered. Default: True",+ singleHitperTax = False &= name "s" &= help "Only the best blast hit per taxonomic entry is considered. Default: False",+ inputQuerySelectionMethod = "filtering" &= name "m" &= help "Method for selection of queries (filtering,clustering). Default: filtering",+ inputQueryNumber = (5 :: Int) &= name "n" &= help "Number of queries used for candidate search. Default: 5", threads = 1 &= name "c" &= help "Number of available cpu slots/cores. Default: 1", taxonomyRestriction = Nothing &= name "r" &= help "Restrict search space to taxonomic kingdom (bacteria,archea,eukaryia). Default: not set", sessionIdentificator = Nothing &= name "d" &= help "Optional session id that is used instead of automatically generated one."- } &= summary "RNAlien version 1.0.0" &= help "Florian Eggenhofer, Ivo L. Hofacker, Christian Höner zu Siederdissen - 2013 - 2015" &= verbosity + } &= summary "RNAlien version 1.0.0" &= help "Florian Eggenhofer, Ivo L. Hofacker, Christian Höner zu Siederdissen - 2013 - 2016" &= verbosity main :: IO () main = do@@ -75,8 +79,8 @@ logMessage "Error: Input fasta file is empty.\n" temporaryDirectoryPath else do let iterationNumber = 0- let tools = ["clustalo","mlocarna","RNAfold","RNAalifold","cmcalibrate","cmstat","cmbuild","RNAz"]- toolsCheck <- checkTools tools temporaryDirectoryPath+ let tools = ["mlocarna","RNAfold","RNAalifold","cmcalibrate","cmstat","cmbuild","RNAz","RNAcode"]+ toolsCheck <- checkTools tools inputQuerySelectionMethod temporaryDirectoryPath -- Check required commandline tools if isLeft toolsCheck then do @@ -87,13 +91,12 @@ let inputSequence = reformatFasta (head inputFasta) initialTaxId <- setInitialTaxId inputBlastDatabase temporaryDirectoryPath inputTaxId inputSequence let checkedTaxonomyRestriction = checkTaxonomyRestriction taxonomyRestriction- let staticOptions = StaticOptions temporaryDirectoryPath sessionId (fromJust inputnSCICutoff) inputTaxId singleHitperTax lengthFilter coverageFilter threads inputBlastDatabase checkedTaxonomyRestriction (setVerbose verboseLevel)+ let staticOptions = StaticOptions temporaryDirectoryPath sessionId (fromJust inputnSCICutoff) inputTaxId singleHitperTax inputQuerySelectionMethod inputQueryNumber lengthFilter coverageFilter threads inputBlastDatabase checkedTaxonomyRestriction (setVerbose verboseLevel) let initialization = ModelConstruction iterationNumber inputSequence [] initialTaxId Nothing (fromJust inputEvalueCutoff) False [] [] logMessage (show initialization) temporaryDirectoryPath modelConstructionResults <- modelConstructer staticOptions initialization let resultTaxonomyRecordsCSVTable = constructTaxonomyRecordsCSVTable modelConstructionResults- let resultNumber = (length (concatMap sequenceRecords (taxRecords modelConstructionResults))) + 1- resultEvaluation <- evaluateConstructionResult staticOptions resultNumber+ resultEvaluation <- evaluateConstructionResult staticOptions modelConstructionResults appendFile (temporaryDirectoryPath ++ "Log") resultEvaluation writeFile (temporaryDirectoryPath ++ "result.csv") resultTaxonomyRecordsCSVTable resultSummary modelConstructionResults staticOptions
src/Bio/RNAlienData.hs view
@@ -14,6 +14,8 @@ nSCICutoff :: Double, userTaxId :: Maybe Int, singleHitperTaxToggle :: Bool,+ querySelectionMethod :: String,+ queryNumber :: Int, lengthFilterToggle :: Bool, coverageFilterToggle :: Bool, cpuThreads :: Int,@@ -62,17 +64,14 @@ nucleotideSequence :: Sequence, -- 0 is unaligned, number is the iteration the sequence has been included into the alignment aligned :: Int,- recordDescription :: String,- -- Is the sequence derived from the blast hit coordinates (B) or from a corresponding genbank feature (G)- sequenceOrigin :: Char + recordDescription :: L.ByteString } instance Show SequenceRecord where- show (SequenceRecord _nucleotideSequence _aligned _recordDescription _sequenceOrigin) = a ++ b ++ c ++ d - where a = "SequenceRecord TaxonomyId: " ++ show _recordDescription ++ "\n" - b = "Sequence Origin: " ++ _recordDescription ++ "\n" - c = "Aligned in iteration: " ++ show _aligned ++ "\n" - d = "Sequence Origin: " ++ show _nucleotideSequence ++ "\n"+ show (SequenceRecord _nucleotideSequence _aligned _recordDescription) = a ++ b ++ c + where a = "Record Description: " ++ (L.unpack _recordDescription) ++ "\n" + b = "Aligned in iteration: " ++ show _aligned ++ "\n" + c = "Sequence:" ++ show _nucleotideSequence ++ "\n" -- | data CMsearch = CMsearch { queryCMfile :: String,@@ -101,7 +100,7 @@ } deriving (Show, Eq, Read) data SearchResult = SearchResult- { candidates :: [(Sequence,Int,String,Char)],+ { candidates :: [(Sequence,Int,L.ByteString)], blastDatabaseSize :: Maybe Double }
src/Bio/RNAlienLibrary.hs view
@@ -13,6 +13,7 @@ checkTools, systemCMsearch, readCMSearch,+ readCMSearches, compareCM, parseCMSearch, cmSearchsubString,@@ -46,9 +47,8 @@ import Data.Either.Unwrap import Data.Maybe import Bio.EntrezHTTP -import qualified Data.List.Split as DS import System.Exit-import Data.Either (lefts,rights)+import Data.Either (lefts,rights,Either) import qualified Text.EditDistance as ED import qualified Data.Vector as V import Control.Concurrent @@ -64,6 +64,12 @@ import Bio.RNAalifoldParser import Bio.RNAzParser import Network.HTTP+import qualified Bio.RNAcodeParser as RC+import Bio.RNAcentralHTTP+import Bio.InfernalParser+import qualified Data.Text as T+import qualified Data.Text.IO as TI+import qualified Data.Text.Encoding as DTE -- | Initial RNA family model construction - generates iteration number, seed alignment and model modelConstructer :: StaticOptions -> ModelConstruction -> IO ModelConstruction@@ -192,13 +198,15 @@ let alignmentSequences = map snd (V.toList (V.concat [alignedSequences])) writeFasta preliminaryFastaPath alignmentSequences let cmBuildFilepath = iterationDirectory ++ "model" ++ ".cmbuild"+ let refinedAlignmentFilepath = iterationDirectory ++ "modelrefined" ++ ".stockholm"+ let cmBuildOptions ="--refine " ++ refinedAlignmentFilepath let foldFilepath = iterationDirectory ++ "model" ++ ".fold" _ <- systemRNAfold preliminaryFastaPath foldFilepath foldoutput <- readRNAfold foldFilepath let seqStructure = foldSecondaryStructure (fromRight foldoutput) let stockholAlignment = convertFastaFoldStockholm (head alignmentSequences) seqStructure writeFile preliminaryAlignmentPath stockholAlignment- _ <- systemCMbuild preliminaryAlignmentPath preliminaryCMPath cmBuildFilepath+ _ <- systemCMbuild cmBuildOptions preliminaryAlignmentPath preliminaryCMPath cmBuildFilepath _ <- systemCMcalibrate "fast" (cpuThreads staticOptions) preliminaryCMPath preliminaryCMLogPath resultModelConstruction <- reevaluatePotentialMembers staticOptions nextModelConstructionInput return resultModelConstruction@@ -247,6 +255,7 @@ let lastIterationAlignmentPath = outputDirectory ++ show (currentIterationNumber - 1) ++ "/model.stockholm" let lastIterationCMPath = outputDirectory ++ show (currentIterationNumber - 1)++ "/model.cm" copyFile lastIterationCMPath resultCMPath+ --copyFile lastIterationCMPath (resultCMPath ++ ".bak1") copyFile lastIterationFastaPath resultFastaPath copyFile lastIterationAlignmentPath resultAlignmentPath _ <- systemCMcalibrate "standard" (cpuThreads staticOptions) resultCMPath resultCMLogPath@@ -260,8 +269,10 @@ let nextModelConstructionInput = constructNext currentIterationNumber modelConstruction alignmentResults Nothing Nothing [] [] (alignmentModeInfernal modelConstruction) constructModel nextModelConstructionInput staticOptions copyFile lastIterationCMPath resultCMPath+ --debug+ --copyFile lastIterationCMPath (resultCMPath ++ ".bak2") copyFile lastIterationFastaPath resultFastaPath- copyFile lastIterationAlignmentPath resultAlignmentPath + copyFile lastIterationAlignmentPath resultAlignmentPath logMessage (iterationSummaryLog nextModelConstructionInput) outputDirectory logVerboseMessage (verbositySwitch staticOptions) (show nextModelConstructionInput) outputDirectory _ <- systemCMcalibrate "standard" (cpuThreads staticOptions) resultCMPath resultCMLogPath@@ -393,7 +404,9 @@ logVerboseMessage (verbositySwitch staticOptions) ("entrezTaxFilter" ++ show entrezTaxFilter ++ "\n") (tempDirPath staticOptions) let hitNumberQuery = buildHitNumberQuery "&HITLIST_SIZE=5000&EXPECT=" ++ show expectThreshold let registrationInfo = buildRegistration "RNAlien" "florian.eggenhofer@univie.ac.at"- let blastQuery = BlastHTTPQuery (Just "ncbi") (Just "blastn") (blastDatabase staticOptions) querySequences' (Just (hitNumberQuery ++ entrezTaxFilter ++ registrationInfo)) (Just (5400000000 :: Int))+ let softmaskFilter = "&FILTER=True&FILTER=m"+ let blastQuery = BlastHTTPQuery (Just "ncbi") (Just "blastn") (blastDatabase staticOptions) querySequences' (Just (hitNumberQuery ++ entrezTaxFilter ++ softmaskFilter ++ registrationInfo)) (Just (5400000000 :: Int))+ --appendFile "/scratch/egg/blasttest/queries" ("\nBlast query:\n" ++ show blastQuery ++ "\n") logVerboseMessage (verbositySwitch staticOptions) ("Sending blast query " ++ (show iterationnumber) ++ "\n") (tempDirPath staticOptions) blastOutput <- CE.catch (blastHTTP blastQuery) (\e -> do let err = show (e :: CE.IOException)@@ -422,7 +435,7 @@ let blastHitsFilteredByCoverage = filterByCoverage blastHitsFilteredByLength queryLength (coverageFilterToggle staticOptions) writeFile (logFileDirectoryPath ++ "/" ++ queryIndexString ++ "_3ablastHitsFilteredByLength") (showlines blastHitsFilteredByCoverage) --tag BlastHits with TaxId- blastHitsWithTaxIdOutput <- retrieveBlastHitsTaxIdEntrez blastHitsFilteredByLength+ blastHitsWithTaxIdOutput <- retrieveBlastHitsTaxIdEntrez blastHitsFilteredByCoverage let uncheckedBlastHitsWithTaxIdList = map (\(blasthits,taxIdout) -> (blasthits,extractTaxIdFromEntrySummaries taxIdout)) blastHitsWithTaxIdOutput let checkedBlastHitsWithTaxId = filter (\(_,taxids) -> not (null taxids)) uncheckedBlastHitsWithTaxIdList --todo checked blasthittaxidswithblasthits need to be merged as taxid blasthit pairs@@ -451,7 +464,7 @@ else do writeFile (logFileDirectoryPath ++ "/" ++ queryIndexString ++ "_10afullSequencesWithSimilars") (showlines fullSequencesWithSimilars) let fullSequences = filterIdenticalSequences fullSequencesWithSimilars 100- let fullSequencesWithOrigin = map (\(parsedFasta,taxid,seqSubject) -> (parsedFasta,taxid,seqSubject,'B')) fullSequences+ --let fullSequencesWithOrigin = map (\(parsedFasta,taxid,seqSubject) -> (parsedFasta,taxid,seqSubject,'B')) fullSequences writeFile (logFileDirectoryPath ++ "/" ++ queryIndexString ++ "_10fullSequences") (showlines fullSequences) let maybeFractionEvalueMatch = getHitWithFractionEvalue rightBlast if isNothing maybeFractionEvalueMatch@@ -459,14 +472,14 @@ else do let fractionEvalueMatch = fromJust maybeFractionEvalueMatch let dbSize = computeDataBaseSize (e_val fractionEvalueMatch) (bits fractionEvalueMatch) (fromIntegral queryLength ::Double)- CE.evaluate (SearchResult fullSequencesWithOrigin (Just dbSize))+ CE.evaluate (SearchResult fullSequences (Just dbSize)) else CE.evaluate (SearchResult [] Nothing) -- |Computes size of blast db in Mb computeDataBaseSize :: Double -> Double -> Double -> Double computeDataBaseSize evalue bitscore querylength = ((evalue * 2 ** bitscore) / querylength)/10^(6 :: Integer) -alignCandidates :: StaticOptions -> ModelConstruction -> String -> SearchResult -> IO ([(Sequence,Int,String,Char)],[(Sequence,Int,String,Char)])+alignCandidates :: StaticOptions -> ModelConstruction -> String -> SearchResult -> IO ([(Sequence,Int,L.ByteString)],[(Sequence,Int,L.ByteString)]) alignCandidates staticOptions modelConstruction multipleSearchResultPrefix searchResults = do let iterationDirectory = tempDirPath staticOptions ++ show (iterationNumber modelConstruction) ++ "/" ++ multipleSearchResultPrefix createDirectoryIfMissing False (iterationDirectory ++ "log")@@ -484,7 +497,7 @@ then alignCandidatesInfernalMode staticOptions modelConstruction multipleSearchResultPrefix (blastDatabaseSize searchResults) filteredCandidates else alignCandidatesInitialMode staticOptions modelConstruction multipleSearchResultPrefix filteredCandidates -alignCandidatesInfernalMode :: StaticOptions -> ModelConstruction -> String -> Maybe Double -> [(Sequence,Int,String,Char)] -> IO ([(Sequence,Int,String,Char)],[(Sequence,Int,String,Char)])+alignCandidatesInfernalMode :: StaticOptions -> ModelConstruction -> String -> Maybe Double -> [(Sequence,Int,L.ByteString)] -> IO ([(Sequence,Int,L.ByteString)],[(Sequence,Int,L.ByteString)]) alignCandidatesInfernalMode staticOptions modelConstruction multipleSearchResultPrefix blastDbSize filteredCandidates = do let iterationDirectory = tempDirPath staticOptions ++ show (iterationNumber modelConstruction) ++ "/" ++ multipleSearchResultPrefix let candidateSequences = extractCandidateSequences filteredCandidates @@ -508,7 +521,7 @@ writeFile (iterationDirectory ++ "log" ++ "/15potentialCandidates'") (showlines potentialCandidates) CE.evaluate (map snd trimmedSelectedCandidates,map snd potentialCandidates) -alignCandidatesInitialMode :: StaticOptions -> ModelConstruction -> String -> [(Sequence,Int,String,Char)] -> IO ([(Sequence,Int,String,Char)],[(Sequence,Int,String,Char)])+alignCandidatesInitialMode :: StaticOptions -> ModelConstruction -> String -> [(Sequence,Int,L.ByteString)] -> IO ([(Sequence,Int,L.ByteString)],[(Sequence,Int,L.ByteString)]) alignCandidatesInitialMode staticOptions modelConstruction multipleSearchResultPrefix filteredCandidates = do let iterationDirectory = tempDirPath staticOptions ++ show (iterationNumber modelConstruction) ++ "/" ++ multipleSearchResultPrefix --writeFile (iterationDirectory ++ "log" ++ "/11bcandidates") (showlines filteredCandidates)@@ -562,8 +575,9 @@ | currentClusterNumber >= numberOfClusters = currentCutoff | otherwise = findCutoffforClusterNumber clustaloDendrogram numberOfClusters (currentCutoff-0.01) where currentClusterNumber = length (cutAt clustaloDendrogram currentCutoff)- -selectQueries :: StaticOptions -> ModelConstruction -> [(Sequence,Int,String,Char)] -> IO [String]++-- Selects Query sequence ids from all collected seqeuences. Queries are then fetched by extractQueries function.+selectQueries :: StaticOptions -> ModelConstruction -> [(Sequence,Int,L.ByteString)] -> IO [String] selectQueries staticOptions modelConstruction selectedCandidates = do logVerboseMessage (verbositySwitch staticOptions) "SelectQueries\n" (tempDirPath staticOptions) --Extract sequences from modelconstruction@@ -573,32 +587,39 @@ let alignmentSequences = map snd (V.toList (V.concat [candidateSequences,alignedSequences])) if length alignmentSequences > 3 then do- --write Fasta sequences- writeFasta (iterationDirectory ++ "query" ++ ".fa") alignmentSequences- let fastaFilepath = iterationDirectory ++ "query" ++ ".fa"- let clustaloFilepath = iterationDirectory ++ "query" ++ ".clustalo"- let clustaloDistMatrixPath = iterationDirectory ++ "query" ++ ".matrix" - alignSequences "clustalo" ("--full --distmat-out=" ++ clustaloDistMatrixPath ++ " ") [fastaFilepath] [] [clustaloFilepath] []- idsDistancematrix <- readClustaloDistMatrix clustaloDistMatrixPath- logEither idsDistancematrix (tempDirPath staticOptions)- let (clustaloIds,clustaloDistMatrix) = fromRight idsDistancematrix- logVerboseMessage (verbositySwitch staticOptions) ("Clustalid: " ++ intercalate "," clustaloIds ++ "\n") (tempDirPath staticOptions)- logVerboseMessage (verbositySwitch staticOptions) ("Distmatrix: " ++ show clustaloDistMatrix ++ "\n") (tempDirPath staticOptions)- let clustaloDendrogram = dendrogram UPGMA clustaloIds (getDistanceMatrixElements clustaloIds clustaloDistMatrix)- logVerboseMessage (verbositySwitch staticOptions) ("ClustaloDendrogram: " ++ show clustaloDendrogram ++ "\n") (tempDirPath staticOptions)- logVerboseMessage (verbositySwitch staticOptions) ("ClustaloDendrogram: " ++ show clustaloDistMatrix ++ "\n") (tempDirPath staticOptions)- let numberOfClusters = setClusterNumber (length alignmentSequences)- logVerboseMessage (verbositySwitch staticOptions) ("numberOfClusters: " ++ show numberOfClusters ++ "\n") (tempDirPath staticOptions)- let dendrogramStartCutDistance = 1 :: Double- let dendrogramCutDistance' = findCutoffforClusterNumber clustaloDendrogram numberOfClusters dendrogramStartCutDistance- logVerboseMessage (verbositySwitch staticOptions) ("dendrogramCutDistance': " ++ show dendrogramCutDistance' ++ "\n") (tempDirPath staticOptions)- let cutDendrogram = cutAt clustaloDendrogram dendrogramCutDistance'- --putStrLn "cutDendrogram: "- --print cutDendrogram- let currentSelectedQueries = take 5 (concatMap (take 1 . elements) cutDendrogram)- logVerboseMessage (verbositySwitch staticOptions) ("SelectedQueries: " ++ show currentSelectedQueries ++ "\n") (tempDirPath staticOptions) - writeFile (tempDirPath staticOptions ++ show (iterationNumber modelConstruction) ++ "/log" ++ "/13selectedQueries") (showlines currentSelectedQueries)- CE.evaluate currentSelectedQueries+ if (querySelectionMethod staticOptions) == "clustering"+ then do+ --write Fasta sequences+ writeFasta (iterationDirectory ++ "query" ++ ".fa") alignmentSequences+ let fastaFilepath = iterationDirectory ++ "query" ++ ".fa"+ let clustaloFilepath = iterationDirectory ++ "query" ++ ".clustalo"+ let clustaloDistMatrixPath = iterationDirectory ++ "query" ++ ".matrix" + alignSequences "clustalo" ("--full --distmat-out=" ++ clustaloDistMatrixPath ++ " ") [fastaFilepath] [] [clustaloFilepath] []+ idsDistancematrix <- readClustaloDistMatrix clustaloDistMatrixPath+ logEither idsDistancematrix (tempDirPath staticOptions)+ let (clustaloIds,clustaloDistMatrix) = fromRight idsDistancematrix+ logVerboseMessage (verbositySwitch staticOptions) ("Clustalid: " ++ intercalate "," clustaloIds ++ "\n") (tempDirPath staticOptions)+ logVerboseMessage (verbositySwitch staticOptions) ("Distmatrix: " ++ show clustaloDistMatrix ++ "\n") (tempDirPath staticOptions)+ let clustaloDendrogram = dendrogram UPGMA clustaloIds (getDistanceMatrixElements clustaloIds clustaloDistMatrix)+ logVerboseMessage (verbositySwitch staticOptions) ("ClustaloDendrogram: " ++ show clustaloDendrogram ++ "\n") (tempDirPath staticOptions)+ logVerboseMessage (verbositySwitch staticOptions) ("ClustaloDendrogram: " ++ show clustaloDistMatrix ++ "\n") (tempDirPath staticOptions)+ let numberOfClusters = setClusterNumber (length alignmentSequences)+ logVerboseMessage (verbositySwitch staticOptions) ("numberOfClusters: " ++ show numberOfClusters ++ "\n") (tempDirPath staticOptions)+ let dendrogramStartCutDistance = 1 :: Double+ let dendrogramCutDistance' = findCutoffforClusterNumber clustaloDendrogram numberOfClusters dendrogramStartCutDistance+ logVerboseMessage (verbositySwitch staticOptions) ("dendrogramCutDistance': " ++ show dendrogramCutDistance' ++ "\n") (tempDirPath staticOptions)+ let cutDendrogram = cutAt clustaloDendrogram dendrogramCutDistance'+ --putStrLn "cutDendrogram: "+ --print cutDendrogram+ let currentSelectedQueries = take (queryNumber staticOptions) (concatMap (take 1 . elements) cutDendrogram)+ logVerboseMessage (verbositySwitch staticOptions) ("SelectedQueries: " ++ show currentSelectedQueries ++ "\n") (tempDirPath staticOptions) + writeFile (tempDirPath staticOptions ++ show (iterationNumber modelConstruction) ++ "/log" ++ "/13selectedQueries") (showlines currentSelectedQueries)+ CE.evaluate currentSelectedQueries+ else do+ let currentSelectedSequences = filterIdenticalSequences' alignmentSequences (95 :: Double)+ let currentSelectedQueries = map (L.unpack . unSL . seqid) (take (queryNumber staticOptions) currentSelectedSequences)+ CE.evaluate currentSelectedQueries+ else return [] constructModel :: ModelConstruction -> StaticOptions -> IO String@@ -620,6 +641,8 @@ let cmCalibrateFilepath = outputDirectory ++ "model" ++ ".cmcalibrate" let cmBuildFilepath = outputDirectory ++ "model" ++ ".cmbuild" let alifoldFilepath = outputDirectory ++ "model" ++ ".alifold"+ let refinedAlignmentFilepath = outputDirectory ++ "modelrefined" ++ ".stockholm"+ let cmBuildOptions ="--refine " ++ refinedAlignmentFilepath if alignmentModeInfernal modelConstruction then do logVerboseMessage (verbositySwitch staticOptions) "Construct Model - infernal mode\n" (tempDirPath staticOptions)@@ -628,12 +651,12 @@ replaceStatus <- replaceStockholmStructure stockholmFilepath alifoldFilepath updatedStructureStockholmFilepath if null replaceStatus then do- systemCMbuild updatedStructureStockholmFilepath cmFilepath cmBuildFilepath+ systemCMbuild cmBuildOptions updatedStructureStockholmFilepath cmFilepath cmBuildFilepath systemCMcalibrate "fast" (cpuThreads staticOptions) cmFilepath cmCalibrateFilepath return cmFilepath else do logWarning ("Warning: A problem occured updating the secondary structure of iteration " ++ show (iterationNumber modelConstruction) ++ " stockholm alignment: " ++ replaceStatus) (tempDirPath staticOptions)- systemCMbuild stockholmFilepath cmFilepath cmBuildFilepath+ systemCMbuild cmBuildOptions stockholmFilepath cmFilepath cmBuildFilepath systemCMcalibrate "fast" (cpuThreads staticOptions) cmFilepath cmCalibrateFilepath return cmFilepath else do@@ -643,7 +666,7 @@ logEither mlocarnaAlignment (tempDirPath staticOptions) let stockholAlignment = convertClustaltoStockholm (fromRight mlocarnaAlignment) writeFile stockholmFilepath stockholAlignment- _ <- systemCMbuild stockholmFilepath cmFilepath cmBuildFilepath+ _ <- systemCMbuild cmBuildOptions stockholmFilepath cmFilepath cmBuildFilepath _ <- systemCMcalibrate "fast" (cpuThreads staticOptions) cmFilepath cmCalibrateFilepath return cmFilepath @@ -740,7 +763,7 @@ filterDuplicates modelConstruction inputSearchResult = uniqueSearchResult where alignedSequences = map snd (V.toList (extractAlignedSequences (iterationNumber modelConstruction) modelConstruction)) collectedIdentifiers = map seqid alignedSequences- uniques = filter (\(s,_,_,_) -> notElem (seqid s) collectedIdentifiers) (candidates inputSearchResult)+ uniques = filter (\(s,_,_) -> notElem (seqid s) collectedIdentifiers) (candidates inputSearchResult) uniqueSearchResult = SearchResult uniques (blastDatabaseSize inputSearchResult) -- | Filter a list of similar extended blast hits @@ -751,35 +774,37 @@ --filterIdenticalSequencesWithOrigin [] _ = [] -- | Filter a list of similar extended blast hits -filterIdenticalSequences :: [(Sequence,Int,String)] -> Double -> [(Sequence,Int,String)] +filterIdenticalSequences :: [(Sequence,Int,L.ByteString)] -> Double -> [(Sequence,Int,L.ByteString)] filterIdenticalSequences (headSequence:rest) identitycutoff = result where filteredSequences = filter (\x -> sequenceIdentity (firstOfTriple headSequence) (firstOfTriple x) < identitycutoff) rest result = headSequence:filterIdenticalSequences filteredSequences identitycutoff filterIdenticalSequences [] _ = [] -- | Filter sequences too similar to already aligned sequences-filterWithCollectedSequences :: [(Sequence,Int,String,Char)] -> [Sequence] -> Double -> [(Sequence,Int,String,Char)] -filterWithCollectedSequences inputCandidates collectedSequences identitycutoff = filter (isUnSimilarSequence collectedSequences identitycutoff . firstOfQuadruple) inputCandidates +filterWithCollectedSequences :: [(Sequence,Int,L.ByteString)] -> [Sequence] -> Double -> [(Sequence,Int,L.ByteString)] +filterWithCollectedSequences inputCandidates collectedSequences identitycutoff = filter (isUnSimilarSequence collectedSequences identitycutoff . firstOfTriple) inputCandidates --filterWithCollectedSequences [] [] _ = [] -- | Filter alignment entries by similiarity +filterIdenticalSequences' :: [Sequence] -> Double -> [Sequence]+filterIdenticalSequences' (headEntry:rest) identitycutoff = result+ where filteredEntries = filter (\ x -> (sequenceIdentity headEntry x) < identitycutoff) rest+ result = headEntry:filterIdenticalSequences' filteredEntries identitycutoff+filterIdenticalSequences' [] _ = []++-- | Filter alignment entries by similiarity filterIdenticalAlignmentEntry :: [ClustalAlignmentEntry] -> Double -> [ClustalAlignmentEntry] filterIdenticalAlignmentEntry (headEntry:rest) identitycutoff = result where filteredEntries = filter (\x -> (stringIdentity (entryAlignedSequence headEntry) (entryAlignedSequence x)) < identitycutoff) rest result = headEntry:filterIdenticalAlignmentEntry filteredEntries identitycutoff filterIdenticalAlignmentEntry [] _ = [] - isUnSimilarSequence :: [Sequence] -> Double -> Sequence -> Bool isUnSimilarSequence collectedSequences identitycutoff checkSequence = any (\ x -> (sequenceIdentity checkSequence x) < identitycutoff) collectedSequences-- + firstOfTriple :: (t, t1, t2) -> t firstOfTriple (a,_,_) = a -firstOfQuadruple :: (t, t1, t2, t3) -> t-firstOfQuadruple (a,_,_,_) = a - -- | Check if the result field of BlastResult is filled and if hits are present blastMatchesPresent :: BlastResult -> Bool blastMatchesPresent blastResult @@ -831,7 +856,7 @@ --the input taxid is not part of the lineage, therefor we look for further taxids in the lineage after we used the parent tax id of the input node parentNodeTaxId = if subTreeTaxId == taxonTaxId taxon then Just (taxonParentTaxId taxon) else linageNodeTaxId -constructNext :: Int -> ModelConstruction -> [(Sequence, Int, String, Char)] -> Maybe Int -> Maybe Taxon -> [String] -> [SearchResult] -> Bool -> ModelConstruction+constructNext :: Int -> ModelConstruction -> [(Sequence,Int,L.ByteString)] -> Maybe Int -> Maybe Taxon -> [String] -> [SearchResult] -> Bool -> ModelConstruction constructNext currentIterationNumber modelconstruction alignmentResults upperTaxLimit inputTaxonomicContext inputSelectedQueries inputPotentialMembers toggleInfernalAlignmentModeTrue = nextModelConstruction where newIterationNumber = currentIterationNumber + 1 taxEntries = taxRecords modelconstruction ++ buildTaxRecords alignmentResults currentIterationNumber@@ -839,25 +864,25 @@ currentAlignmentMode = toggleInfernalAlignmentModeTrue || alignmentModeInfernal modelconstruction nextModelConstruction = ModelConstruction newIterationNumber (inputFasta modelconstruction) taxEntries upperTaxLimit inputTaxonomicContext (evalueThreshold modelconstruction) currentAlignmentMode inputSelectedQueries potMembers -buildTaxRecords :: [(Sequence,Int,String,Char)] -> Int -> [TaxonomyRecord]+buildTaxRecords :: [(Sequence,Int,L.ByteString)] -> Int -> [TaxonomyRecord] buildTaxRecords alignmentResults currentIterationNumber = taxonomyRecords where taxIdGroups = groupBy sameTaxIdAlignmentResult alignmentResults taxonomyRecords = map (buildTaxRecord currentIterationNumber) taxIdGroups -sameTaxIdAlignmentResult :: (Sequence,Int,String,Char) -> (Sequence,Int,String,Char) -> Bool-sameTaxIdAlignmentResult (_,taxId1,_,_) (_,taxId2,_,_) = taxId1 == taxId2+sameTaxIdAlignmentResult :: (Sequence,Int,L.ByteString) -> (Sequence,Int,L.ByteString) -> Bool+sameTaxIdAlignmentResult (_,taxId1,_) (_,taxId2,_) = taxId1 == taxId2 -buildTaxRecord :: Int -> [(Sequence,Int,String,Char)] -> TaxonomyRecord+buildTaxRecord :: Int -> [(Sequence,Int,L.ByteString)] -> TaxonomyRecord buildTaxRecord currentIterationNumber entries = taxRecord- where recordTaxId = (\(_,currentTaxonomyId,_,_) -> currentTaxonomyId) (head entries)+ where recordTaxId = (\(_,currentTaxonomyId,_) -> currentTaxonomyId) (head entries) seqRecords = map (buildSeqRecord currentIterationNumber) entries taxRecord = TaxonomyRecord recordTaxId seqRecords -buildSeqRecord :: Int -> (Sequence,Int,String,Char) -> SequenceRecord -buildSeqRecord currentIterationNumber (parsedFasta,_,seqSubject,seqOrigin) = SequenceRecord parsedFasta currentIterationNumber seqSubject seqOrigin +buildSeqRecord :: Int -> (Sequence,Int,L.ByteString) -> SequenceRecord +buildSeqRecord currentIterationNumber (parsedFasta,_,seqSubject) = SequenceRecord parsedFasta currentIterationNumber seqSubject -- | Partitions sequences by containing a cmsearch hit and extracts the hit region as new sequence-evaluePartitionTrimCMsearchHits :: Double -> [(CMsearch,(Sequence, Int, String, Char))] -> ([(CMsearch,(Sequence, Int, String, Char))],[(CMsearch,(Sequence, Int, String, Char))],[(CMsearch,(Sequence, Int, String, Char))])+evaluePartitionTrimCMsearchHits :: Double -> [(CMsearch,(Sequence, Int, L.ByteString))] -> ([(CMsearch,(Sequence, Int, L.ByteString))],[(CMsearch,(Sequence, Int, L.ByteString))],[(CMsearch,(Sequence, Int, L.ByteString))]) evaluePartitionTrimCMsearchHits eValueThreshold cmSearchCandidatesWithSequences = (trimmedSelectedCandidates,potentialCandidates,rejectedCandidates) where potentialMemberseValueThreshold = eValueThreshold * 1000 (prefilteredCandidates,rejectedCandidates) = partition (\(cmSearchResult,_) -> any (\hitScore' -> potentialMemberseValueThreshold >= hitEvalue hitScore') (cmsearchHits cmSearchResult)) cmSearchCandidatesWithSequences@@ -865,8 +890,8 @@ trimmedSelectedCandidates = map (\(cmSearchResult,inputSequence) -> (cmSearchResult,trimCMsearchHit cmSearchResult inputSequence)) selectedCandidates -trimCMsearchHit :: CMsearch -> (Sequence, Int, String, Char) -> (Sequence, Int, String, Char)-trimCMsearchHit cmSearchResult (inputSequence,b,c,d) = (subSequence,b,c,d)+trimCMsearchHit :: CMsearch -> (Sequence, Int, L.ByteString) -> (Sequence, Int, L.ByteString)+trimCMsearchHit cmSearchResult (inputSequence,b,c) = (subSequence,b,c) where hitScoreEntry = head (cmsearchHits cmSearchResult) sequenceString = L.unpack (unSD (seqdata inputSequence)) sequenceSubstring = cmSearchsubString (hitStart hitScoreEntry) (hitEnd hitScoreEntry) sequenceString@@ -893,9 +918,9 @@ alignedSequences = fastaSeqData:map nucleotideSequence (concatMap sequenceRecords (taxRecords modelconstruction)) querySequences' = concatMap (\querySeqId -> filter (\alignedSeq -> L.unpack (unSL (seqid alignedSeq)) == querySeqId) alignedSequences) querySeqIds -extractQueryCandidates :: [(Sequence,Int,String,Char)] -> V.Vector (Int,Sequence)+extractQueryCandidates :: [(Sequence,Int,L.ByteString)] -> V.Vector (Int,Sequence) extractQueryCandidates querycandidates = indexedSeqences- where sequences = map (\(candidateSequence,_,_,_) -> candidateSequence) querycandidates+ where sequences = map (\(candidateSequence,_,_) -> candidateSequence) querycandidates indexedSeqences = V.map (\(number,candidateSequence) -> (number + 1,candidateSequence))(V.indexed (V.fromList sequences)) buildTaxFilterQuery :: Maybe Int -> Maybe Int -> String@@ -916,6 +941,7 @@ randomid :: Int16 -> String randomid number = "cm" ++ show number +-- | Create session id for RNAlien createSessionID :: Maybe String -> IO String createSessionID sessionIdentificator = do if isJust sessionIdentificator@@ -946,8 +972,8 @@ systemClustalo options (inputFilePath, outputFilePath) = system ("clustalo " ++ options ++ "--infile=" ++ inputFilePath ++ " >" ++ outputFilePath) -- | Run external CMbuild command and read the output into the corresponding datatype -systemCMbuild :: String -> String -> String -> IO ExitCode-systemCMbuild alignmentFilepath modelFilepath outputFilePath = system ("cmbuild " ++ modelFilepath ++ " " ++ alignmentFilepath ++ " > " ++ outputFilePath) +systemCMbuild :: String -> String -> String -> String -> IO ExitCode+systemCMbuild options alignmentFilepath modelFilepath outputFilePath = system ("cmbuild " ++ options ++ " " ++ modelFilepath ++ " " ++ alignmentFilepath ++ " > " ++ outputFilePath) -- | Run CMCompare and read the output into the corresponding datatype systemCMcompare :: String -> String -> String -> IO ExitCode@@ -972,7 +998,7 @@ systemCMalign :: String -> String -> String -> String -> IO ExitCode systemCMalign options filePathCovarianceModel filePathSequence filePathAlignment = system ("cmalign " ++ options ++ " " ++ filePathCovarianceModel ++ " " ++ filePathSequence ++ "> " ++ filePathAlignment) -compareCM :: String -> String -> String -> IO Double+compareCM :: String -> String -> String -> IO (Either String Double) compareCM rfamCMPath resultCMpath outputDirectory = do let myOptions = defaultDecodeOptions { decDelimiter = fromIntegral (ord ' ')@@ -988,7 +1014,7 @@ let bitscore1 = read (decodedCmCompareOutput !! 2) :: Double let bitscore2 = read (decodedCmCompareOutput !! 3) :: Double let minmax = minimum [bitscore1,bitscore2]- return minmax+ return (Right minmax) readInt :: String -> Int readInt = read@@ -996,233 +1022,9 @@ readDouble :: String -> Double readDouble = read --- | parse from input filePath -parseCMSearch :: String -> Either ParseError CMsearch-parseCMSearch = parse genParserCMsearch "parseCMsearch" ---- | parse from input filePath -readCMSearch :: String -> IO (Either ParseError CMsearch) -readCMSearch filePath = do - parsedFile <- parseFromFile genParserCMsearch filePath- CE.evaluate parsedFile - -genParserCMsearch :: GenParser Char st CMsearch-genParserCMsearch = do- string "# cmsearch :: search CM(s) against a sequence database"- newline- string "# INFERNAL "- many1 (noneOf "\n")- newline - string "# Copyright (C) 201"- many1 (noneOf "\n")- newline - string "# Freely distributed under the GNU General Public License (GPLv3)."- newline - string "# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"- newline- string "# query CM file:"- many1 space- queryCMfile' <- many1 (noneOf "\n")- newline- string "# target sequence database:"- many1 space - targetSequenceDatabase' <- many1 (noneOf "\n")- newline- optional (try (genParserCMsearchHeaderField "# CM configuration"))- optional (try (genParserCMsearchHeaderField "# database size is set to"))- optional (try (genParserCMsearchHeaderField "# truncated sequence detection"))- string "# number of worker threads:"- many1 space- numberOfWorkerThreads' <- many1 (noneOf "\n")- newline- string "# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"- newline- optional newline- string "Query:"- many1 (noneOf "\n") - newline- optional (try (genParserCMsearchHeaderField "Accession"))- optional (try (genParserCMsearchHeaderField "Description"))- string "Hit scores:"- newline- choice [try (string " rank"), try (string " rank") , try (string " rank"), try (string " rank"),try (string " rank"),try (string " rank")]- many1 space - string "E-value"- many1 space - string "score"- many1 space - string "bias"- many1 space - string "sequence"- many1 space - string "start"- many1 space - string "end"- many1 space - string "mdl"- many1 space - string "trunc"- many1 space - string "gc"- many1 space - string "description"- newline- string " -"- many1 (try (oneOf " -"))- newline- optional (try (string " ------ inclusion threshold ------"))- many newline- hitScores' <- many (try genParserCMsearchHit) --`endBy` (try (string "Hit alignments:"))- optional (try genParserCMsearchEmptyHit)- -- this is followed by hit alignments and internal cmsearch statistics which are not parsed- many anyChar- eof- return $ CMsearch queryCMfile' targetSequenceDatabase' numberOfWorkerThreads' hitScores'--genParserCMsearchHeaderField :: String -> GenParser Char st String-genParserCMsearchHeaderField fieldname = do- string (fieldname ++ ":")- many1 space- many1 (noneOf "\n")- newline- return []--genParserCMsearchEmptyHit :: GenParser Char st [CMsearchHit]-genParserCMsearchEmptyHit = do- string " [No hits detected that satisfy reporting thresholds]"- newline- optional (try newline)- return []--genParserCMsearchHit :: GenParser Char st CMsearchHit-genParserCMsearchHit = do- many1 space- string "(" - hitRank' <- many1 digit- string ")"- many1 space- hitSignificant' <- choice [char '!', char '?']- many1 space - hitEValue' <- many1 (oneOf "0123456789.e-")- many1 space - hitScore' <- many1 (oneOf "0123456789.e-")- many1 space - hitBias' <- many1 (oneOf "0123456789.e-")- many1 space- hitSequenceHeader' <- many1 (noneOf " ")- many1 space - hitStart' <- many1 digit- many1 space- hitEnd' <- many1 digit- many1 space - hitStrand' <- choice [char '+', char '-', char '.']- many1 space - hitModel' <- many1 letter- many1 space - hitTruncation' <- many1 (choice [alphaNum, char '\''])- many1 space - hitGCcontent' <- many1 (oneOf "0123456789.e-")- many1 space - hitDescription' <- many1 (noneOf "\n") - newline- optional (try (string " ------ inclusion threshold ------"))- optional (try newline)- return $ CMsearchHit (readInt hitRank') hitSignificant' (readDouble hitEValue') (readDouble hitScore') (readDouble hitBias') (L.pack hitSequenceHeader') (readInt hitStart') (readInt hitEnd') hitStrand' (L.pack hitModel') (L.pack hitTruncation') (readDouble hitGCcontent') (L.pack hitDescription')---- | parse from input filePath -parseCMstat :: String -> Either ParseError CMstat-parseCMstat = parse genParserCMstat "parseCMstat"---- | parse from input filePath -readCMstat :: String -> IO (Either ParseError CMstat) -readCMstat filePath = do - parsedFile <- parseFromFile genParserCMstat filePath- CE.evaluate parsedFile - -genParserCMstat :: GenParser Char st CMstat-genParserCMstat = do- string "# cmstat :: display summary statistics for CMs"- newline- string "# INFERNAL "- many1 (noneOf "\n")- newline - string "# Copyright (C) 201"- many1 (noneOf "\n")- newline - string "# Freely distributed under the GNU General Public License (GPLv3)."- newline - string "# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"- newline- char '#'- many1 (char ' ')- string "rel entropy"- newline- char '#'- many1 (char ' ')- many1 (char '-')- newline- char '#'- many1 space - string "idx"- many1 space - string "name"- many1 space - string "accession"- many1 space - string "nseq"- many1 space - string "eff_nseq"- many1 space - string "clen"- many1 space - string "W"- many1 space - string "bps"- many1 space - string "bifs"- many1 space - string "model"- many1 space - string "cm"- many1 space- string "hmm"- newline- string "#"- many1 (try (oneOf " -"))- newline- many1 space - _statIndex <- many1 digit- many1 space- _statName <- many1 letter- many1 space - _statAccession <- many1 (noneOf " ")- many1 space - _statSequenceNumber <- many1 digit- many1 space - _statEffectiveSequences <- many1 (oneOf "0123456789.e-")- many1 space- _statConsensusLength <- many digit- many1 space - _statW <- many1 digit- many1 space- _statBasepaires <- many1 digit- many1 space - _statBifurcations <- many1 digit- many1 space - _statModel <- many1 letter- many1 space - _relativeEntropyCM <- many1 (oneOf "0123456789.e-")- many1 space - _relativeEntropyHMM <- many1 (oneOf "0123456789.e-")- newline- char '#'- newline- eof - return $ CMstat (readInt _statIndex) _statName _statAccession (readInt _statSequenceNumber) (readDouble _statEffectiveSequences) (readInt _statConsensusLength) (readInt _statW) (readInt _statBasepaires) (readInt _statBifurcations) _statModel (readDouble _relativeEntropyCM) (readDouble _relativeEntropyHMM)- -extractCandidateSequences :: [(Sequence,Int,String,Char)] -> V.Vector (Int,Sequence)+extractCandidateSequences :: [(Sequence,Int,L.ByteString)] -> V.Vector (Int,Sequence) extractCandidateSequences candidates' = indexedSeqences- where sequences = map (\(inputSequence,_,_,_) -> inputSequence) candidates'+ where sequences = map (\(inputSequence,_,_) -> inputSequence) candidates' indexedSeqences = V.map (\(number,inputSequence) -> (number + 1,inputSequence))(V.indexed (V.fromList sequences)) extractAlignedSequences :: Int -> ModelConstruction -> V.Vector (Int,Sequence)@@ -1277,9 +1079,8 @@ maxIdentity = fromIntegral (maximum (map (snd . Bio.BlastXML.identity) blastMatches)) coverageStatus = (maxIdentity/(fromIntegral queryLength))* (100 :: Double) >= (80 :: Double) - -- | Wrapper for retrieveFullSequence that rerequests incomplete return sequees-retrieveFullSequences :: StaticOptions -> [(String,Int,Int,String,String,Int,String)] -> IO [(Sequence,Int,String)]+retrieveFullSequences :: StaticOptions -> [(String,Int,Int,String,T.Text,Int,L.ByteString)] -> IO [(Sequence,Int,L.ByteString)] retrieveFullSequences staticOptions requestedSequences = do fullSequences <- mapM (retrieveFullSequence (tempDirPath staticOptions)) requestedSequences if any (isNothing . firstOfTriple) fullSequences@@ -1295,7 +1096,7 @@ CE.evaluate unwrappedRetrievals else CE.evaluate (map (\(x,y,z) -> (fromJust x,y,z)) fullSequences) -retrieveFullSequence :: String -> (String,Int,Int,String,String,Int,String) -> IO (Maybe Sequence,Int,String)+retrieveFullSequence :: String -> (String,Int,Int,String,T.Text,Int,L.ByteString) -> IO (Maybe Sequence,Int,L.ByteString) retrieveFullSequence temporaryDirectoryPath (nucleotideId,seqStart,seqStop,strand,_,taxid,subject') = do let program' = Just "efetch" let database' = Just "nucleotide"@@ -1317,7 +1118,7 @@ then return (Nothing,taxid,subject') else CE.evaluate (Just parsedFasta,taxid,subject') -getRequestedSequenceElement :: Int -> (BlastHit,Int) -> (String,Int,Int,String,String,Int,String)+getRequestedSequenceElement :: Int -> (BlastHit,Int) -> (String,Int,Int,String,T.Text,Int,L.ByteString) getRequestedSequenceElement queryLength (blastHit,taxid) | blastHitIsReverseComplement (blastHit,taxid) = getReverseRequestedSequenceElement queryLength (blastHit,taxid) | otherwise = getForwardRequestedSequenceElement queryLength (blastHit,taxid)@@ -1329,11 +1130,11 @@ firstHSPto = h_to blastMatch isReverse = firstHSPfrom > firstHSPto -getForwardRequestedSequenceElement :: Int -> (BlastHit,Int) -> (String,Int,Int,String,String,Int,String)+getForwardRequestedSequenceElement :: Int -> (BlastHit,Int) -> (String,Int,Int,String,T.Text,Int,L.ByteString) getForwardRequestedSequenceElement queryLength (blastHit,taxid) = (geneIdentifier',startcoordinate,endcoordinate,strand,accession',taxid,subjectBlast)- where accession' = L.unpack (extractAccession blastHit)- subjectBlast = L.unpack (unSL (subject blastHit))- geneIdentifier' = extractGeneId blastHit--+ where accession' = extractAccession blastHit+ subjectBlast = unSL (subject blastHit)+ geneIdentifier' = extractGeneId blastHit blastMatch = head (matches blastHit) blastHitOriginSequenceLength = slength blastHit minHfrom = h_from blastMatch@@ -1372,10 +1173,10 @@ | currentValue > upperBoundry = upperBoundry | otherwise = currentValue -getReverseRequestedSequenceElement :: Int -> (BlastHit,Int) -> (String,Int,Int,String,String,Int,String)+getReverseRequestedSequenceElement :: Int -> (BlastHit,Int) -> (String,Int,Int,String,T.Text,Int,L.ByteString) getReverseRequestedSequenceElement queryLength (blastHit,taxid) = (geneIdentifier',startcoordinate,endcoordinate,strand,accession',taxid,subjectBlast)- where accession' = L.unpack (extractAccession blastHit)- subjectBlast = L.unpack (unSL (subject blastHit)) + where accession' = extractAccession blastHit+ subjectBlast = unSL (subject blastHit) geneIdentifier' = extractGeneId blastHit blastMatch = head (matches blastHit) blastHitOriginSequenceLength = slength blastHit @@ -1572,10 +1373,10 @@ hitTaxIdStrings = map extractTaxIdfromDocumentSummary blastHitSummaries hitTaxIds = map readInt hitTaxIdStrings -extractAccession :: BlastHit -> L.ByteString+extractAccession :: BlastHit -> T.Text extractAccession currentBlastHit = accession'- where splitedFields = DS.splitOn "|" (L.unpack (hitId currentBlastHit))- accession' = L.pack (splitedFields !! 3) + where splitedFields = T.splitOn (T.pack "|") (DTE.decodeUtf8 (L.toStrict (hitId currentBlastHit)))+ accession' = splitedFields !! 3 extractGeneId :: BlastHit -> String extractGeneId currentBlastHit = nucleotideId@@ -1615,10 +1416,12 @@ logEither (Left logoutput) temporaryDirectoryPath = appendFile (temporaryDirectoryPath ++ "Log") (show logoutput) logEither _ _ = return () -checkTools :: [String] -> String -> IO (Either String String)-checkTools tools temporaryDirectoryPath = do+checkTools :: [String] -> String -> String -> IO (Either String String)+checkTools tools temporaryDirectoryPath selectedQuerySelectionMethod = do+ -- if queryselectionmethod is set to clustering then also check for clustal omega+ let additionaltools = if selectedQuerySelectionMethod == "clustering" then tools ++ ["clustalo"] else tools -- check if all tools are available via PATH or Left- checks <- mapM checkTool tools+ checks <- mapM checkTool additionaltools if not (null (lefts checks)) then return (Left (concat (lefts checks))) else do @@ -1666,35 +1469,45 @@ | verbosityLevel == Loud = True | otherwise = False -evaluateConstructionResult :: StaticOptions -> Int -> IO String-evaluateConstructionResult staticOptions entryNumber = do+evaluateConstructionResult :: StaticOptions -> ModelConstruction -> IO String+evaluateConstructionResult staticOptions mCResult = do let evaluationDirectoryFilepath = tempDirPath staticOptions ++ "evaluation/" createDirectoryIfMissing False evaluationDirectoryFilepath let fastaFilepath = tempDirPath staticOptions ++ "result.fa" let clustalFilepath = evaluationDirectoryFilepath ++ "result.clustal" let reformatedClustalPath = evaluationDirectoryFilepath ++ "result.clustal.reformated" let cmFilepath = tempDirPath staticOptions ++ "result.cm"+ let resultSequences = map nucleotideSequence (concatMap sequenceRecords (taxRecords mCResult))+ let resultNumber = length resultSequences + 1 + let rnaCentralQueries = map buildSequenceViaMD5Query resultSequences + rnaCentralEntries <- getRNACentralEntries rnaCentralQueries+ let rnaCentralEvaluationResult = showRNAcentralAlienEvaluation rnaCentralEntries+ writeFile (tempDirPath staticOptions ++ "result.rnacentral") rnaCentralEvaluationResult systemCMalign ("--outformat=Clustal --cpu " ++ show (cpuThreads staticOptions)) cmFilepath fastaFilepath clustalFilepath let resultModelStatistics = tempDirPath staticOptions ++ "result.cmstat" systemCMstat cmFilepath resultModelStatistics inputcmStat <- readCMstat resultModelStatistics let cmstatString = cmstatEvalOutput inputcmStat- if entryNumber > 1+ if resultNumber > 1 then do let resultRNAz = tempDirPath staticOptions ++ "result.rnaz"- rnazClustalpath <- preprocessClustalForRNAzExternal clustalFilepath reformatedClustalPath+ let resultRNAcode = tempDirPath staticOptions ++ "result.rnacode"+ rnazClustalpath <- preprocessClustalForRNAcodeExternal clustalFilepath reformatedClustalPath if isRight rnazClustalpath then do systemRNAz "-l" (fromRight rnazClustalpath) resultRNAz inputRNAz <- readRNAz resultRNAz let rnaZString = rnaZEvalOutput inputRNAz- return ("\nEvaluation of RNAlien result :\nCMstat statistics for result.cm\n" ++ cmstatString ++ "\nRNAz statistics for result alignment: " ++ rnaZString)+ RC.systemRNAcode " -t " (fromRight rnazClustalpath) resultRNAcode+ inputRNAcode <- RC.readRNAcodeTabular resultRNAcode+ let rnaCodeString = rnaCodeEvalOutput inputRNAcode+ return ("\nEvaluation of RNAlien result :\nCMstat statistics for result.cm\n" ++ cmstatString ++ "\nRNAz statistics for result alignment: " ++ rnaZString ++ "\nRNAcode output for result alignment:\n" ++ rnaCodeString ++ "\nSequences found by RNAlien with RNAcentral entry:\n" ++ rnaCentralEvaluationResult) else do logWarning ("Running RNAz for result evalution encountered a problem:" ++ fromLeft rnazClustalpath) (tempDirPath staticOptions) - return ("\nEvaluation of RNAlien result :\nCMstat statistics for result.cm\n" ++ cmstatString ++ "\nRNAz statistics for result alignment: Running RNAz for result evalution encountered a problem\n" ++ fromLeft rnazClustalpath)+ return ("\nEvaluation of RNAlien result :\nCMstat statistics for result.cm\n" ++ cmstatString ++ "\nRNAz statistics for result alignment: Running RNAz for result evalution encountered a problem\n" ++ fromLeft rnazClustalpath ++ "\n" ++ "Sequences found by RNAlien with RNAcentral entry:\n" ++ rnaCentralEvaluationResult) else do logWarning "Message: RNAlien could not find additional covariant sequences\n Could not run RNAz statistics. Could not run RNAz statistics with a single sequence.\n" (tempDirPath staticOptions) - return ("\nEvaluation of RNAlien result :\nCMstat statistics for result.cm\n" ++ cmstatString ++ "\nRNAlien could not find additional covariant sequences. Could not run RNAz statistics with a single sequence.\n")+ return ("\nEvaluation of RNAlien result :\nCMstat statistics for result.cm\n" ++ cmstatString ++ "\nRNAlien could not find additional covariant sequences. Could not run RNAz statistics with a single sequence.\n\nSequences found by RNAlien with RNAcentral entry:\n" ++ rnaCentralEvaluationResult) cmstatEvalOutput :: Either ParseError CMstat -> String @@ -1711,27 +1524,54 @@ where rnaZ = fromRight inputRNAz rnazString = " Mean pairwise identity: " ++ show (meanPairwiseIdentity rnaZ) ++ "\n Shannon entropy: " ++ show (shannonEntropy rnaZ) ++ "\n GC content: " ++ show (gcContent rnaZ) ++ "\n Mean single sequence minimum free energy: " ++ show (meanSingleSequenceMinimumFreeEnergy rnaZ) ++ "\n Consensus minimum free energy: " ++ show (consensusMinimumFreeEnergy rnaZ) ++ "\n Energy contribution: " ++ show (energyContribution rnaZ) ++ "\n Covariance contribution: " ++ show (covarianceContribution rnaZ) ++ "\n Combinations pair: " ++ show (combinationsPair rnaZ) ++ "\n Mean z-score: " ++ show (meanZScore rnaZ) ++ "\n Structure conservation index: " ++ show (structureConservationIndex rnaZ) ++ "\n Background model: " ++ backgroundModel rnaZ ++ "\n Decision model: " ++ decisionModel rnaZ ++ "\n SVM decision value: " ++ show (svmDecisionValue rnaZ) ++ "\n SVM class propability: " ++ show (svmRNAClassProbability rnaZ) ++ "\n Prediction: " ++ prediction rnaZ +rnaCodeEvalOutput :: Either ParseError RC.RNAcode -> String +rnaCodeEvalOutput inputRNAcode + | isRight inputRNAcode = rnaCodeString+ | otherwise = show (fromLeft inputRNAcode)+ where rnaCode = fromRight inputRNAcode+ rnaCodeString = "HSS\tFrame\tLength\tFrom\tTo\tName\tStart\tEnd\tScore\tP\n" ++ rnaCodeEntries+ rnaCodeEntries = concatMap showRNACodeHits (RC.rnacodeHits rnaCode)++showRNACodeHits :: RC.RNAcodeHit -> String+showRNACodeHits rnacodeHit = show (RC.hss rnacodeHit) ++ "\t" ++ show (RC.frame rnacodeHit) ++ "\t" ++ show (RC.length rnacodeHit) ++ "\t"++ show (RC.from rnacodeHit) ++ "\t" ++ show (RC.to rnacodeHit) ++ "\t" ++ (RC.name rnacodeHit) ++ "\t" ++ show (RC.start rnacodeHit) ++ "\t" ++ show (RC.end rnacodeHit) ++ "\t" ++ show (RC.score rnacodeHit) ++ show (RC.pvalue rnacodeHit) ++ "\n"+ -- | Call for external preprocessClustalForRNAz preprocessClustalForRNAzExternal :: String -> String -> IO (Either String String) preprocessClustalForRNAzExternal clustalFilepath reformatedClustalPath = do- clustalString <- readFile clustalFilepath+ clustalText <- TI.readFile clustalFilepath --change clustal format for rnazSelectSeqs.pl- let reformatedClustalString = map reformatAln clustalString- writeFile reformatedClustalPath reformatedClustalString+ let reformatedClustalText = T.map reformatAln clustalText+ TI.writeFile reformatedClustalPath reformatedClustalText --select representative entries from result.Clustal with select_sequences let selectedClustalpath = clustalFilepath ++ ".selected" system ("rnazSelectSeqs.pl " ++ reformatedClustalPath ++ " >" ++ selectedClustalpath) return (Right selectedClustalpath) +-- | Call for external preprocessClustalForRNAcode - RNAcode additionally to RNAz requirements does not accept pipe,underscore, doublepoint symbols+preprocessClustalForRNAcodeExternal :: String -> String -> IO (Either String String)+preprocessClustalForRNAcodeExternal clustalFilepath reformatedClustalPath = do+ clustalText <- TI.readFile clustalFilepath+ --change clustal format for rnazSelectSeqs.pl+ let clustalTextLines = T.lines clustalText+ let headerClustalTextLines = T.unlines (take 2 clustalTextLines)+ let headerlessClustalTextLines = T.unlines (drop 2 clustalTextLines)+ let reformatedClustalText = T.map reformatRNACodeAln headerlessClustalTextLines+ TI.writeFile reformatedClustalPath (headerClustalTextLines `T.append` (T.singleton '\n') `T.append` reformatedClustalText)+ --select representative entries from result.Clustal with select_sequences+ let selectedClustalpath = clustalFilepath ++ ".selected"+ system ("rnazSelectSeqs.pl " ++ reformatedClustalPath ++ " >" ++ selectedClustalpath)+ return (Right selectedClustalpath)+ -- | RNAz can process 500 sequences at max. Using rnazSelectSeqs to isolate representative sample. rnazSelectSeqs only accepts - gap characters, alignment is reformatted accordingly. preprocessClustalForRNAz :: String -> String -> IO (Either String String) preprocessClustalForRNAz clustalFilepath reformatedClustalPath = do- clustalString <- readFile clustalFilepath- if length (lines clustalString) > 500+ clustalText <- TI.readFile clustalFilepath+ let clustalTextLines = T.lines clustalText+ if length clustalTextLines > 500 then do --change clustal format for rnazSelectSeqs.pl- let reformatedClustalString = map reformatAln clustalString- writeFile reformatedClustalPath reformatedClustalString+ let reformatedClustalString = T.map reformatAln clustalText+ TI.writeFile reformatedClustalPath reformatedClustalString --select representative entries from result.Clustal with select_sequences let selectedClustalpath = clustalFilepath ++ ".selected" parsedClustalInput <- readClustalAlignment clustalFilepath@@ -1743,6 +1583,7 @@ else return (Left (show (fromLeft parsedClustalInput))) else return (Right clustalFilepath) + -- Iteratively removes sequences with decreasing similarity until target number of alignment entries is reached. rnaZSelectSeqs :: ClustalAlignment -> Int -> Double -> ClustalAlignment rnaZSelectSeqs currentClustalAlignment targetEntries identityCutoff@@ -1751,7 +1592,21 @@ where numberOfEntries = length (alignmentEntries currentClustalAlignment) filteredEntries = filterIdenticalAlignmentEntry (alignmentEntries currentClustalAlignment) identityCutoff filteredAlignment = ClustalAlignment filteredEntries (conservationTrack currentClustalAlignment)- ++reformatRNACodeAln :: Char -> Char +reformatRNACodeAln c+ | c == ':' = '-'+ | c == '|' = '-'+ | c == '.' = '-'+ | c == '~' = '-'+ | c == '_' = '-'+ | c == 'u' = 'U'+ | c == 't' = 'T'+ | c == 'g' = 'G'+ | c == 'c' = 'C'+ | c == 'a' = 'A'+ | otherwise = c+ reformatAln :: Char -> Char reformatAln c | c == '.' = '-'
src/Bio/RNAlienStatistics.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE DeriveDataTypeable #-} -- | Statistics for RNAlien Results--- dist/build/RNAlienStatistics/RNAlienStatistics -i /scratch/egg/temp/cm13676/1/model.cm -r /home/mescalin/egg/current/Data/AlienTest/cms/BsrG.cm -g /scratch/egg/temp/AlienSearch/genomes/ -o /scratch/egg/temp/AlienStatistics+-- dist/build/RNAlienStatistics/RNAlienStatistics -s bitscore -i /scratch/egg/temp/cm13676/1/model.cm -r /home/mescalin/egg/current/Data/AlienTest/cms/BsrG.cm -g /scratch/egg/temp/AlienSearch/genomes/ -o /scratch/egg/temp/AlienStatistics module Main where import System.Console.CmdArgs @@ -32,6 +32,8 @@ alienThreshold :: Double, outputDirectoryPath :: String, benchmarkIndex :: Int,+ thresholdSelection :: String,+ linkScores :: Bool, threads :: Int } deriving (Show,Data,Typeable) @@ -49,14 +51,16 @@ alienThreshold = 20 &= name "t" &= help "Bitscore threshold for RNAlien model hits on Rfam fasta, default 20", rfamThreshold = 20 &= name "x" &= help "Bitscore threshold for Rfam model hits on Alien fasta, default 20", benchmarkIndex = 1 &= name "b" &= help "Index used to identify sRNA tagged RNA families",+ thresholdSelection = "bitscore" &= name "s" &= help "Selection method, (bitscore, evalue), default bitscore",+ linkScores = False &= name "l" &= help "Triggers computation of linkscores via CMCompare", threads = 1 &= name "c" &= help "Number of available cpu slots/cores, default 1"- } &= summary "RNAlienStatistics devel version" &= help "Florian Eggenhofer - >2013" &= verbosity + } &= summary "RNAlienStatistics" &= help "Florian Eggenhofer - >2013" &= verbosity --cmSearchFasta threads rfamCovarianceModelPath outputDirectoryPath "Rfam" False genomesDirectoryPath-cmSearchFasta :: Int -> Double -> Int -> String -> String -> String -> String -> IO [CMsearchHit]-cmSearchFasta benchmarkIndex thresholdScore cpuThreads covarianceModelPath outputDirectory modelType fastapath = do+cmSearchFasta :: Int -> String -> Double -> Int -> String -> String -> String -> String -> IO [CMsearchHit]+cmSearchFasta benchmarkIndex thresholdSelection thresholdScore cpuThreads covarianceModelPath outputDirectory modelType fastapath = do createDirectoryIfMissing False (outputDirectory ++ "/" ++ modelType)- _ <- systemCMsearch cpuThreads "" covarianceModelPath fastapath (outputDirectory ++ "/" ++ modelType ++ "/" ++ (show benchmarkIndex) ++ ".cmsearch")+ _ <- systemCMsearch cpuThreads " -Z 1000 " covarianceModelPath fastapath (outputDirectory ++ "/" ++ modelType ++ "/" ++ (show benchmarkIndex) ++ ".cmsearch") result <- readCMSearch (outputDirectory ++ "/" ++ modelType ++ "/" ++ (show benchmarkIndex) ++ ".cmsearch") if (isLeft result) then do@@ -64,14 +68,40 @@ return [] else do let rightResults = fromRight result- let (significantHits,_) = partitionCMsearchHitsByScore thresholdScore rightResults+ let significantHits = filterCMsearchHits thresholdSelection thresholdScore rightResults let organismUniquesignificantHits = nubBy cmSearchSameOrganism significantHits return organismUniquesignificantHits -partitionCMsearchHitsByScore :: Double -> CMsearch -> ([CMsearchHit],[CMsearchHit])-partitionCMsearchHitsByScore thresholdScore cmSearchResult = (selected,rejected)- where (selected,rejected) = partition (\hit -> hitScore hit >= thresholdScore) (cmsearchHits cmSearchResult)+--cmSearchFasta threads rfamCovarianceModelPath outputDirectoryPath "Rfam" False genomesDirectoryPath+cmSearchesFasta :: Int -> String -> Double -> Int -> String -> String -> String -> String -> IO [CMsearchHit]+cmSearchesFasta benchmarkIndex thresholdSelection thresholdScore cpuThreads covarianceModelPath outputDirectory modelType fastapath = do+ createDirectoryIfMissing False (outputDirectory ++ "/" ++ modelType)+ _ <- systemCMsearch cpuThreads " -Z 1000 " covarianceModelPath fastapath (outputDirectory ++ "/" ++ modelType ++ "/" ++ (show benchmarkIndex) ++ ".cmsearch")+ result <- readCMSearches (outputDirectory ++ "/" ++ modelType ++ "/" ++ (show benchmarkIndex) ++ ".cmsearch")+ if (isLeft result)+ then do+ print (fromLeft result)+ return []+ else do+ let rightResults = fromRight result+ let significantHits = filterCMsearchHits thresholdSelection thresholdScore rightResults+ let organismUniquesignificantHits = nubBy cmSearchSameOrganism significantHits+ return organismUniquesignificantHits +filterCMsearchHits :: String -> Double -> CMsearch -> [CMsearchHit]+filterCMsearchHits thresholdSelection thresholdScore cmSearchResult+ | thresholdSelection == "bitscore" = bitscorefiltered+ | otherwise = evaluefiltered+ where bitscorefiltered = filter (\hit -> hitScore hit >= thresholdScore) (cmsearchHits cmSearchResult)+ evaluefiltered = filter (\hit -> hitEvalue hit <= thresholdScore) (cmsearchHits cmSearchResult)++partitionCMsearchHits :: String -> Double -> CMsearch -> ([CMsearchHit],[CMsearchHit])+partitionCMsearchHits thresholdSelection thresholdScore cmSearchResult+ | thresholdSelection == "bitscore" = (bitscoreselected,bitscorerejected)+ | otherwise = (evalueselected,evaluerejected)+ where (bitscoreselected,bitscorerejected) = partition (\hit -> hitScore hit >= thresholdScore) (cmsearchHits cmSearchResult)+ (evalueselected,evaluerejected) = partition (\hit -> hitEvalue hit <= thresholdScore) (cmsearchHits cmSearchResult)+ trimCMsearchFastaFile :: String -> String -> String -> CMsearch -> String -> IO () trimCMsearchFastaFile genomesDirectory outputFolder modelType cmsearch fastafile = do let fastaInputPath = genomesDirectory ++ "/" ++ fastafile@@ -114,17 +144,19 @@ if rfamModelExists then do --compute linkscore- linkscore <- compareCM rfamCovarianceModelPath alienCovarianceModelPath outputDirectoryPath- rfamMaxLinkScore <- compareCM rfamCovarianceModelPath rfamCovarianceModelPath outputDirectoryPath- alienMaxLinkscore <- compareCM alienCovarianceModelPath alienCovarianceModelPath outputDirectoryPath+ linkscore <- if linkScores+ then compareCM rfamCovarianceModelPath alienCovarianceModelPath outputDirectoryPath+ else return (Left "-")+ rfamMaxLinkScore <- if linkScores then compareCM rfamCovarianceModelPath rfamCovarianceModelPath outputDirectoryPath else return (Left "-")+ alienMaxLinkscore <- if linkScores then compareCM alienCovarianceModelPath alienCovarianceModelPath outputDirectoryPath else return (Left "-") _ <- system ("cat " ++ rfamFastaFilePath ++ " | grep '>' | wc -l >" ++ outputDirectoryPath ++ FP.takeFileName rfamFastaFilePath ++ ".entries") _ <- system ("cat " ++ alienFastaFilePath ++ " | grep '>' | wc -l >" ++ outputDirectoryPath ++ FP.takeFileName alienFastaFilePath ++ ".entries") rfamFastaEntries <- readFile (outputDirectoryPath ++ FP.takeFileName rfamFastaFilePath ++ ".entries") alienFastaEntries <- readFile (outputDirectoryPath ++ FP.takeFileName alienFastaFilePath ++ ".entries") let rfamFastaEntriesNumber = read rfamFastaEntries :: Int let alienFastaEntriesNumber = read alienFastaEntries :: Int- rfamonAlienResults <- cmSearchFasta benchmarkIndex rfamThreshold threads rfamCovarianceModelPath outputDirectoryPath "rfamOnAlien" alienFastaFilePath - alienonRfamResults <- cmSearchFasta benchmarkIndex alienThreshold threads alienCovarianceModelPath outputDirectoryPath "alienOnRfam" rfamFastaFilePath + rfamonAlienResults <- cmSearchesFasta benchmarkIndex thresholdSelection rfamThreshold threads rfamCovarianceModelPath outputDirectoryPath "rfamOnAlien" alienFastaFilePath + alienonRfamResults <- cmSearchFasta benchmarkIndex thresholdSelection alienThreshold threads alienCovarianceModelPath outputDirectoryPath "alienOnRfam" rfamFastaFilePath let rfamonAlienResultsNumber = length rfamonAlienResults let alienonRfamResultsNumber = length alienonRfamResults let rfamonAlienRecovery = (fromIntegral rfamonAlienResultsNumber :: Double) / (fromIntegral alienFastaEntriesNumber :: Double)@@ -134,9 +166,9 @@ putStrLn ("BenchmarkIndex: " ++ show benchmarkIndex) putStrLn ("RfamModelName: " ++ rfamModelName) putStrLn ("RfamModelId: " ++ rfamModelId)- putStrLn ("Linkscore: " ++ show linkscore)- putStrLn ("rfamMaxLinkScore: " ++ show rfamMaxLinkScore)- putStrLn ("alienMaxLinkscore: " ++ show alienMaxLinkscore) + putStrLn ("Linkscore: " ++ (either id show linkscore))+ putStrLn ("rfamMaxLinkScore: " ++ (either id show rfamMaxLinkScore))+ putStrLn ("alienMaxLinkscore: " ++ (either id show alienMaxLinkscore)) putStrLn ("rfamGatheringThreshold: " ++ show rfamThreshold) putStrLn ("alienGatheringThreshold: " ++ show alienThreshold) putStrLn ("rfamFastaEntriesNumber: " ++ show rfamFastaEntriesNumber)@@ -148,24 +180,13 @@ print rnazString print cmStatString else do- putStrLn (show benchmarkIndex ++ "\t" ++ rfamModelName ++ "\t" ++ rfamModelId ++ "\t" ++ show linkscore ++ "\t" ++ show rfamMaxLinkScore ++ "\t" ++ show alienMaxLinkscore ++ "\t" ++ show rfamThreshold ++ "\t" ++ show alienThreshold ++ "\t" ++ show rfamFastaEntriesNumber ++ "\t" ++ show alienFastaEntriesNumber ++ "\t" ++ show rfamonAlienResultsNumber ++ "\t" ++ show alienonRfamResultsNumber ++ "\t" ++ printf "%.2f" rfamonAlienRecovery ++ "\t" ++ printf "%.2f" alienonRfamRecovery ++ "\t" ++ rnazString ++ "\t" ++ cmStatString)+ putStrLn (show benchmarkIndex ++ "\t" ++ rfamModelName ++ "\t" ++ rfamModelId ++ "\t" ++ (either id show linkscore) ++ "\t" ++ (either id show rfamMaxLinkScore) ++ "\t" ++ (either id show alienMaxLinkscore) ++ "\t" ++ show rfamThreshold ++ "\t" ++ show alienThreshold ++ "\t" ++ show rfamFastaEntriesNumber ++ "\t" ++ show alienFastaEntriesNumber ++ "\t" ++ show rfamonAlienResultsNumber ++ "\t" ++ show alienonRfamResultsNumber ++ "\t" ++ printf "%.2f" rfamonAlienRecovery ++ "\t" ++ printf "%.2f" alienonRfamRecovery ++ "\t" ++ rnazString ++ "\t" ++ cmStatString) else do --compute linkscore- --linkscore <- compareCM rfamCovarianceModelPath alienCovarianceModelPath outputDirectoryPath- --rfamMaxLinkScore <- compareCM rfamCovarianceModelPath rfamCovarianceModelPath outputDirectoryPath- alienMaxLinkscore <- compareCM alienCovarianceModelPath alienCovarianceModelPath outputDirectoryPath- --_ <- system ("cat " ++ rfamFastaFilePath ++ " | grep '>' | wc -l >" ++ outputDirectoryPath ++ FP.takeFileName rfamFastaFilePath ++ ".entries")+ alienMaxLinkscore <- if linkScores then compareCM alienCovarianceModelPath alienCovarianceModelPath outputDirectoryPath else return ( Left "-") _ <- system ("cat " ++ alienFastaFilePath ++ " | grep '>' | wc -l >" ++ outputDirectoryPath ++ FP.takeFileName alienFastaFilePath ++ ".entries")- --rfamFastaEntries <- readFile (outputDirectoryPath ++ FP.takeFileName rfamFastaFilePath ++ ".entries") alienFastaEntries <- readFile (outputDirectoryPath ++ FP.takeFileName alienFastaFilePath ++ ".entries") - --let rfamFastaEntriesNumber = read rfamFastaEntries :: Int- let alienFastaEntriesNumber = read alienFastaEntries :: Int- --rfamonAlienResults <- cmSearchFasta benchmarkIndex rfamThreshold threads rfamCovarianceModelPath outputDirectoryPath "rfamOnAlien" alienFastaFilePath - --alienonRfamResults <- cmSearchFasta benchmarkIndex alienThreshold threads alienCovarianceModelPath outputDirectoryPath "alienOnRfam" rfamFastaFilePath - --let rfamonAlienResultsNumber = length rfamonAlienResults- --let alienonRfamResultsNumber = length alienonRfamResults- --let rfamonAlienRecovery = (fromIntegral rfamonAlienResultsNumber :: Double) / (fromIntegral alienFastaEntriesNumber :: Double)- --let alienonRfamRecovery = (fromIntegral alienonRfamResultsNumber :: Double) / (fromIntegral rfamFastaEntriesNumber :: Double) + let alienFastaEntriesNumber = read alienFastaEntries :: Int if (verbose == Loud) then do putStrLn ("BenchmarkIndex:")@@ -173,7 +194,7 @@ putStrLn ("RfamModelId: -") putStrLn ("Linkscore: -") putStrLn ("rfamMaxLinkScore: -")- putStrLn ("alienMaxLinkscore: " ++ show alienMaxLinkscore) + putStrLn ("alienMaxLinkscore: " ++ (either id show alienMaxLinkscore)) putStrLn ("rfamGatheringThreshold: -") putStrLn ("alienGatheringThreshold: -") putStrLn ("rfamFastaEntriesNumber: -")@@ -185,7 +206,7 @@ print rnazString print cmStatString else do- putStrLn (show benchmarkIndex ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ show alienMaxLinkscore ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ show alienFastaEntriesNumber ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ rnazString ++ "\t" ++ cmStatString)+ putStrLn (show benchmarkIndex ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ (either id show alienMaxLinkscore) ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ show alienFastaEntriesNumber ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ "-" ++ "\t" ++ rnazString ++ "\t" ++ cmStatString) rnazOutput :: Verbosity -> String -> IO String rnazOutput verbose rnazPath = do