Biobase 0.1.0.1 → 0.3.1.0
raw patch · 52 files changed
+3502/−2154 lines, 52 filesdep +deepseqdep +either-unwrapdep +filepathdep ~PrimitiveArray
Dependencies added: deepseq, either-unwrap, filepath, ghc-prim, mtl, utility-ht, vector-read-instances, zlib
Dependency ranges changed: PrimitiveArray
Files
- Biobase.cabal +72/−42
- Biobase/Constants.hs +14/−12
- Biobase/DataSource/CT.hs +38/−0
- Biobase/DataSource/CT/Import.hs +64/−0
- Biobase/DataSource/DotParen.hs +18/−0
- Biobase/DataSource/DotParen/Import.hs +113/−0
- Biobase/DataSource/FR3D.hs +120/−0
- Biobase/DataSource/FR3D/Import.hs +92/−0
- Biobase/DataSource/InfernalCM.hs +326/−0
- Biobase/DataSource/InfernalCM/Export.hs +76/−0
- Biobase/DataSource/InfernalCM/Import.hs +197/−0
- Biobase/DataSource/MCFold.hs +190/−0
- Biobase/DataSource/MCFold/Conversions.hs +58/−0
- Biobase/DataSource/MCFold/Import.hs +226/−0
- Biobase/DataSource/Mafft.hs +50/−0
- Biobase/DataSource/Mafft/Import.hs +74/−0
- Biobase/DataSource/Turner.hs +41/−0
- Biobase/DataSource/Turner/Import.hs +176/−0
- Biobase/DataSource/Turner/Tables.hs +133/−0
- Biobase/DataSource/Vienna.hs +96/−0
- Biobase/DataSource/Vienna/Default.hs +27/−0
- Biobase/DataSource/Vienna/Export/ViennaC.hs +264/−0
- Biobase/DataSource/Vienna/Export/ViennaPar.hs +140/−0
- Biobase/DataSource/Vienna/Import/Turner.hs +72/−0
- Biobase/DataSource/Vienna/Import/ViennaPar.hs +124/−0
- Biobase/DataSource/Vienna/Modification/NonStandard.hs +122/−0
- Biobase/DataSource/Vienna/Modification/Partition.hs +51/−0
- Biobase/DataSource/Vienna/Modification/Temperature.hs +34/−0
- Biobase/Infernal/CM.hs +0/−326
- Biobase/Infernal/CM/Export.hs +0/−76
- Biobase/Infernal/CM/Import.hs +0/−194
- Biobase/Infernal/Stockholm.hs +0/−16
- Biobase/Infernal/Stockholm/Import.hs +0/−35
- Biobase/RNA.hs +99/−178
- Biobase/RNA/Complex.hs +72/−0
- Biobase/RNA/Hashes.hs +32/−0
- Biobase/RNA/NucBounds.hs +54/−0
- Biobase/RNA/Pairs.hs +124/−0
- Biobase/RNA/ViennaPair.hs +108/−0
- Biobase/Turner.hs +0/−41
- Biobase/Turner/Import.hs +0/−176
- Biobase/Turner/Tables.hs +0/−133
- Biobase/Vienna.hs +0/−89
- Biobase/Vienna/Default.hs +0/−27
- Biobase/Vienna/Export/ViennaC.hs +0/−264
- Biobase/Vienna/Export/ViennaPar.hs +0/−139
- Biobase/Vienna/Import/Turner.hs +0/−71
- Biobase/Vienna/Import/ViennaPar.hs +0/−123
- Biobase/Vienna/Modification/NonStandard.hs +0/−121
- Biobase/Vienna/Modification/Partition.hs +0/−51
- Biobase/Vienna/Modification/Temperature.hs +0/−34
- templates/cheader +5/−6
Biobase.cabal view
@@ -1,9 +1,9 @@ name: Biobase-version: 0.1.0.1+version: 0.3.1.0 author: Christian Hoener zu Siederdissen maintainer: choener@tbi.univie.ac.at-homepage: http://www.tbi.univie.ac.at/~choener/Haskell/-copyright: Christian Hoener zu Siederdissen, 2010+homepage: http://www.tbi.univie.ac.at/~choener/+copyright: Christian Hoener zu Siederdissen, 2010,2011 category: Bioinformatics synopsis: Base library for bioinformatics license: GPL-3@@ -14,49 +14,53 @@ description: Base library for bioinformatics providing the following features: .- * RNA primary and secondary structure+ RNA sequences and energy files: .- * Infernal covariance models+ * efficient format for RNA sequences, based on the vector package .- * Turner and Vienna energy files+ * internal conversion from strings and bytestrings .+ * secondary structure manipulation functions, im- and export of Vienna-dotbracket notation . .- RNA sequences and energy files: .- * efficient format for RNA sequences, based on the vector package+ Utility classes: .- * import from strings, bytestrings, fasta files (using the bio library)+ * algebraic ring class .- * secondary structure manipulation functions, im- and export of Vienna-dotbracket notation+ * instances for Gibbs free energy, partition function probabilities, and scores .- * import Turner energy files+ * conversion between different entities .- * cf. http://rna.urmc.rochester.edu/NNDB/index.html .- * im- and export of Vienna 2.0 energy files .+ Bioinformatics data sources: .+ * mostly just imports, some export functions are provided .- Covariance models:+ * Fasta (please use the "bio" library by Ketil Malde) .- * import covariance models+ * Mafft .- * basic manipulation of covariance models+ * RNA secondary structure: Dot-Bracket, CT .- * Stockholm file format manipulation+ * ViennaRNA energy files (with default parameters) .+ * Turner energy files: cf. <http://rna.urmc.rochester.edu/NNDB/index.html> .+ * RNAstrand database: dot-parenthesis (one file, many entries) .- Utility classes:+ * FR3D: basepairs .- * algebraic ring class+ * Infernal: covariance models (text-based) .- * instances for Gibbs free energy, partition function probabilities, and scores+ * MC-Fold: NCM database .- * conversion between different entities .- * ready for the vector library+ .+ Important notes:+ .+ * In general, this library is not unicode safe (and could somebody tell me the reason for encoding DNA/RNA sequences in unicode?) @@ -68,49 +72,75 @@ build-depends: array, base >=4 && <5,+ ghc-prim, bytestring, containers,+ deepseq, directory >=1, file-embed >=0.0.3, filemanip >=0.3.3 && <0.4,+ filepath,+ mtl, parsec >=3 && <4, primitive >=0.3 && <0.4,+ split >=0.1.2.3, tuple >=0.2.0.1,+ utility-ht, vector >=0.7 && <0.8,- split >=0.1.2.3,+ zlib,+ either-unwrap, HsTools >=0.0.1.1 && <0.0.2, ParsecTools >=0.0.2 && <0.0.3,- PrimitiveArray >=0.0.2.1 && <0.0.3+ PrimitiveArray >=0.0.3.1 && <0.0.4,+ vector-read-instances exposed-modules: Biobase.Constants- Biobase.Infernal.CM- Biobase.Infernal.CM.Export- Biobase.Infernal.CM.Import- Biobase.Infernal.Stockholm- Biobase.Infernal.Stockholm.Import+ Biobase.DataSource.CT+ Biobase.DataSource.CT.Import+ Biobase.DataSource.DotParen+ Biobase.DataSource.DotParen.Import+ Biobase.DataSource.FR3D+ Biobase.DataSource.FR3D.Import+ Biobase.DataSource.InfernalCM+ Biobase.DataSource.InfernalCM.Export+ Biobase.DataSource.InfernalCM.Import+ Biobase.DataSource.Mafft+ Biobase.DataSource.Mafft.Import+ Biobase.DataSource.MCFold+ Biobase.DataSource.MCFold.Conversions+ Biobase.DataSource.MCFold.Import+ Biobase.DataSource.Turner+ Biobase.DataSource.Turner.Import+ Biobase.DataSource.Turner.Tables+ Biobase.DataSource.Vienna+ Biobase.DataSource.Vienna.Default+ Biobase.DataSource.Vienna.Export.ViennaC+ Biobase.DataSource.Vienna.Export.ViennaPar+ Biobase.DataSource.Vienna.Import.Turner+ Biobase.DataSource.Vienna.Import.ViennaPar+ Biobase.DataSource.Vienna.Modification.NonStandard+ Biobase.DataSource.Vienna.Modification.Partition+ Biobase.DataSource.Vienna.Modification.Temperature Biobase.RNA+ Biobase.RNA.Complex+ Biobase.RNA.Hashes+ Biobase.RNA.NucBounds+ Biobase.RNA.Pairs+ Biobase.RNA.ViennaPair Biobase.Structure Biobase.Structure.DotBracket Biobase.Structure.Shapes- Biobase.Turner- Biobase.Turner.Import- Biobase.Turner.Tables Biobase.Types.Convert Biobase.Types.Energy Biobase.Types.Partition Biobase.Types.Ring Biobase.Types.Score- Biobase.Vienna- Biobase.Vienna.Default- Biobase.Vienna.Export.ViennaC- Biobase.Vienna.Export.ViennaPar- Biobase.Vienna.Import.Turner- Biobase.Vienna.Import.ViennaPar- Biobase.Vienna.Modification.NonStandard- Biobase.Vienna.Modification.Partition- Biobase.Vienna.Modification.Temperature ghc-options:- -O2+ -Odph++ if impl(ghc > 6.13)+ ghc-options:+ -fllvm
Biobase/Constants.hs view
@@ -6,27 +6,29 @@ --- * energy "Infinities" for Int's+-- * energy "Infinities" -- | maxBound on Int is problematic, if we try something like maxBound + -- maxBound which happens very often. 'eInf' is used for settings like lookup -- tables, etc while comparisons are against 'eMax'. -- Both values need to be small enough not to overflow in typical situations. -eInf :: Int-eInf = 10000000--eMax :: Int-eMax = eInf `div` 10--+class Constants a where+ eInf :: a+ eMax :: a --- * floating infinity+instance Constants Int where+ eInf = 10000000+ eMax = 1000000+ {-# INLINE eInf #-}+ {-# INLINE eMax #-} --- here, we choose a real infinity and let the ieee handle it+instance Constants Double where+ eInf = 10000000+ eMax = 1000000+ {-# INLINE eInf #-}+ {-# INLINE eMax #-} -fInf :: Double-fInf = 1/0 -- * some constants, required for scaling and Boltzmann
+ Biobase/DataSource/CT.hs view
@@ -0,0 +1,38 @@++-- | Import CT type structures++module Biobase.DataSource.CT where++import qualified Data.Array.IArray as A+import Data.List.Split++++-- | A CT file. Encodes one or more individual RNAs within one complex. The+-- 'nucs' array encodes (1,n) as '0' has a special meaning. It is used in+-- 'prv', 'nxt' do denote no next or previous nucleotide in the chain.++data CT = CT+ { comments :: [String]+ , lengthLine :: String+ , nucs :: A.Array Int Nuc+ }+ deriving (Show,Read)++-- | A nucleotide. Encodes character, previous and next nucleotide on the chain+-- and pairing partner.++data Nuc = Nuc+ { nuc :: Char+ , prv :: Int+ , nxt :: Int+ , partner :: Int+ }+ deriving (Show,Read)++-- | transforms a 'CT' object into our internal format.++fromCT :: CT -> ()+fromCT ct = res where+ res = ()+ chns = split (keepDelimsR $ whenElt ((==0) . nxt)) . A.elems $ nucs ct
+ Biobase/DataSource/CT/Import.hs view
@@ -0,0 +1,64 @@++-- | Parse a CT file.++module Biobase.DataSource.CT.Import where++import Control.Applicative+import Text.Parsec.Char+import Text.Parsec.Combinator hiding (optional)+import Text.Parsec.Error+import Text.Parsec hiding (many)+import Text.Parsec hiding ((<|>), many, optional)+import Text.Parsec.String+import qualified Data.Array.IArray as A++import Biobase.RNA+import Biobase.RNA.Pairs+import Biobase.DataSource.CT++++-- | Parse a CT file.++fromFile :: FilePath -> IO (Either String CT)+fromFile fname = do+ x <- parseFromFile ctP fname+ return $ case x of+ Left err -> Left $ show err+ Right res -> res++-- * Parser++commentP :: GenParser Char st String+commentP = char '#' *> anyChar `manyTill` newline++commentsP = many commentP++lenlineP :: GenParser Char st (Int,String)+lenlineP = (,) <$> snumP <*> anyChar `manyTill` newline++-- | We parse six fields: position, nucleotide, next nuc, previous nuc, pairing+-- partner and (position again). CT8 adds two additional fields (unknown) and+-- (unknown). Fields in brackets () are not returned, just parsed.++nucLineP :: GenParser Char st (Int,Nuc)+nucLineP = f <$> snumP <*> scharP <*> snumP <*> snumP <*> snumP <* snumP <* choice [newline, snumP *> snumP *> newline] where+ f pos chr prv nxt partner = (pos, Nuc chr prv nxt partner)++nucLinesP :: GenParser Char st [(Int,Nuc)]+nucLinesP = many (try nucLineP)++-- | Parse a CT file with some error handling.++ctP :: GenParser Char st (Either String CT)+ctP = f <$> commentsP <*> lenlineP <*> nucLinesP <* spaces <* eof where+ f cs (l,ll) ns+ | l /= length ns = Left $ "CT inscribed length of: " ++ show l ++ " doesn't match read entries in: " ++ unlines cs+ | otherwise = Right . CT cs ll $ A.array (1,length ns) ns++scharP = spaces *> anyChar++snumP :: GenParser Char st Int+snumP = read <$ try spaces <*> numberP++numberP = many1 digit
+ Biobase/DataSource/DotParen.hs view
@@ -0,0 +1,18 @@++-- | A dot-parenthesis file. These are mostly used by the RNAstrand DB.+-- Admittedly, the format is very similar to dot-bracket.++module Biobase.DataSource.DotParen where++import qualified Data.ByteString.Lazy.Char8 as BS++++data DotParen = DotParen+ { comments :: [BS.ByteString]+ , sequence :: BS.ByteString+ , dotparen :: BS.ByteString+ }+ deriving (Show)++type DotParens = [DotParen]
+ Biobase/DataSource/DotParen/Import.hs view
@@ -0,0 +1,113 @@+{-# LANGUAGE RecordWildCards #-}++-- | Imports a dot-parenthesis file.+--+-- TODO This importer is not unicode-safe. It silently filters out all+-- sequence/structure pairs with unequal lengths. This is work for later.++module Biobase.DataSource.DotParen.Import+ ( fromFile+ , fromFileOrFail+ ) where++import Control.Applicative+import Control.Monad (when)+import Data.Either.Unwrap (isLeft,fromLeft,fromRight)+import qualified Data.ByteString.Lazy.Char8 as BS+import System.Exit (exitFailure)+import Text.Parsec.ByteString.Lazy+import Text.Parsec hiding (many,(<|>))+import Data.List (findIndices)++import Biobase.DataSource.DotParen++++-- | Import a set of sequence/structure pairs from a file.+--+-- TODO improve error handling++fromFile :: FilePath -> IO (Either String DotParens)+fromFile fname = do+ res <- parseFromFile pFile fname+ check res+ where+ check res+ | Left err <- res = return $ Left (show err)+ {-+ | Right ls <- res+ , xs@(x:_) <- findIndices unEqualLengths ls = return . Left $ "unequal sequence / structure length for: " ++ show (map (ls!!) xs)+ -}+ | Right ls <- res = return . Right . filter (not . unEqualLengths) $ ls+ unEqualLengths DotParen{..} = BS.length sequence /= BS.length dotparen++-- | Read RnaStrand data or fail++fromFileOrFail fname = do+ xs' <- fromFile fname+ when (isLeft xs') $ do+ print "error reading source:"+ putStrLn $ fromLeft xs'+ exitFailure+ return $ fromRight xs'++++-- * The parsers++-- | parse a comment line++pComment :: GenParser Char st BS.ByteString+pComment = BS.pack <$ char '#' <*> manyTill anyChar newline++-- | parse all comments++pComments :: GenParser Char st [BS.ByteString]+pComments = many pComment++data DS = D BS.ByteString | S BS.ByteString+isS (S _) = True+isS _ = False+fromDS (S x) = x+fromDS (D x) = x+++-- | parse a sequence line++pSequence :: GenParser Char st DS+pSequence = (\c cs -> S $ BS.pack $ c:cs) <$> noneOf "#" <*> manyTill anyChar newline where++-- | parse one dot-paren line++pDotParen :: GenParser Char st DS+pDotParen = D . BS.pack <$> manyTill dps newline where+ dps = oneOf "()[]<>{}."++-- | parse either a dot-paren line or a sequence line++pDS :: GenParser Char st DS+pDS = choice [try pDotParen, pSequence]++-- | Returns a pair of (sequence,dot-paren)++pDSs :: GenParser Char st (BS.ByteString,BS.ByteString)+pDSs = f <$> many1 pDS where+ f xs = let+ (ss,ds) = span isS xs+ in (BS.concat $ map fromDS ss,BS.concat $ map fromDS ds)++-- | Parse one block++pBlock :: GenParser Char st DotParen+pBlock = (\cs (ss,ds) -> DotParen cs ss ds) <$> pComments <* many newline <*> pDSs++-- | Parse many blocks++pBlocks :: GenParser Char st DotParens+pBlocks = many pBlock++-- | Parse file++pFile :: GenParser Char st DotParens+pFile = pBlocks <* eof+
+ Biobase/DataSource/FR3D.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE RecordWildCards #-}++-- | Holds the 'FR3DBasepairs' structure extracted from a FR3D basepairs file.+-- The other files are still on the TODO list+--+-- TODO write data structures and parsers for the other files.+--+-- TODO rewrite by reducing all those data-structures to something more+-- intelligent. Use 'Nucleotide's for encoding. Have a converter to 'Complex',+-- too.++module Biobase.DataSource.FR3D where++import Data.Map (Map)+import qualified Data.Map as M+import Data.Char (isDigit)+import Control.Monad.Error -- TODO GHC < 7.0.0 only ???+import Data.List (nubBy)++import qualified Biobase.RNA.Complex as C+import Biobase.RNA.Pairs (ExtPair)++++-- * FR3D data structures++-- | Wrap everything up, giving us our data source.++data FR3D = FR3D+ { complex :: C.Complex ExtPair -- ^ parsed PDB/FR3D as normal 'Complex'+ , fr3dBasepairs :: FR3DBasepairs -- ^ the source information+ } deriving (Show)++-- | A complete 'FR3DBasepairs' structure. We have the 'pdbID' from which the FR3D+-- came from, the 'versions' of different programs, the 'chains' or different+-- nucleotide sequences used in the structure, the 'pairs' themselves and other+-- 'comments' which could not be identified correctly.++data FR3DBasepairs = FR3DBasepairs+ { pdbID :: String+ , versions :: String+ , chains :: Map String String+ , pairs :: [Pair]+ , comments :: [String] -- unknown comments, maybe really just comments+ } deriving (Read,Show)++-- | Each 'Pair' is a triple of the 'interaction' between the two 'Nucleotide's+-- 'nuc1' and nuc2'.++data Pair = Pair+ { interaction :: Interaction+ , nuc1 :: Nucleotide+ , nuc2 :: Nucleotide+ } deriving (Read,Show,Eq,Ord)++-- | Each 'Nucleotide' is described by the 'nuc' itself (A,C,G,U) (something+-- else?), the pdb 'num'ber (whatever that is), the 'chain' id and the+-- 'pos'ition in the chain.++data Nucleotide = Nucleotide+ { nuc :: Char+ , num :: String -- should be "20" but could be "20A" (grr)+ , chain :: String -- could be "chain 1" or "chain E" or so+ , pos :: Int+ } deriving (Read,Show,Eq,Ord)++type Interaction = String -- ?++++-- | fix the 'pos' in all 'Nucleotide's. Not actually clear, if this /DOES/ fix+-- the problem!++fixLengths :: FR3DBasepairs -> FR3DBasepairs+fixLengths b = b {pairs = map f $ pairs b} where+ f p = p{nuc1 = g $ nuc1 p, nuc2 = g $ nuc2 p}+ g n+ | pos n > (length $ chains b M.! chain n) = n{pos = read $ filter isDigit $ num n}+ | otherwise = n++-- | Check if a given 'FR3DBasepairs' structure is correct, or if there are errors++checkFR3DBasepairs :: FR3DBasepairs -> Either String FR3DBasepairs+checkFR3DBasepairs b' = checkChains b' >>= checkLength >>= return where+ checkChains b+ | null cnucs = Right b+ | otherwise = Left $ "CHAIN: " ++ show cnucs+ where cnucs = filter (\n -> not $ chain n `M.member` chains b) ps+ checkLength b+ | null cnucs = Right b+ | otherwise = Left $ "LENGTH: " ++ show b ++ show cnucs+ where cnucs = filter (\n -> length (chains b M.! chain n) < pos n) ps -- positions start countaing at "1"+ checkNucs b+ | null cnucs = Right b+ | otherwise = Left $ "NUCS: " ++ show cnucs+ where cnucs = filter (\n -> (chains b M.! chain n !! (pos n -1)) == nuc n) ps+ ps = concatMap (\x -> [nuc1 x, nuc2 x]) $ pairs b'++++-- * Transform 'FR3DBasepairs' into 'Complex'++-- | Aquire a 'Complex' from the data read.+--+-- TODO write me++makeComplex :: FR3DBasepairs -> C.Complex ExtPair+makeComplex b@FR3DBasepairs{..}+ | length sqnc /= length chns = error $ "makeComplex: " ++ show b+ | otherwise = C.mkComplex "TODO write me" {- sqnc strc chns -} where+ sqnc = concatMap snd $ M.toAscList chains+ strc = nubBy eqT12 $ map (\(Pair z n1 n2) -> (pos n1-1,pos n2-1,z)) pairs+ chns = concatMap (\(k,v) -> concat $ replicate (length v) k) $ M.toAscList chains++eqT12 (a,b,_) (x,y,_) = (a,b)==(x,y) || (a,b)==(y,x)++-- | Simple wrapper fixing up an 'FR3D'++mkFR3D :: FR3DBasepairs -> FR3D+mkFR3D b = FR3D {complex=makeComplex b, fr3dBasepairs=b}
+ Biobase/DataSource/FR3D/Import.hs view
@@ -0,0 +1,92 @@++-- Import / parse FR3D basepairs files.++module Biobase.DataSource.FR3D.Import where++import Control.Applicative+import Control.Monad+import Data.Either+import Data.List+import System.Directory+import System.FilePath+import System.IO.Unsafe+import Text.Parsec.Char+import Text.Parsec.Combinator hiding (optional)+import Text.Parsec.Error+import Text.Parsec hiding ((<|>), many, optional)+import Text.Parsec.String+import qualified Data.Map as M+import Control.Arrow (first)++import Biobase.DataSource.FR3D++-- * New default importer++-- | import a number of 'FR3D' structures.++fromDir :: FilePath -> IO ([FR3D], [ParseError])+fromDir dirname = do+ (bps,errs) <- importFR3DBasepairsFiles dirname+ return (map mkFR3D bps,errs)++fromFile :: FilePath -> IO (Either ParseError FR3D)+fromFile fname = do+ bp <- importFR3DBasepairsFile fname+ return $ mkFR3D `fmap` bp++++-- * Older functions++-- | Parse a complete FR3D basepairs file and return a 'FR3DBasepairs' structure.+-- Does not set the 'pdbID', that one is encoded in the filename. (And in each+-- individual 'Pair'...).++parseFR3DBasepairs :: GenParser Char st FR3DBasepairs+parseFR3DBasepairs = mk <$> comments <* pdbdesc <*> many (parsePair <* newline) where+ comments = many commentline+ commentline = char '#' *> manyTill anyChar newline+ pdbdesc = string "PDB_ID" *> manyTill anyChar newline+ mk cs bps =+ let -- TODO this is too fragile!+ (v:_:chns) = cs+ f (x:y:_) = (x,y)+ in FR3DBasepairs "" v (M.fromList $ map (f . words) chns) {-(map ((\[n,c] -> (read n,c)) . drop 1 . words) chns)-} bps cs++-- | One line of connected nucleotides forms a 'Pair'++parsePair :: GenParser Char st Pair+parsePair = Pair <$ mtas <*> interact <*> parseNucleotide <* space <*> parseNucleotide where+ interact = mtas++-- | One of the two 'Nucleotide's in a 'Pair'++parseNucleotide :: GenParser Char st Nucleotide+parseNucleotide = Nucleotide <$> anyChar <* space <*> mtas <*> mtas <*> number where+ number = read <$> many1 digit++-- | Given a directory, try to import all files matching "_basepairs_FR3D.txt".+-- In the result (as,bs), the as are the successful parses, while bs failed.+-- For now (NOV 2010), bs is empty ;-)++importFR3DBasepairsFiles :: FilePath -> IO ([FR3DBasepairs], [Text.Parsec.Error.ParseError])+importFR3DBasepairsFiles d = do+ de <- doesDirectoryExist d+ if de+ then do+ cnts <- getDirectoryContents d+ let cands = filter ("basepairs_FR3D.txt" `isSuffixOf`) cnts+ (psL,psR) <- partitionEithers `fmap` mapM (pFF d) cands+ return (psR, psL)+ else return ([], [])++pFF d c = unsafeInterleaveIO . fmap (fmap (\x -> x{pdbID = take 4 c})) . parseFromFile parseFR3DBasepairs $ d </> c++-- | Try to import just one basepair file.++importFR3DBasepairsFile :: FilePath -> IO (Either Text.Parsec.Error.ParseError FR3DBasepairs)+importFR3DBasepairsFile f = fmap (fmap (\x -> x{pdbID = take 4 f})) $ parseFromFile parseFR3DBasepairs f++-- * helper functions++mtas = manyTill anyChar space
+ Biobase/DataSource/InfernalCM.hs view
@@ -0,0 +1,326 @@++--+-- Stores Infernal Covariance Model data. Built for ease of use, not speed but+-- should work reasonably well.+--++-- TODO Data.Vector?+--+-- TODO use generics?+--+-- TODO functions to change to probabilities!+--+-- TODO cmCanonize function!+--+-- TODO put functions into their own modules, a bit of cleanup+--+-- TODO add functions to insert a new node between two already existing nodes; think about how to handle BIF+--+-- TODO add ability to remove node; think about how to handle BIF+--+-- NOTE maybe BIF should not be insertable/removable right now?++module Biobase.DataSource.InfernalCM where+++import Data.Array.IArray+import Data.List (genericLength)++import Biobase.RNA hiding (nucE) -- "E type" nucleotides do not happen in CMs!++++-- * Data types for Covariance Models++-- {{{ Data types++-- | A complete covariance model. Each node and each state can be tagged with+-- additional data. Typically, say after parsing, the tag will be ().++data CM n s = CM+ { nodes :: Array Int (Node n)+ , states :: Array Int (State s)+ , header :: [(String,String)] -- keeps the list of header entries sorted!+ , localBegin :: Array Int Double+ , localEnd :: Array Int Double+ , cmType :: CMType+ , nullModel :: Array Nucleotide Double+ } deriving (Show)++-- | Describes one node++data Node n = Node+ { nid :: Int+ , ntype :: NodeType+ , nparents :: [Int] -- TODO can there be more than one?+ , nchildren :: [Int]+ , nstates :: [Int]+ , ntag :: n+ } deriving (Show)++-- | One state++data State s = State+ { sid :: Int+ , stype :: StateType+ , snode :: Int+ , sparents :: [Int]+ , schildren :: [Transition]+ , semission :: [Emission]+ , stag :: s+ } deriving (Show)++-- | CMType is important if we want to set localBegin / localEnd!++data CMType = CMProb | CMScore+ deriving (Show,Eq)++-- | can emit either one nucleotide or a pair++data Emission+ = EmitS {eNuc :: Nucleotide, escore :: Double}+ | EmitP { eNucL :: Nucleotide, eNucR :: Nucleotide, escore :: Double}+ deriving (Show)++-- | branches are transition without attached probability becaue both branches are always taken++data Transition+ = Branch {tchild :: Int}+ | Transition {tchild :: Int, tscore :: Double}+ deriving (Show)++-- | the different node types++data NodeType = MATP | MATL | MATR | BIF | ROOT | BEGL | BEGR | END+ deriving (Read,Show,Eq,Ord,Enum,Bounded)++-- | the different state types++data StateType = MP | IL | IR | D | ML | MR | B | S | E+ deriving (Read,Show,Eq,Ord,Enum,Bounded)++-- }}}+++-- * make a local model out of a global one++-- | generate a local model with local begin prob and local end prob++cmMakeLocal :: Double -> Double -> CM n s -> CM n s+cmMakeLocal pbegin pend cm = cmMakeLocalBegin pbegin $ cmMakeLocalEnd pend cm++++cmMakeLocalBegin :: Double -> CM n s -> CM n s+cmMakeLocalBegin pbegin cm = cm{localBegin = localBegin cm // changes} where+ changes = rootS : (start : intern)+ rootS = (0, prob2Score 0 1.0) -- root disabled!+ start = (head . nstates $ nodes cm ! 1, prob2Score (1-pbegin) 1.0) -- the first state after "root 0"+ intern = map (\k -> (sid $ nodeMainState cm k,prob2Score (pbegin / l) 1.0)) nds+ nds = filter (localBeginPossible cm) . elems $ nodes cm+ l = genericLength nds++++-- TODO have to change the transition score, too!++cmMakeLocalEnd :: Double -> CM n s -> CM n s+cmMakeLocalEnd pend cm = cm{localEnd = localEnd cm // changes} where+ changes = map (\k -> (sid $ nodeMainState cm k,prob2Score (pend / l) 1.0)) nds+ nds = filter (localBeginPossible cm) . elems $ nodes cm+ l = genericLength nds++++-- * Transform between score and probability mode++-- | given a CM in score mode, change it to probability mode++cmScore2Prob :: CM n s -> CM n s+cmScore2Prob cm' = if cmType cm' == CMProb then cm' else CM+ (nodes cm)+ (statesScore2Prob cm $ states cm)+ (header cm)+ (localBeginScore2Prob $ localBegin cm)+ (localEndScore2Prob $ localEnd cm)+ CMProb+ nm+ where+ nm = amap (flip score2Prob 0.25) $ nullModel cm'+ cm = cm' {nullModel = nm}+++-- | Given a CM in prob mode, change to score mode++cmProb2Score :: CM n s -> CM n s+cmProb2Score cm' = if cmType cm' == CMScore then cm' else CM+ (nodes cm)+ (statesProb2Score cm $ states cm)+ (header cm)+ (localBeginProb2Score $ localBegin cm)+ (localEndProb2Score $ localEnd cm)+ CMScore+ nm+ where+ nm = amap (flip prob2Score 0.25) $ nullModel cm'+ cm = cm' {nullModel = nm}++++-- | normalize all PROBabilities in a CM++cmNormalizeProbabilities :: CM n s -> CM n s+cmNormalizeProbabilities cm+ | cmType cm == CMScore = error "cannot normalize score-type CM"+ | otherwise = cm -- TODO have to map normalization over all scores!++++-- {{{ CM score/prob conversion helpers++statesScore2Prob :: CM n s -> Array Int (State s) -> Array Int (State s)+statesScore2Prob cm sA = amap f sA where+ f s = s {schildren = map fT $ schildren s, semission = map fE $ semission s}+ fT b@(Branch _) = b+ fT (Transition k v) = Transition k (score2Prob v 1.0)+ fE (EmitS k v) = EmitS k (score2Prob v $ nullModel cm ! k)+ fE (EmitP k1 k2 v) = EmitP k1 k2 (score2Prob v $ (nullModel cm ! k1) * (nullModel cm ! k2))++++localBeginScore2Prob :: Array Int Double -> Array Int Double+localBeginScore2Prob sA = amap f sA where+ f s = score2Prob s 1.0++++localEndScore2Prob :: Array Int Double -> Array Int Double+localEndScore2Prob sA = amap f sA where+ f s = score2Prob s 1.0++++statesProb2Score :: CM n s -> Array Int (State s) -> Array Int (State s)+statesProb2Score cm sA = amap f sA where+ f s = s {schildren = map fT $ schildren s, semission = map fE $ semission s}+ fT b@(Branch _) = b+ fT (Transition k v) = Transition k (prob2Score v 1.0)+ fE (EmitS k v) = EmitS k (prob2Score v $ nullModel cm ! k)+ fE (EmitP k1 k2 v) = EmitP k1 k2 (prob2Score v $ (nullModel cm ! k1) * (nullModel cm ! k2))++++localBeginProb2Score :: Array Int Double -> Array Int Double+localBeginProb2Score sA = amap f sA where+ f s = prob2Score s 1.0++++localEndProb2Score :: Array Int Double -> Array Int Double+localEndProb2Score sA = amap f sA where+ f s = score2Prob s 1.0++-- }}}+++++-- * Helper Functions++-- {{{ helper functions++-- | extract the main state for each node (eg MP state for MATP node)++-- TODO shouldn't this just be "head $ nstates n"?++nodeMainState :: CM n s -> Node n -> State s+nodeMainState cm n = head $ filter ((==st) . stype) ss where+ (Just st) = (ntype n) `lookup` nodeMainStateAssocs+ ss = map (states cm !) $ nstates n+++-- | Checks for each node, if it can be target of a local begin.++localBeginPossible :: CM n s -> Node n -> Bool+localBeginPossible cm n =+ if ntype n `elem` okNodes+ && (not . any (==0) $ nparents n) -- nodes reachable from "root" (that is: node 1) have handled specially+ then True+ else False+ where+ okNodes = [MATP,MATL,MATR,BIF]++++-- | Checks for each node if it can lead to a local end.++localEndPossible :: CM n s -> Node n -> Bool+localEndPossible cm n =+ if ntype n `elem` okNodes+ && (END /= (ntype $ nodes cm ! (nid n +1)))+ then True+ else False+ where+ okNodes = [MATP,MATL,MATR,BEGL,BEGR]++++-- | transform scores into probabilities, given a nullmodel for x++-- TODO quickcheck!++score2Prob x null+ | x == (-1/0) = 0+ | otherwise = exp (x * log 2) * null++++-- | back into scores++prob2Score x null+ | x == 0 = (-1/0)+ | otherwise = log (x / null) / log 2++++-- | Transform a state, setting probabilities instead of scores. Requires CM+-- knowledge for background model.++-- TODO actually use the background model++stateScore2Prob :: CM n s -> State s -> State s+stateScore2Prob cm s = error "implement me"++++-- | Transform a state, setting scores instead of probabilities.++stateProb2Score :: CM n s -> State s -> State s+stateProb2Score cm s = error "implement me"+transitionTargets :: [Transition] -> [Int]+transitionTargets xs = map f xs where+ f (Branch x) = x+ f (Transition x _) = x+++nodeMainStateAssocs :: [(NodeType,StateType)]+nodeMainStateAssocs =+ [ (MATP, MP)+ , (MATL, ML)+ , (MATR, MR)+ , (BIF, B)+ , (ROOT, S)+ , (BEGL, S)+ , (BEGR, S)+ , (END, E)+ ]++-- }}}++++-- TODO score -> prob : exp (x / log 2) -- CHECK THIS!!!+-- score -> prob : exp (x * log 2)+-- prob -> score : (log x) / log 2+-- TODO mkGlobal (needed?)+-- TODO use logsum : log (exp x + exp y) = x + log (1 + exp (y-x)), where x>y
+ Biobase/DataSource/InfernalCM/Export.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE RecordWildCards #-}++-- | write an Infernal model. We aim for version 1.0.2 of Infernal but right+-- now, there is no explicit version management! We just return header+-- information as we read it. So we are compatible to all versions that can be+-- parsed but have no safeguards in place.+--+-- NOTE: exported model can apparently be calibrated.+--+-- TODO make sure that (Export.toString . Import.fromString == id); the other+-- way around is not absolutely necessary (except if the Infernal parser should+-- require this at some point)+--+-- TODO put functions like stringS into another module?++module Biobase.DataSource.InfernalCM.Export where++import qualified Data.Array.IArray as A+import Text.Printf++import Biobase.DataSource.InfernalCM++import Biobase.DataSource.InfernalCM.Import -- TODO for testing only!++++-- | Main export function for CMs. Creates a string that is accepted by+-- Infernal++toString :: CM n s -> String+toString cm@CM{..} = unlines $ hdr ++ ["MODEL:"] ++ nds ++ ["//"]+ where+ hdr = map (\(k,v) -> k ++ " " ++ v) header+ nds = concatMap (nodeToString cm) $ A.elems nodes++++-- | export a specific node, used by 'toString'++nodeToString :: CM n s -> Node n -> [String]+nodeToString cm Node{..} = printf "\t\t\t\t[ %s %d ]" (show ntype) nid : map (stateToString cm . (states cm A.!)) nstates++++-- | export a specific states, used by 'nodeToString'++stateToString :: CM n s -> State s -> String+stateToString cm State{..} = printf " %2s %6d %6d %2d %6d %6d %-55s %s" (show stype) sid maxP numP minC numC tscores escores+ where+ maxP+ | null sparents = -1+ | otherwise = maximum sparents+ numP = length sparents+ minC+ | null schildren = -1+ | otherwise = minimum $ map tchild schildren+ numC+ | stype == B = maximum $ map tchild schildren+ | otherwise = length schildren+ tscores :: String+ tscores+ | stype == B = ""+ | otherwise = concatMap (printf "%s " . stringS . tscore) schildren+ escores :: String+ escores+ | null semission = ""+ | otherwise = concatMap (printf "%.3f " . escore) semission++++-- | export scores for transitions with the Infernal-specific "-infinity" value+-- of "*"++stringS x+ | x == (-1/0) = " *"+ | otherwise = printf "%.3f" x
+ Biobase/DataSource/InfernalCM/Import.hs view
@@ -0,0 +1,197 @@++--+-- A parser for Infernal's Covariance Models (CM). Should work with version 1.0+-- of Infernal.+--++-- TODO use generics?+--+-- TODO importing the cmcalibrate calibration data is currently broken! (data is parsed as separate lines)++module Biobase.DataSource.InfernalCM.Import + ( fromFile+ , fromString+ ) where++import Data.Maybe (fromJust)+import qualified Data.Array.IArray as A+import qualified Data.List as L+import Text.ParserCombinators.Parsec hiding (State)++import Biobase.DataSource.InfernalCM+import Biobase.RNA hiding (nucE)++++-- {{{ Parsec++myChar = alphaNum <|> char '-' <|> char '_' <|> char '.'+headerChar = myChar <|> char '[' <|> char ']'+floating = many1 $ digit <|> char '.' <|> char 'e' <|> char '-'++headerLine = do+ key <- many1 headerChar+ --spaces+ many1 $ char ' '+ val <- many1 (headerChar <|> char ' ' <|> char '/' <|> char ':')+ newline+ return (key,val)++unknownNumbers = do+ many1 $ char ' '+ ns <- floating `sepEndBy` (many1 $ char ' ')+ newline+ return ("",concat ns)++theHeader = do+ hs <- many $ (try headerLine <|> try unknownNumbers)+ string "MODEL:"+ newline+ return hs++-- }}}++-- {{{ Node++node = do+ spaces+ string "[ "+ name <- many letter+ spaces+ num <- many digit >>= (return . read)+ spaces+ string "]"+ newline+ states <- many $ try (state num)+ return $ (Node+ { ntype = read name+ , nid = num+ , nstates = map sid states+ , nparents = []+ , nchildren = []+ , ntag = ()+ }+ , states)++-- }}}++-- {{{ stuff++-- TODO put some of this into HsTools/Parsec stuff++aNum = many1 $ char '-' <|> digit+addneginf :: String -> Double+addneginf "*" = (-1)/0 --"-1000000000.0"+addneginf x = read x++-- }}}++-- {{{ State++state nodeID = do+ spaces+ name <- many1 myChar+ spaces+ sid <- aNum >>= (return . read)+ spaces+ plast <- aNum >>= (return . read)+ spaces+ pnum <- aNum >>= (return . read)+ spaces+ cfirst <- aNum >>= (return . read)+ spaces+ cnum <- aNum >>= (return . read)+ probs <- ( (many $ myChar <|> char '*') `sepBy` (many1 $ char ' ') >>=+ return . map addneginf . filter ((/=) "") )+ newline+ let s = case name of+ "B" -> State+ { stype = read name+ , sid = sid+ , snode = nodeID+ , sparents = [plast-pnum+1 .. plast]+ , schildren = [Branch cfirst, Branch cnum]+ , semission = []+ , stag = ()+ }+ _ -> State+ { stype = read name+ , sid = sid+ , snode = nodeID+ , sparents = [plast-pnum+1 .. plast]+ , schildren = zipWith Transition [cfirst .. cfirst+cnum-1] probs+ , semission = let keep = drop cnum probs in+ case length keep of+ 0 -> []+ 4 -> zipWith EmitS acgu keep+ 16 -> zipWith (\(k1,k2) v -> EmitP k1 k2 v) acguPairs keep+ _ -> error $ "strange number of probabilities" ++ show (keep)+ , stag = ()+ }+ return s++-- }}}++-- {{{ Model++models = do+ ms <- many model+ eof+ return ms++model = do+ h <- theHeader+ ns <- many node+ let states = concatMap snd ns+ let nodes = map (addPCinfo states . fst) ns+ -- just add all the node parent / child info+ string "//"+ newline+ -- eof -- removed, we want to be able to read concatenated models!+ return $ CM+ { nodes = A.array (0, length nodes -1) $ zip (map nid nodes) nodes+ , states = A.array (0, length states -1) $ zip (map sid states) states+ , header = h+ , localBegin = A.array (0, length states -1) $ zip [0 .. length states -1] (0.0 : repeat (-1/0))+ , localEnd = A.array (0, length states -1) $ zip [0 .. length states -1] (repeat (-1/0))+ , cmType = CMScore+ , nullModel = A.array (nucA,nucU) $ zip acgu (map read . words . fromJust $ "NULL" `lookup` h) -- TODO circumvents the whole parsing stuff!+ }++-- }}}++-- {{{ Stuff++addPCinfo states n =+ let+ s = nstates n+ sp = L.nub $ L.sort $ concatMap (sparents . (states !!)) s+ sc = L.nub $ L.sort $ concatMap (transitionTargets . schildren . (states !!)) s+ np = (L.nub $ L.sort $ map (snode . (states !!)) sp) L.\\ [nid n]+ nc = (L.nub $ L.sort $ map (snode . (states !!)) sc) L.\\ [nid n]+ in+ n {nparents = np, nchildren = nc}++++-- | Two types of parsing, once using a file and once by parsing a string.++fromFile f = parseFromFile models f+fromString s = parse models "(stdin)" s++-- }}}++-- | Helper function to remove impossible state transitions (those that have+-- -infty score).++-- TODO move to InfernalCM.hs and have it for Prob and Score both++{-+canonize cm = cm {states = A.amap f $ states cm} where+ f s = s {schildren = filter g $ schildren s}+ g (Branch _) = True+ g (Transition _ v) = + h (_,s)+ | s == (-1)/0 = False+ | otherwise = True+-}
+ Biobase/DataSource/MCFold.hs view
@@ -0,0 +1,190 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++-- | The next iteration of MC-Fold-DP which is, hopefully, a bit faster. It can+-- be seen that the dsConnect and ddConnect data structures do not care about+-- the type of connection, only which kind of NCM is involved and the pair.+-- This follows the way MC-Fold integrates away the specific type of pair+-- family involved.++module Biobase.DataSource.MCFold where++import Control.DeepSeq+import Data.Ix+import Data.Ix.Tuple+import Data.PrimitiveArray+import Data.PrimitiveArray.Ix -- only needed for the ghci part?+import qualified Data.Vector.Unboxed as VU++import Biobase.RNA+import Biobase.RNA.Hashes++++-- | This version of the motif database accepts ACGU+E as nucleotides.+-- Occurances of E lead to a maximization over all strings where the E are+-- replaced by ACGU -- if the corresponding function was used, otherwise all E+-- map to infinity (actually only a large number).+--+-- The dsConnect and ddConnect database stores the combined information for+-- connections between different cycles.++data MotifDB = MotifDB+ -- The most important data, NCMs and connections between two of those+ { sCycles :: [(Int,CycleArray)] -- ^ store length of cycles, cycle array for this length+ , dCycles :: [((Int,Int),CycleArray)] -- ^ store (left,right) lengths, cycle array+ , dsConnect :: [(((Int,Int),Int),ConnectArray)]+ , ddConnect :: [(((Int,Int),(Int,Int)),ConnectArray)]+ -- Following is other data, mostly from the importer+ , rawPairScores :: PairScoreArray+ , rawJunctionScores :: JunctionArray+ , rawSHingeCounts :: [(Int,[RawHinge])] -- ^ length of cycle, hinge data+ , rawDHingeCounts :: [((Int,Int),[RawHinge])] -- ^ length of cycle, length of cycle, hinge data+ } deriving (Show)++++-- * Newtypes for different annotations++newtype TransCis = TransCis Int+ deriving (Eq,Ord,Ix,NFData,Read,Show,Enum)+(trans:cis:_) = map TransCis [0..]++instance Bounded TransCis where+ minBound = trans+ maxBound = cis++newtype AntiPara = AntiPara Int+ deriving (Eq,Ord,Ix,NFData,Read,Show,Enum)+(anti:para:_) = map AntiPara [0..]++instance Bounded AntiPara where+ minBound = anti+ maxBound = para++newtype Slash = Slash Int+ deriving (Eq,Ord,Ix,NFData,Read,Show,Enum)+(wsp:hsp:csp:ssp:bsp:_) = map Slash [0..]++instance Bounded Slash where+ minBound = wsp+ maxBound = bsp++newtype Prime = Prime Int+ deriving (Eq,Ord,Ix,NFData,Read,Show,Enum)+(p5:p3:_) = map Prime [0..]++instance Bounded Prime where+ minBound = p5+ maxBound = p3++-- | log-scores as derived from probabilities.+--+-- TODO apply (min eInf)?++logScore :: Double -> Double+logScore x = (-0.606) * log x++type CycleArray = PrimArray HashedPrimary Double+type ConnectArray = PrimArray (Nucleotide,Nucleotide) Double -- ,Slash,Slash,AntiPara,TransCis) Double+type RawHinge = (((Prime,Nucleotide,Nucleotide),(Slash,Slash,AntiPara,TransCis)),Double)+type PairScoreArray = PrimArray (Nucleotide,Nucleotide) Double+type JunctionArray = PrimArray (Int,Int) Double++++-- * A lot of static information++-- | Known single-pair types. (Length of nucleotide string, 0-based index).++-- 4 -> (5,2)+-- 5 -> (5,3)+-- 6 -> (5,4)+--+-- found to be wrong+-- 5 -> (0,5)++knownSingleNCM :: VU.Vector (Int,Int)+knownSingleNCM = VU.fromList+ [ (4,2)+ , (5,3)+ , (6,4)+ ]++-- | Known double-pair types. ((Length of left...,Length of right nucleotide+-- string), 0-based index++-- found to be right through hacking!+-- all are (..) to next type+-- NCM type -> junctions IV.! (a,b)+-- (a+1,b+1) for the junction.db+-- (2,2) -> (5,5)+-- (2,3) -> (8,2)+-- (3,2) -> (9,2)++knownDoubleNCM :: VU.Vector ((Int,Int),Int)+knownDoubleNCM = VU.fromList+ [ ((2,2), 5)+ , ((3,3), 6)+ , ((2,3), 7)+ , ((3,2), 8)+ , ((2,4), 9)+ , ((4,2),10)+ ]++-- | This is a list of known hinge types. If it has to be regenerated at some+-- point, run the following command inside the MCfold DB:+--+-- cat *hinge | grep -v "^\[" | awk '{print $1 " " $2 " " $3}' | sort | uniq | awk '{printf " , \"%s\"\n", $0}'++knownHinges =+ [ "B/B anti trans"+ , "B/H anti trans"+ , "B/H para cis"+ , "B/S anti cis"+ , "B/S anti trans"+ , "B/S para trans"+ , "B/W anti cis"+ , "B/W anti trans"+ , "B/W para cis"+ , "B/W para trans"+ , "C/H para trans"+ , "H/B anti trans"+ , "H/C para trans"+ , "H/H anti cis"+ , "H/H para trans"+ , "H/S anti trans"+ , "H/S para trans"+ , "H/W anti cis"+ , "H/W anti trans"+ , "H/W para cis"+ , "H/W para trans"+ , "S/B anti cis"+ , "S/B para trans"+ , "S/C para cis"+ , "S/H anti cis"+ , "S/H anti trans"+ , "S/H para cis"+ , "S/H para trans"+ , "S/S anti cis"+ , "S/S para trans"+ , "S/W anti cis"+ , "S/W anti trans"+ , "S/W para cis"+ , "S/W para trans"+ , "W/B anti cis"+ , "W/B anti trans"+ , "W/B para cis"+ , "W/C anti trans"+ , "W/H anti cis"+ , "W/H anti trans"+ , "W/H para cis"+ , "W/H para trans"+ , "W/S anti cis"+ , "W/S anti trans"+ , "W/S para cis"+ , "W/S para trans"+ , "W/W anti cis"+ , "W/W anti trans"+ , "W/W para cis"+ , "W/W para trans"+ ]
+ Biobase/DataSource/MCFold/Conversions.hs view
@@ -0,0 +1,58 @@++-- | Performs operations on cyclearrays, most importantly calculating energies+-- for "E" cases.+--+-- TODO MotifDB -> MotifDB should be the type.+--+-- TODO two different cases (i) activate "E" with reasonable defaults (ii)+-- generic sparse data correction. If (ii) is used, it should come before (i)+-- in order to produce reasonable results for motifs with "E"++module Biobase.DataSource.MCFold.Conversions+ ( maxArray+ ) where++import qualified Data.Vector.Unboxed as VU++import Data.PrimitiveArray++import Biobase.Constants+import Biobase.DataSource.MCFold+import Biobase.RNA+import Biobase.RNA.Hashes+import Biobase.RNA.NucBounds++++-- * activate++-- | Given a CycleArray, create entries for all keys containing at least one E.+-- Set said energy to maximum over all non-E containing neighbors.++maxArray :: CycleArray -> Int -> CycleArray+maxArray arr k = fromAssocs l u eInf xs where+ (l,u) = bounds arr+ xs = map (\k -> let p = mkPrimary k in (mkHashedPrimary (minExtended,maxExtended) p,maxOver arr p)) $ genKeys k++-- | Perform maximum calculation for one element++maxOver :: CycleArray -> Primary -> Double+maxOver arr p+ | VU.all (/=nucE) p = arr ! mkci p+ | otherwise = maximum $ map ((arr !) . mkci . mkPrimary) keys+ where+ mkci = mkHashedPrimary (minExtended,maxExtended)+ keys = mkKeys $ VU.toList p++-- | Create all neighboring keys for a given one++mkKeys :: [Nucleotide] -> [[Nucleotide]]+mkKeys [x] = if x==nucE then [[y] |y<-acgu] else [[x]]+mkKeys (x:xs) = [ head y:ys | y<-mkKeys [x], ys<-mkKeys xs ]++-- | Generate all keys of a given size++genKeys :: Int -> [[Nucleotide]]+genKeys k+ | k==1 = [[y] | y<-eacgu]+ | k> 1 = [ y:ys | y<-eacgu, ys<-genKeys (k-1) ]
+ Biobase/DataSource/MCFold/Import.hs view
@@ -0,0 +1,226 @@+{-# LANGUAGE ScopedTypeVariables #-}++-- | Importer for the NCM database.+--+-- NOTE This version reads only known single/double-stranded NCMs.+--+-- NOTE "infinity" is a large constant, given by RNA.Constants.eInf++module Biobase.DataSource.MCFold.Import+ ( parseDir+ ) where++import Control.Applicative+import Control.Arrow (first, second)+import Control.Monad (liftM)+import Data.Either.Unwrap (fromRight)+import Data.Maybe (fromJust)+import qualified Data.ByteString as B+import qualified Data.Map as M+import qualified Data.Vector.Unboxed as VU+import System.FilePath ((</>))+import Text.Parsec.ByteString+import Text.Parsec hiding (many, (<|>))+import Text.Parsec.Prim (parse)+import Text.Printf++import Text.Parsec.Numbers+import Data.PrimitiveArray++import Biobase.Constants+import Biobase.DataSource.MCFold+import Biobase.RNA+import Biobase.RNA.Hashes+import Biobase.RNA.NucBounds++++parseDir :: FilePath -> IO MotifDB+parseDir dir = do+ let sList = map fst $ VU.toList knownSingleNCM+ let dList = map fst $ VU.toList knownDoubleNCM+ -- basic filenames+ let (spFiles :: [FilePath]) = map ((dir </>) . printf "1_strand_%d.db") sList+ let (dsFiles :: [FilePath]) = map ((dir </>) . uncurry (printf "2_strand_%d_%d.db")) dList+ -- parse cycle DB+ let parseWith parser suffix lst = liftM (zip lst) . mapM (liftM fromRight . parseFromFile parser . (++suffix))+ sCycles <- parseWith parseCycle ".cycle" sList spFiles+ dCycles <- parseWith parseCycle ".cycle" dList dsFiles+ -- parse hinge DB: parses the original counted data+ sHinges <- parseWith parseHinge ".hinge" sList spFiles+ dHinges <- parseWith parseHinge ".hinge" dList dsFiles+ -- parse the DB with individual pair contributions, dropping the 5 integer-based values first+ pairScores <- liftM (fromAssocs minExtended maxExtended eInf . zip [(n1,n2)|n1<-eacgu,n2<-eacgu] . drop 5 . fromRight) . parseFromFile parsePairScores $ (dir </> "hinge.db") -- strangely, the data is in hinge.db+ -- parse contributions by individual junctions+ junctionScores <- liftM (fromList (0,0) (21,21) . fromRight) . parseFromFile parseJunction $ (dir </> "junction.db")+ return $ MotifDB+ { sCycles = map (second (toNCMArray pairScores)) sCycles+ , dCycles = map (second (toNCMArray pairScores)) dCycles+ , dsConnect = [ mkDSConnect junctionScores pairScores d s | d <- dHinges, s <- sHinges ]+ , ddConnect = [ mkDDConnect junctionScores pairScores d d | d <- dHinges, d <- dHinges ]+ , rawPairScores = pairScores+ , rawJunctionScores = junctionScores+ , rawSHingeCounts = sHinges+ , rawDHingeCounts = dHinges+ }++-- | Create the connections array for a given doubleNCM known by (l,r) length+-- and singleNCM. Such a connection is then only defined by the connecting+-- pair.+--+-- TODO check if connect calculates correctly!++mkDSConnect :: JunctionArray -> PairScoreArray -> ((Int,Int),[RawHinge]) -> (Int,[RawHinge]) -> (((Int,Int),Int),ConnectArray)+mkDSConnect junction pair ((lenLeft,lenRight),ds) (len,ss) = (((lenLeft,lenRight),len), fromAssocs l u z xs) where+ l = minExtended+ u = maxExtended+ z = eInf+ xs = [ ((n1,n2), connect n1 n2) | n1<-acgu, n2<-acgu ]+ dsMap = M.map normalize . M.fromListWith (++) $ map (\((pnn,others),v) -> (pnn,[(others,v)])) $ ds+ ssMap = M.map normalize . M.fromListWith (++) $ map (\((pnn,others),v) -> (pnn,[(others,v)])) $ ss+ connect n1 n2 =+ let+ common = [ va*vb | (ka,va) <- M.findWithDefault [] (p3,n1,n2) dsMap, (kb,vb) <- M.findWithDefault [] (p5,n1,n2) ssMap, ka==kb ]+ c = if null common+ then eInf+ else junction ! (((lenLeft,lenRight) `lookup` knownDoubleNCM),(len `lookup` knownSingleNCM)) -- junction score between two NCMs+ + (logScore $ sum common)+ in c+ lookup k = snd . fromJust . VU.find ((==k).fst)+ normalize xs+ | null xs = xs+ | otherwise = map (second (/total)) xs+ where total = sum $ map snd xs++-- | Same as above. Some annoying code duplication.+--+-- TODO check if connect calculates correctly++mkDDConnect :: JunctionArray -> PairScoreArray -> ((Int,Int),[RawHinge]) -> ((Int,Int),[RawHinge]) -> (((Int,Int),(Int,Int)),ConnectArray)+mkDDConnect junction pair ((lenLA,lenRA),dsA) ((lenLB,lenRB),dsB) = (((lenLA,lenRA),(lenLB,lenRB)), fromAssocs l u z xs) where+ l = minExtended+ u = maxExtended+ z = eInf+ xs = [ ((n1,n2), connect n1 n2) | n1<-acgu, n2<-acgu ]+ dsAMap = M.map normalize . M.fromListWith (++) $ map (\((pnn,others),v) -> (pnn,[(others,v)])) $ dsA+ dsBMap = M.map normalize . M.fromListWith (++) $ map (\((pnn,others),v) -> (pnn,[(others,v)])) $ dsB+ connect n1 n2 =+ let+ common = [ va*vb | (ka,va) <- M.findWithDefault [] (p3,n1,n2) dsAMap, (kb,vb) <- M.findWithDefault [] (p5,n1,n2) dsBMap, ka==kb ]+ c = if null common+ then eInf+ else junction ! (((lenLA,lenRA) `lookup` knownDoubleNCM),((lenLB,lenRB) `lookup` knownDoubleNCM)) -- junction score between two NCMs+ + (logScore $ sum common)+ in c+ lookup k = snd . fromJust . VU.find ((==k).fst)+ normalize xs+ | null xs = xs+ | otherwise = map (second (/total)) xs+ where total = sum $ map snd xs++-- | Generates the array of all NCMs. We add the score for the closing pair+-- (hinge.db) directly here.++toNCMArray :: PairScoreArray -> [Cycle] -> PrimArray HashedPrimary Double+toNCMArray pairScores xs+ | null xs = error "toNCMArray expects non-empty list of Cycles"+ | otherwise = fromAssocs l u z $ map f xs+ where+ lp = replicate (length . fst $ head xs) (minExtended :: Nucleotide)+ up = replicate (length . fst $ head xs) (maxExtended :: Nucleotide)+ l = mkci $ mkPrimary lp+ u = mkci $ mkPrimary up+ z = eInf+ mkci s = mkHashedPrimary (minExtended,maxExtended) s+ f (s,v) =+ let+ p = mkPrimary s+ pS = pairScores ! (VU.head p, VU.last p)+ in (mkci p,v + pS)++++-- * Parsers for different files++-- | parser for junction.db++parseJunction :: GenParser B.ByteString st [Double]+parseJunction = many1 (doubles <* spaces) <* eof where+ doubles = try (const eInf <$> string "+inf") <|> floatX++-- | parser for hinge.db Returns scores for individual pairs.++parsePairScores :: GenParser B.ByteString st [Double]+parsePairScores = (\a b -> a ++ b) <$> fl <*> ls where+ fl = many1 (read <$> many1 digit <* spaces) -- the 5 integers in the top line+ ls = many1 (doubles <* spaces) <* eof -- the 5x5 matrix of doubles+ doubles = try (const eInf <$> string "+inf") <|> floatX++-- | parser for NCM database (*.cycle)++parseCycle :: GenParser B.ByteString st [Cycle]+parseCycle = many1 (cycle <* newline) <* eof where+ cycle :: GenParser B.ByteString st Cycle+ cycle = (\a b -> (a,b)) <$> many1 letter <* ws <*> floatX++-- many ws characters++ws = many $ char ' '++-- | helper function for the strange double values+--+-- TODO move floatX into HsTools!++floatX :: GenParser B.ByteString st Double+floatX = toDouble <$> prefix <*> many digit <*> char '.' <*> many digit where+ prefix = char '+' <|> char '-'+ toDouble '+' ds1 dot ds2 = read $ ds1 ++ [dot] ++ ds2+ toDouble '-' ds1 dot ds2 = read $ "-" ++ ds1 ++ [dot] ++ ds2++-- | new hinge parser++parseHinge :: GenParser B.ByteString st [RawHinge]+parseHinge = concat <$> many hinge <* eof where+ mkap "anti" = anti+ mkap "para" = para+ mktc "trans" = trans+ mktc "cis" = cis+ mksp x = case x of+ 'S' -> ssp+ 'H' -> hsp+ 'W' -> wsp+ 'B' -> bsp+ 'C' -> csp+ _ -> error $ "parseHinge: " ++ [x]+ hinge :: GenParser B.ByteString st [RawHinge]+ -- use monad format to check opening / closing equality+ hinge = do+ string "[ "+ n53 <- digit+ let primeType = if n53 == '5' then p5 else p3+ string "' "+ b1 <- oneOf "ACGU"+ string " "+ b2 <- oneOf "ACGU"+ string " ]"+ newline+ hts <- many (try hingetype)+ return $ map (\((s1,s2,ap,tr),count) -> (((primeType,mkNuc b1,mkNuc b2),(s1,s2,ap,tr)),count)) hts+ hingetype :: GenParser B.ByteString st ((Slash,Slash,AntiPara,TransCis),Double)+ hingetype = mkht+ <$> hw+ <* space+ <*> (try (string "anti") <|> string "para")+ <* space+ <*> (try (string "trans") <|> string "cis")+ <* space+ <*> many1 digit+ <* newline+ mkht (a:_:b:[]) ap tc cnt = ((mksp a, mksp b, mkap ap, mktc tc), read cnt)+ hw = many1 (char '/' <|> letter)++++-- * Types++type Cycle = (String,Double)
+ Biobase/DataSource/Mafft.hs view
@@ -0,0 +1,50 @@++-- | Mafft data.+--+-- NOTE: For the "-" strand, the start position is given by ("genome size" -+-- "start position" + "length")+--+-- TODO mafft blocks contain "i" parts which i haven't seen yet. These have to+-- be parsed, too.++module Biobase.DataSource.Mafft where++import qualified Data.ByteString.Lazy.Char8 as BS++++-- | A complete Mafft file.++data Mafft = Mafft+ { comments :: [BS.ByteString]+ , blocks :: [Block]+ }+ deriving (Show)++-- | One Mafft block.+--+-- THERE is "a ", "i ", "s "++data Block = Block+ { alignment :: BS.ByteString+ , sequences :: [Sequence]+ }+ deriving (Show)++-- | Encodes one sequence entry.++data Sequence = Sequence+ { species :: BS.ByteString+ , start :: Int+ , length :: Int+ , strand :: PlusMinus+ , genomeSize :: Int+ , alignedSequence :: CompressedBS+ }+ deriving (Show)++newtype PlusMinus = PlusMinus Char+ deriving (Eq,Show)++newtype CompressedBS = CompressedBS BS.ByteString+ deriving (Eq,Show)
+ Biobase/DataSource/Mafft/Import.hs view
@@ -0,0 +1,74 @@++-- | Imports a mafft file. The mafft file may be gzip-compressed, as long as+-- the filename contains a ".gz" suffix. Files without ".gz" suffix are treated+-- as uncrompressed.++module Biobase.DataSource.Mafft.Import+ ( fromFile+ ) where++import qualified Codec.Compression.GZip as GZip+import System.FilePath (takeExtension)+import qualified Data.ByteString.Lazy.Char8 as BS+import Text.Parsec hiding (many,(<|>))+import Text.Parsec.ByteString.Lazy+import Control.Applicative++import Biobase.DataSource.Mafft++++test = fromFile "tba.maf.gz"++-- | Import 'Mafft' from file.++fromFile :: FilePath -> IO (Either String Mafft)+fromFile fname = do+ content <- if (takeExtension fname == ".gz")+ then GZip.decompress `fmap` BS.readFile fname+ else BS.readFile fname+ res <- return $ runP pFile () fname content+ case res of+ Left err -> return . Left $ show err+ Right m -> return . Right $ m++-- | Parses one comment line.++pComment :: GenParser Char st BS.ByteString+pComment = BS.pack <$ char '#' <*> manyTill anyChar newline++-- | Parses many comment lines.++pComments :: GenParser Char st [BS.ByteString]+pComments = many pComment++-- | Parses one complete 'Block'.++pBlock :: GenParser Char st Block+pBlock = Block <$> pAli <*> many1 pSequence where+ pAli = BS.pack <$ char 'a' <*> manyTill anyChar newline <?> "expecting alignment (score)"++-- | Parses many 'Block's.++pBlocks :: GenParser Char st [Block]+pBlocks = (try $ pBlock <* newline) `manyTill` (string "##eof maf" <* spaces <* eof)++-- | The Mafft file parser.++pFile :: GenParser Char st Mafft+pFile = Mafft <$> pComments <*> pBlocks++-- | Parses one 'Sequence' line.++pSequence :: GenParser Char st Sequence+pSequence = Sequence <$ string "s " <*> sname <*> sstart <*> slength <*> sstrand <*> sgenomesize <*> salisequence where+ sname = BS.pack <$> manyTill alphaNum (many1 space)+ sstart = read <$> number <* spaces+ slength = read <$> number <* spaces+ sstrand = PlusMinus <$> (char '+' <|> char '-') <* spaces+ sgenomesize = read <$> number <* spaces+ salisequence = CompressedBS . GZip.compress . BS.pack <$> manyTill anyChar newline++-- | Parses an integral number.++number = many1 digit
+ Biobase/DataSource/Turner.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE TypeSynonymInstances #-}++-- | Mathews / Turner nearest neighbor energy tables for interactions between+-- RNA-RNA and DNA-DNA. Using lazy tables for easy filling of missing data.+-- Transform tables into uvectors for efficient access.++module Biobase.DataSource.Turner where++import Biobase.RNA (Nucleotide)+import qualified Biobase.DataSource.Turner.Tables as T++++-- | Data structure containing all necessary tables for the Turner 2004 model.+-- Note the temperature, using an additional function, rescaling becomes+-- possible. A Show and a Read instance are automatically derived but one+-- should use the Turner and/or Vienna import/export facilities. All data uses+-- complete tables, where any base can pair with any other. Missing data ("."+-- in tables) is given by 'Nothing', otherwise we have 'Just Int'.+-- +-- In general, have a look here:+-- <http://rna.urmc.rochester.edu/NNDB/turner04/index.html> where+-- parameters are explained.+-- +-- Conversion from Turner to Vienna is only possible in one direction as a+-- number of parameters are not used in Vienna RNA Folding.++++-- We are missing tables for DNA-RNA data: helixdr.dat, stackdr.dat,+-- stackdr.dh. Several other files have unknown data, too. These are:+-- dnadynalign*, fam\_hmm\_pars.dat, helix.dat, int22-exp.dh++type TurnerTables = T.Turner2004 Basepair Nucleotide Double++type TurnerEntropy = TurnerTables+type TurnerEnthalpy = TurnerTables+type Temperature = Double+type TurnerSet = (Temperature,TurnerEntropy,TurnerEnthalpy)++type Basepair = (Nucleotide,Nucleotide)
+ Biobase/DataSource/Turner/Import.hs view
@@ -0,0 +1,176 @@+{-# LANGUAGE NoMonomorphismRestriction #-}++-- | Turner file parser. Returns a Turner2004 data structure. We store data in+-- the same way it is stored in the ViennaRNA package. Pairs are tuples+-- however.+--+-- How is 'stack' data stored:+--+-- AX+-- UY -> ((A,U),(Y,X))+--+-- How 'iloop1x1' is stored:+--+-- X+-- A G+-- U C -> ((A,U),(C,G),X,Y)+-- Y+--+-- Now 'iloop1x2' is stored:+--+-- X+-- A G+-- U C -> ((A,U),(C,G),X,C,Y), single (X) first, then 5' to 3'+-- YC+--+-- 'iloop2x2' is stored:+--+-- XY+-- A G+-- U C -> ((A,U),(C,G),X,Y,y,x), X-->Y then x<--y+-- xy+--+--TODO not sure if dangle3/dangle5 are correctly split or if they should switch++module Biobase.DataSource.Turner.Import+ ( parseTurner+ ) where++import Control.Applicative+import Control.Arrow (first)+import Control.Monad+import Data.Either+import Data.List.Split (splitEvery)+import Data.List (transpose)+import qualified Data.Map as M+import System.FilePath.Find+import Text.Parsec hiding ((<|>), many)+import Text.Parsec.String++import Biobase.RNA+import Data.Ix.Tuple+import Data.PrimitiveArray+import Data.PrimitiveArray.Ix+import Text.Parsec.Numbers++import Biobase.DataSource.Turner.Tables++++-- * Associate every file with a parse.++minp = (nucA,nucA)+maxp = (nucU,nucU)+minpb = (minp,nucA)+maxpb = (maxp,nucU)+minpp = (minp,minp)+maxpp = (maxp,maxp)+minppbb = (minp,minp,nucA,nucA)+maxppbb = (maxp,maxp,nucU,nucU)+minppbbb = (minp,minp,nucA,nucA,nucA)+maxppbbb = (maxp,maxp,nucU,nucU,nucU)+minppbbbb = (minp,minp,nucA,nucA,nucA,nucA)+maxppbbbb = (maxp,maxp,nucU,nucU,nucU,nucU)+minpbb = (minp,nucA,nucA)+maxpbb = (maxp,nucU,nucU)+-- (4,3) switched for vienna rna compatibility+keyspp = [((k1,k2),(k4,k3)) | k1 <- acgu, k3 <- acgu, k2 <- acgu, k4 <- acgu]+keyspb = [((k1,k2),k3) | k1 <- acgu, k2 <- acgu, k3 <- acgu]+keyspbb = [((k1,k2),k3,k4) | k1 <- acgu, k3 <- acgu, k2 <- acgu, k4 <- acgu]+plist11 = [(nucA,nucU),(nucC,nucG),(nucG,nucC),(nucU,nucA),(nucG,nucU),(nucU,nucG)]+plist22 = [(nucA,nucU),(nucC,nucG),(nucG,nucC),(nucG,nucU),(nucU,nucA),(nucU,nucG)]+-- (4,3) switched for vienna rna compatibility+keysppbb = [((k1,k2),(k4,k3),k5,k6) | (k1,k2) <- plist11, k5 <- acgu, (k3,k4) <- plist11, k6 <- acgu]+-- (4,3) switched for vienna rna compatibility+keysppbbb = [((k1,k2),(k4,k3),k5,k6,k7) | (k1,k2) <- plist11, k6 <- acgu, k5 <- acgu, (k3,k4) <- plist11, k7 <- acgu]+-- (4,3) switched for vienna rna compatibility, 5786 is 5'3' order top, bottom!+keysppbbbb = [((k1,k2),(k4,k3),k5,k6,k7,k8) | (k1,k2) <- plist22, (k3,k4) <- plist22, k5 <- acgu, k8 <- acgu, k6 <- acgu, k7 <- acgu]+z = 999999++++-- | Given the base dir and a suffix (.dat/.dh most likely), parse the relevant+-- files. The prefix can be used for, eg., dna file++parseTurner prefix basedir fsuffix = do+ vstack <- grabB basedir fsuffix $ prefix ++ "stack"+ vdangles <- grabB basedir fsuffix $ prefix ++ "dangle"+ vlengths <- grabB basedir fsuffix $ prefix ++ "loop"+ vhairmm <- grabB basedir fsuffix $ prefix ++ "tstackh"+ viloopmm <- grabB basedir fsuffix $ prefix ++ "tstacki"+ viloop23mm <- grabB basedir fsuffix $ prefix ++ "tstacki23"+ viloop1nmm <- grabB basedir fsuffix $ prefix ++ "tstacki1n"+ vmultimm <- grabB basedir fsuffix $ prefix ++ "tstackm"+ vextmm <- grabB basedir fsuffix $ prefix ++ "tstack"+ viloop11 <- grabB basedir fsuffix $ prefix ++ "int11"+ viloop12 <- grabB basedir fsuffix $ prefix ++ "int21"+ viloop22 <- grabB basedir fsuffix $ prefix ++ "int22"+ vlookups <- fmap (map (first (map mkNuc)) . concat) $ mapM (\f -> grabA basedir fsuffix $ prefix ++ f) ["triloop","tloop","hexaloop"]+ vmisc <- grabB basedir fsuffix $ prefix ++ "miscloop"+ let (vdangle3,vdangle5) = splitAt (length vdangles `div` 2) vdangles+ let (_:viloopl:vbulgel:vhairpinl:[]) = transpose $ splitEvery 4 vlengths+ return $ Turner2004+ { stack = fromAssocs minpp maxpp z $ zip keyspp vstack+ , dangle3 = fromAssocs minpb maxpb z $ zip keyspb vdangle3+ , dangle5 = fromAssocs minpb maxpb z $ zip keyspb vdangle5+ , hairpinL = fromAssocs 0 30 z $ zip [1..] vhairpinl+ , bulgeL = fromAssocs 0 30 z $ zip [1..] vbulgel+ , iloopL = fromAssocs 0 30 z $ zip [1..] viloopl+ , hairpinMM = fromAssocs minpbb maxpbb z $ zip keyspbb vhairmm+ , iloopMM = fromAssocs minpbb maxpbb z $ zip keyspbb viloopmm+ , iloop2x3MM = fromAssocs minpbb maxpbb z $ zip keyspbb viloop23mm+ , iloop1xnMM = fromAssocs minpbb maxpbb z $ zip keyspbb viloop1nmm+ , multiMM = fromAssocs minpbb maxpbb z $ zip keyspbb vmultimm+ , extMM = fromAssocs minpbb maxpbb z $ zip keyspbb vextmm+ , hairpinLookup = M.fromList vlookups+ , iloop1x1 = fromAssocs minppbb maxppbb z $ zip keysppbb viloop11+ , iloop1x2 = fromAssocs minppbbb maxppbbb z $ zip keysppbbb viloop12+ , iloop2x2 = fromAssocs minppbbbb maxppbbbb z $ zip keysppbbbb viloop22+ , ninio = vmisc !! 2+ , maxNinio = vmisc !! 1+ , multiOffset = vmisc !! 6+ , multiNuc = vmisc !! 7+ , multiHelix = vmisc !! 8+ , largeLoop = vmisc !! 0+ , termAU = vmisc !! 14+ , intermolecularInit = vmisc !! 19+ }++grabB basedir fsuffix fname = do+ p <- parseFromFile pBlockFile (basedir ++ "/" ++ fname ++ fsuffix)+ case p of+ (Right ans) -> return ans+ (Left err) -> error $ show err++grabA basedir fsuffix fname = do+ p <- parseFromFile pAssocFile (basedir ++ "/" ++ fname ++ fsuffix)+ case p of+ (Right ans) -> return ans+ (Left err) -> error $ show err++++-- * File parser: We do not want to understand the format, just extract all+-- data.++-- | Blocks of data.++pBlockFile = concat <$> many (try numberRow <|> infoRow) <* eof where+ -- a line with a least one number+ numberRow = many (char ' ') *> (number <* notFollowedBy (char '\'')) `sepEndBy1` (many $ char ' ') <* newline+ -- a number is a dot or some extended floating point number+ number = (try dotFloat) <|> (999999 <$ char '.') <|> parseExtFloat <?> "floating point number"++-- | A File with associations.++pAssocFile = concat <$> many1 (try assocRow <|> infoRow) where+ -- one assocs of string, value+ assocRow = (\a b -> [(a,b)]) <$ many (char ' ') <*> many1 (oneOf nuc) <* many (char ' ') <*> parseExtFloat <* many (char ' ')++-- a line with crap+infoRow = [] <$ anyChar `manyTill` newline++-- a rather stupid float+dotFloat = (\s a b -> read $ s:'0':a:b) <$> (char '-' <|> pure ' ') <*> char '.' <*> many1 digit++nuc = "ACGUT"
+ Biobase/DataSource/Turner/Tables.hs view
@@ -0,0 +1,133 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TypeSynonymInstances #-}++-- | Turner Nearest Neighbor Energy Tables}++-- TODO (Read) instance? (Vector has no Read instance...)++module Biobase.DataSource.Turner.Tables where++import qualified Data.Map as M++import Data.PrimitiveArray+import Data.PrimitiveArray.Ix++++-- | A data structure describing all fields as used by the Turner 2004+-- parameter set. Some fields are commented out until they are being used.++data Turner2004 a b c = Turner2004+ { stack :: PrimArray (a,a) c+ , dangle3 :: PrimArray (a,b) c+ , dangle5 :: PrimArray (a,b) c+ , hairpinL :: PrimArray Int c+ , hairpinMM :: PrimArray (a,b,b) c+ , hairpinLookup :: M.Map [b] c+-- , hairpinGGG :: c+-- , hairpinCslope :: c+-- , hairpinCintercept :: c+-- , hairpinC3 :: c+ , bulgeL :: PrimArray Int c+-- , bulgeSingleC :: c+ , iloop1x1 :: PrimArray (a,a,b,b) c+ , iloop1x2 :: PrimArray (a,a,b,b,b) c+ , iloop2x2 :: PrimArray (a,a,b,b,b,b) c+ , iloopMM :: PrimArray (a,b,b) c+ , iloop2x3MM :: PrimArray (a,b,b) c+ , iloop1xnMM :: PrimArray (a,b,b) c+ , iloopL :: PrimArray Int c+ , multiMM :: PrimArray (a,b,b) c+ , ninio :: c+ , maxNinio :: c+ , multiOffset :: c+ , multiNuc :: c+ , multiHelix :: c+-- , multiAsym :: c+-- , multiStrain :: c+ , extMM :: PrimArray (a,b,b) c+-- , coaxStack :: PrimArray (a,a) c+-- , coaxStackOpen :: PrimArray (a,b,b) c+-- , coaxStackCont :: PrimArray (a,b,b) c+ , largeLoop :: Double+ , termAU :: c+ , intermolecularInit :: c+ }++++-- | Map functions over the payload.++dmap f Turner2004{..} = Turner2004+ { stack = amap f stack+ , dangle3 = amap f dangle3+ , dangle5 = amap f dangle5+ , hairpinL = amap f hairpinL+ , hairpinMM = amap f hairpinMM+ , hairpinLookup = fmap f hairpinLookup+-- , hairpinGGG = f hairpinGGG+-- , hairpinCslope = f hairpinCslope+-- , hairpinCintercept = f hairpinCintercept+-- , hairpinC3 = f hairpinC3+ , bulgeL = amap f bulgeL+-- , bulgeSingleC = f bulgeSingleC+ , iloop1x1 = amap f iloop1x1+ , iloop1x2 = amap f iloop1x2+ , iloop2x2 = amap f iloop2x2+ , iloopMM = amap f iloopMM+ , iloop2x3MM = amap f iloop2x3MM+ , iloop1xnMM = amap f iloop1xnMM+ , iloopL = amap f iloopL+ , multiMM = amap f multiMM+ , ninio = f ninio+ , maxNinio = f maxNinio+ , multiOffset = f multiOffset+ , multiNuc = f multiNuc+ , multiHelix = f multiHelix+-- , multiAsym = f multiAsym+-- , multiStrain = f multiStrain+ , extMM = amap f extMM+-- , coaxStack = amap f coaxStack+-- , coaxStackOpen = amap f coaxStackOpen+-- , coaxStackCont = amap f coaxStackCont+ , largeLoop = largeLoop+ , termAU = f termAU+ , intermolecularInit = f intermolecularInit+ }++++-- | Zip two payloads.+--+-- TODO right now, we have undefined behaviour when some arrrays are of different length++dZipWith f t1 t2 = Turner2004+ { stack = zipWithPA f (stack t1) (stack t2)+ , dangle3 = zipWithPA f (dangle3 t1) (dangle3 t2)+ , dangle5 = zipWithPA f (dangle5 t1) (dangle5 t2)+ , hairpinL = zipWithPA f (hairpinL t1) (hairpinL t2)+ , hairpinMM = zipWithPA f (hairpinMM t1) (hairpinMM t2)+ , hairpinLookup = undefined -- zipWithPA f (hairpinLookup t1) (hairpinLookup t2)+ , bulgeL = zipWithPA f (bulgeL t1) (bulgeL t2)+ , iloop1x1 = zipWithPA f (iloop1x1 t1) (iloop1x1 t2)+ , iloop1x2 = zipWithPA f (iloop1x2 t1) (iloop1x2 t2)+ , iloop2x2 = zipWithPA f (iloop2x2 t1) (iloop2x2 t2)+ , iloopMM = zipWithPA f (iloopMM t1) (iloopMM t2)+ , iloop2x3MM = zipWithPA f (iloop2x3MM t1) (iloop2x3MM t2)+ , iloop1xnMM = zipWithPA f (iloop1xnMM t1) (iloop1xnMM t2)+ , iloopL = zipWithPA f (iloopL t1) (iloopL t2)+ , multiMM = zipWithPA f (multiMM t1) (multiMM t2)+ , ninio = f (ninio t1) (ninio t2)+ , maxNinio = f (maxNinio t1) (maxNinio t2)+ , multiOffset = f (multiOffset t1) (multiOffset t2)+ , multiNuc = f (multiNuc t1) (multiNuc t2)+ , multiHelix = f (multiHelix t1) (multiHelix t2)+ , extMM = zipWithPA f (extMM t1) (extMM t2)+ , largeLoop = largeLoop t1 -- no zipping here! TODO make this a constant somewhere!+ , termAU = f (termAU t1) (termAU t2)+ , intermolecularInit = f (intermolecularInit t1) (intermolecularInit t2)+ }++zipWithPA f a1 a2 = let (l,u) = bounds a1 in fromList l u $ zipWith f (toList a1) (toList a2)
+ Biobase/DataSource/Vienna.hs view
@@ -0,0 +1,96 @@+{-# LANGUAGE NoMonomorphismRestriction #-}++-- | Turner energy data as used in the ViennaRNA package.+--+-- TODO should use energy type for tables, not int!++module Biobase.DataSource.Vienna where++import Data.Map (Map,empty)++import Data.Ix.Tuple+import Data.PrimitiveArray+import Data.PrimitiveArray.Ix++import Biobase.Constants+import Biobase.DataSource.Turner.Tables+import Biobase.RNA+import Biobase.RNA.NucBounds+import Biobase.RNA.ViennaPair+import Biobase.Types.Energy+import Biobase.Types.Partition++++-- Type for Vienna Tables++-- type ViennaEnergySet = (Temperature, ViennaTables, ViennaTables)++type ViennaIntTables = Turner2004 ViennaPair Nucleotide Int+type ViennaEnergyTables = Turner2004 ViennaPair Nucleotide Energy+type ViennaPartitionTables = Turner2004 ViennaPair Nucleotide Partition++type Temperature = Double++++-- | An empty Turner2004 set, with Vienna-style keys for tables. Unused fields+-- are commented out. Activate them in BiobaseTurner before doing the same+-- here!++emptyTables :: ViennaIntTables+emptyTables = Turner2004+ --stack+ { stack = emptyIV+ --dangle+ , dangle3 = emptyPB+ , dangle5 = emptyPB+ --hairpin+ , hairpinL = emptyV+ , hairpinMM = emptyIV+ , hairpinLookup = empty+ --eInf+ --eInf+ --eInf+ --eInf+ --bulge+ , bulgeL = emptyV+ --eInf+ --internal+ , iloop1x1 = emptyPPBB+ , iloop1x2 = emptyPPBBB+ , iloop2x2 = emptyPPBBBB+ , iloopMM = emptyPBB+ , iloop2x3MM = emptyPBB+ , iloop1xnMM = emptyPBB+ , iloopL = emptyV+ --multibranch+ , multiMM = emptyPBB+ , ninio = eInf+ , maxNinio = eInf+ , multiOffset = eInf+ , multiNuc = eInf+ , multiHelix = eInf+ --eInf+ --eInf+ --exterior+ , extMM = emptyPBB+ --coaxial stacking+ --emptyIV+ --emptyIV+ --emptyIV+ --scalar values+ , largeLoop = eInf -- large loop is always double+ , termAU = eInf+ , intermolecularInit = eInf+ }++emptyIV = fromAssocs minExtended maxExtended eInf []+emptyPB = fromAssocs minExtended (maxBound,nucU) eInf []+emptyPBB = fromAssocs minExtended (maxBound,nucU,nucU) eInf []+emptyPPBB = fromAssocs minExtended (maxBound,maxBound,nucU,nucU) eInf []+emptyPPBBB = fromAssocs minExtended (maxBound,maxBound,nucU,nucU,nucU) eInf []+emptyPPBBBB = fromAssocs minExtended (maxBound,maxBound,nucU,nucU,nucU,nucU) eInf []++-- TODO should be an empty a+emptyV = fromAssocs 0 30 eInf []
+ Biobase/DataSource/Vienna/Default.hs view
@@ -0,0 +1,27 @@++{-# LANGUAGE TemplateHaskell #-}++-- | Embedding of a default set of parameters. These are encoded in Vienna style and+-- use the Turner2004 set of parameters.++module Biobase.DataSource.Vienna.Default+ ( turner2004GH+ ) where++import Data.FileEmbed+import qualified Data.ByteString.Char8 as B++import Biobase.DataSource.Vienna.Import.ViennaPar+import Biobase.DataSource.Turner.Tables+import Biobase.DataSource.Vienna+import Biobase.Types.Energy++++defaultPars :: B.ByteString+defaultPars = $(embedFile "parfiles/Turner2004GH.par")++-- Turner entropy and enthalpy tables.++turner2004GH = (dmap Energy ta,dmap Energy tb) where+ (ta,tb) = importPar $ B.unpack defaultPars
+ Biobase/DataSource/Vienna/Export/ViennaC.hs view
@@ -0,0 +1,264 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}++-- | Exports the Vienna energy tables as a number of C files (one .c file, a+-- number .h files). For this reason, files are written into a target+-- directory!++module Biobase.DataSource.Vienna.Export.ViennaC+ ( export+ ) where++import Prelude hiding (pi)+import Text.Printf+import System.Directory+import Data.List.Split+import Data.List+import qualified Data.Map as M+import Data.FileEmbed+import qualified Data.ByteString.Char8 as B++import Biobase.DataSource.Turner.Tables+import Biobase.DataSource.Vienna+import Data.PrimitiveArray+import Biobase.RNA++import Biobase.DataSource.Vienna.Default++(g,h) = turner2004GH++++type Directory = FilePath++-- | Export the files required for default values in the ViennaRNA 2.0 C+-- package.++export :: ViennaIntTables -> ViennaIntTables -> Directory -> IO ()+export trnrG trnrH target = mapM_ (\f -> f trnrG trnrH target) [exportC, export11, export21, export22]++++-- | Export the main C file++exportC :: ViennaIntTables -> ViennaIntTables -> Directory -> IO ()+exportC trnrG trnrH target = writeFile (target ++ "/energy_par.c") out where+ out = unlines [ B.unpack $(embedFile "templates/cheader") , xs, stck, lps, mms, dngls, tris, tets, hexs,includes]+ xs = unlines+ [ pd "lxc37" $ largeLoop trnrG+ , pi "ML_intern37" $ multiHelix trnrG+ , pi "ML_interndH" $ multiHelix trnrH+ , pi "ML_closing37" $ multiOffset trnrG+ , pi "ML_closingdH" $ multiOffset trnrH+ , pi "ML_BASE37" $ multiNuc trnrG+ , pi "ML_BASEdH" $ multiNuc trnrH+ , pi "MAX_NINIO" $ maxNinio trnrG+ , pi "ninio37" $ ninio trnrG+ , pi "niniodH" $ ninio trnrH+ , pi "TerminalAU37" $ termAU trnrG+ , pi "TerminalAUdH" $ termAU trnrH+ , pi "DuplexInit37" $ intermolecularInit trnrG+ , pi "DuplexInitdH" $ intermolecularInit trnrH+ , pi "TripleC37" 100+ , pi "TripleCdH" 1860+ , pi "MultipleCA37" 30+ , pi "MultipleCAdH" 340+ , pi "MultipleCB37" 160+ , pi "MultipleCBdH" 760+ ]+ stck = unlines+ [ "PUBLIC int stack37[NBPAIRS+1][NBPAIRS+1] ="+ , (block2 8 . toList $ stack trnrG)+ , "PUBLIC int stackdH[NBPAIRS+1][NBPAIRS+1] ="+ , (block2 8 . toList $ stack trnrH)+ ]+ lps = unlines+ [ "PUBLIC int hairpin37[31] = {" ++ (concat . intersperse "," . map printNum . toList $ hairpinL trnrG) ++ "};"+ , "PUBLIC int hairpindH[31] = {" ++ (concat . intersperse "," . map printNum . toList $ hairpinL trnrH) ++ "};"+ , "PUBLIC int bulge37[31] = {" ++ (concat . intersperse "," . map printNum . toList $ bulgeL trnrG) ++ "};"+ , "PUBLIC int bulgedH[31] = {" ++ (concat . intersperse "," . map printNum . toList $ bulgeL trnrH) ++ "};"+ , "PUBLIC int internal_loop37[31] = {" ++ (concat . intersperse "," . map printNum . toList $ iloopL trnrG) ++ "};"+ , "PUBLIC int internal_loopdH[31] = {" ++ (concat . intersperse "," . map printNum . toList $ iloopL trnrH) ++ "};"+ ]+ mms = unlines+ [ writeMM "I" iloopMM trnrG trnrH+ , writeMM "H" hairpinMM trnrG trnrH+ , writeMM "M" multiMM trnrG trnrH+ , writeMM "1nI" iloop1xnMM trnrG trnrH+ , writeMM "23I" iloop2x3MM trnrG trnrH+ , writeMM "Ext" extMM trnrG trnrH+ ]+ dngls = unlines+ [ "PUBLIC int dangle3_37[NBPAIRS+1][5] ="+ , block2 5 . toList $ dangle3 trnrG+ , "PUBLIC int dangle3_dH[NBPAIRS+1][5] ="+ , block2 5 . toList $ dangle3 trnrH+ , "PUBLIC int dangle5_37[NBPAIRS+1][5] ="+ , block2 5 . toList $ dangle5 trnrG+ , "PUBLIC int dangle5_dH[NBPAIRS+1][5] ="+ , block2 5 . toList $ dangle5 trnrH+ ]+ t3 = getLookup 3 trnrG trnrH+ t4 = getLookup 4 trnrG trnrH+ t6 = getLookup 6 trnrG trnrH+ tris = writeTabbed 3 "Triloop" t3+ tets = writeTabbed 4 "Tetraloop" t4+ hexs = writeTabbed 6 "Hexaloop" t6++ includes = unlines $ map ((++ "\"") . ("#include \""++))+ [ "intl11.h"+ , "intl11dH.h"+ , "intl21.h"+ , "intl21dH.h"+ , "intl22.h"+ , "intl22dH.h"+ ]++++-- | Export iloops 1x1++export11 :: ViennaIntTables -> ViennaIntTables -> Directory -> IO ()+export11 trnrG trnrH target = writeFile (target ++ "/intl11.h") outG >> writeFile (target ++ "/intl11dH.h") outH where+ outG = unlines+ [ "PUBLIC int int11_37[NBPAIRS+1][NBPAIRS+1][5][5] ="+ , (block4 8 5 5 . toList $ iloop1x1 trnrG)+ ]+ outH = unlines+ [ "PUBLIC int int11_dH[NBPAIRS+1][NBPAIRS+1][5][5] ="+ , (block4 8 5 5 . toList $ iloop1x1 trnrH)+ ]++++-- | Export iloops 2x1++export21 :: ViennaIntTables -> ViennaIntTables -> Directory -> IO ()+export21 trnrG trnrH target = writeFile (target ++ "/intl21.h") outG >> writeFile (target ++ "/intl21dH.h") outH where+ outG = unlines+ [ "PUBLIC int int21_37[NBPAIRS+1][NBPAIRS+1][5][5][5] ="+ , (block5 8 5 5 5 . toList $ iloop1x2 trnrG)+ ]+ outH = unlines+ [ "PUBLIC int int21_dH[NBPAIRS+1][NBPAIRS+1][5][5][5] ="+ , (block5 8 5 5 5 . toList $ iloop1x2 trnrH)+ ]++++-- | Export iloops 2x2++export22 :: ViennaIntTables -> ViennaIntTables -> Directory -> IO ()+export22 trnrG trnrH target = writeFile (target ++ "/intl22.h") outG >> writeFile (target ++ "/intl22dH.h") outH where+ outG = unlines+ [ "PUBLIC int int22_37[NBPAIRS+1][NBPAIRS+1][5][5][5][5] ="+ , (block6 8 5 5 5 5 . toList $ iloop2x2 trnrG)+ ]+ outH = unlines+ [ "PUBLIC int int22_dH[NBPAIRS+1][NBPAIRS+1][5][5][5][5] ="+ , (block6 8 5 5 5 5 . toList $ iloop2x2 trnrH)+ ]++++-- * Helper functions++writeTabbed (ksize :: Int) key (ns,gs,hs) = unlines+ [ printf "PUBLIC char %ss[%d] =" key ((ksize+3)*40+1)+ , ns+ , ";"+ ] ++ printf "PUBLIC int %s37[40] = " key ++ gs ++ ";\n"+ ++ printf "PUBLIC int %sdH[40] = " key ++ hs ++ ";\n"++getLookup k trnrG trnrH = (nsF,gs,hs) where+ nsF = concat $ intersperse "\n" $ map ((++ " \"") . (" \"" ++) . map fromNuc) ns+ ns = filter ((==(k+2)) . length) . M.keys $ hairpinLookup trnrG+ gs = lkup trnrG+ hs = lkup trnrH+ lkup tbl = ("{"++) . (++"}") . concat . intersperse "," $ map (printNum . (hairpinLookup tbl M.!)) ns++writeMM typ fun trnrG trnrH = unlines+ [ printf "PUBLIC int mismatch%s37[NBPAIRS+1][5][5] =" typ+ , block3 5 5 . toList $ fun trnrG+ , printf "PUBLIC int mismatch%sdH[NBPAIRS+1][5][5] =" typ+ , block3 5 5 . toList $ fun trnrH+ ]++block2 s2 xs+ = (++ "};")+ . ("{" ++)+ . concat+ . intersperse "\n,"+ . map ((++ "}") . ("{" ++) . concat . intersperse ",")+ . splitEvery s2+ $ map printNum xs++block3 s2 s3 xs+ = (++ "};")+ . ("{" ++)+ . concat+ . intersperse "\n,"+ . map ((++ "}") . ("{" ++) . concat . intersperse ",")+ . splitEvery s2+ . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")+ . splitEvery s3+ $ map printNum xs++block4 s2 s3 s4 xs+ = (++ "};")+ . ("{" ++)+ . concat+ . intersperse "\n,"+ . map ((++ "}") . ("{" ++) . concat . intersperse ",")+ . splitEvery s2+ . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")+ . splitEvery s3+ . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")+ . splitEvery s4+ $ map printNum xs++block5 s2 s3 s4 s5 xs+ = (++ "};")+ . ("{" ++)+ . concat+ . intersperse "\n,"+ . map ((++ "}") . ("{" ++) . concat . intersperse ",")+ . splitEvery s2+ . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")+ . splitEvery s3+ . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")+ . splitEvery s4+ . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")+ . splitEvery s5+ $ map printNum xs++block6 s2 s3 s4 s5 s6 xs+ = (++ "};")+ . ("{" ++)+ . concat+ . intersperse "\n,"+ . map ((++ "}") . ("{" ++) . concat . intersperse ",")+ . splitEvery s2+ . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")+ . splitEvery s3+ . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")+ . splitEvery s4+ . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")+ . splitEvery s5+ . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")+ . splitEvery s6+ $ map printNum xs+++pd :: String -> Double -> String+pd k v = printf "PUBLIC double %s=%f;" k v++pi :: String -> Int -> String+pi k v = printf "PUBLIC int %s=%d;" k v++printNum :: Int -> String+printNum n+ | n >= maxN = " INF"+ | otherwise = printf "%6d" n+ where+ maxN = 10000
+ Biobase/DataSource/Vienna/Export/ViennaPar.hs view
@@ -0,0 +1,140 @@++{-# LANGUAGE NoMonomorphismRestriction #-}++module Biobase.DataSource.Vienna.Export.ViennaPar+ ( export+ ) where++import Data.Tuple.Select+import Data.List.Split+import Text.Printf+import Control.Arrow+import Data.List (intersperse)+import qualified Data.Map as M++import Data.PrimitiveArray+import Biobase.DataSource.Turner.Tables+import Biobase.RNA+import Biobase.RNA.ViennaPair+import Biobase.Constants++import Biobase.DataSource.Vienna++++export :: ViennaIntTables -> ViennaIntTables -> String+export trnr trnrH = hdr ++ blocks ++ mlps ++ ninios ++ misc ++ triloops ++ tetra ++ hexa ++ "\n#END" where+ hdr = "## RNAfold parameter file v2.0\n\n"+ mlps = printf "# ML_params\n%7d %7d %7d %7d %7d %7d\n\n"+ (multiNuc trnr) (multiNuc trnrH)+ (multiOffset trnr) (multiOffset trnrH)+ (multiHelix trnr) (multiHelix trnrH)+ ninios = printf "# NINIO\n%7d %7d %7d\n\n"+ (ninio trnr) (ninio trnrH) (maxNinio trnr)+ misc = printf "# Misc\n %7d %7d %7d %7d\n\n"+ (intermolecularInit trnr) (intermolecularInit trnrH) (termAU trnr) (termAU trnrH)+ triloops = "# Triloops\n" ++ printHairpinAssocs 5 trnr trnrH ++ "\n"+ tetra = "# Tetraloops\n" ++ printHairpinAssocs 6 trnr trnrH ++ "\n"+ hexa = "# Hexaloops\n" ++ printHairpinAssocs 8 trnr trnrH ++ "\n"+ blocks = concat $ zipWith (++)+ -- entropy terms+ [ printBlock "stack" 7 pp2lkey $ stack trnr+ , printBlock "mismatch_hairpin" 5 pbb2lkey $ hairpinMM trnr+ , printBlock "mismatch_interior" 5 pbb2lkey $ iloopMM trnr+ , printBlock "mismatch_interior_1n" 5 pbb2lkey $ iloop1xnMM trnr+ , printBlock "mismatch_interior_23" 5 pbb2lkey $ iloop2x3MM trnr+ , printBlock "mismatch_multi" 5 pbb2lkey $ multiMM trnr+ , printBlock "mismatch_exterior" 5 pbb2lkey $ extMM trnr+ , printBlock "dangle5" 5 pb2lkey $ dangle5 trnr+ , printBlock "dangle3" 5 pb2lkey $ dangle3 trnr+ , printBlock "int11" 5 ppbb2lkey $ iloop1x1 trnr+ , printBlock "int21" 5 ppbbb2lkey $ iloop1x2 trnr+ , printBlock22 "int22" 4 ppbbbb2lkey $ iloop2x2 trnr+ , printLinear "hairpin" 10 $ hairpinL trnr+ , printLinear "bulge" 10 $ bulgeL trnr+ , printLinear "interior" 10 $ iloopL trnr+ ]+ -- enthalpy terms+ [ printBlockH "stack" 7 pp2lkey $ stack trnrH+ , printBlockH "mismatch_hairpin" 5 pbb2lkey $ hairpinMM trnrH+ , printBlockH "mismatch_interior" 5 pbb2lkey $ iloopMM trnrH+ , printBlockH "mismatch_interior_1n" 5 pbb2lkey $ iloop1xnMM trnrH+ , printBlockH "mismatch_interior_23" 5 pbb2lkey $ iloop2x3MM trnrH+ , printBlockH "mismatch_multi" 5 pbb2lkey $ multiMM trnrH+ , printBlockH "mismatch_exterior" 5 pbb2lkey $ extMM trnrH+ , printBlockH "dangle5" 5 pb2lkey $ dangle5 trnrH+ , printBlockH "dangle3" 5 pb2lkey $ dangle3 trnrH+ , printBlockH "int11" 5 ppbb2lkey $ iloop1x1 trnrH+ , printBlockH "int21" 5 ppbbb2lkey $ iloop1x2 trnrH+ , printBlock22H "int22" 4 ppbbbb2lkey $ iloop2x2 trnrH+ , printLinearH "hairpin" 10 $ hairpinL trnrH+ , printLinearH "bulge" 10 $ bulgeL trnrH+ , printLinearH "interior" 10 $ iloopL trnrH+ ]++++-- * Helper functions++-- | Show the key of the line, minus the changing last key++showKey :: [(LKey,Int)] -> String+showKey xs =+ " /* " +++ (concat $ intersperse "," $ init $ (map show ps) ++ (map show ns)) +++ " */"+ where+ (ps,ns) = fst $ head xs++-- | Transform from tuple-based keys to a pair of list-based keys.++type LKey = ([ViennaPair],[Nucleotide])++pb2lkey (p1,b1) = ([p1],[b1])+pbb2lkey (p1,b1,b2) = ([p1],[b1,b2])+pp2lkey (k1,k2) = ([k1,k2],[])+ppbb2lkey (p1,p2,b1,b2) = ([p1,p2],[b1,b2])+ppbbb2lkey (p1,p2,b1,b2,b3) = ([p1,p2],[b1,b2,b3])+ppbbbb2lkey (p1,p2,b1,b2,b3,b4) = ([p1,p2],[b1,b2,b3,b4])++-- | Print a block.++printBlock = printBlockG noNP where+ noNP ((ps,ns),v) = not $ any (==vpNP) ps || any (==nucChain) ns++printBlockH s = printBlock (s ++ "_enthalpies")++printBlock22 = printBlockG noNSNPE where+ noNSNPE ((ps,ns),v) = not $ any (==vpNP) ps || any (==vpNS) ps || any (==nucE) ns || any (==nucChain) ns++printBlock22H s = printBlock22 (s ++ "_enthalpies")++printBlockG fltr s k tolkey xs' =+ let+ xs = filter fltr $ map (first tolkey) $ assocs xs'+ in+ printf "# %s\n" s +++ (concatMap printLine $ splitEvery k xs) +++ "\n"++printLine xs =+ concatMap printVal xs ++ " " ++ showKey xs +++ printf "\n"++printVal (k,v)+ | v > eMax = printf " INF"+ | otherwise = printf "%6d" v++-- | A linear block is more boring++printLinear s k xs' = let xs = assocs xs' in+ printf "# %s\n" s +++ (concatMap (\ys -> concatMap printVal ys ++ "\n") $ splitEvery k xs) +++ "\n"++printHairpinAssocs l trnr trnrH = res where+ res = concat $ zipWith (\(k,v) vH -> printf "%s %7d %7d\n" (concatMap show k) v vH) xs ys+ xs = filter ((==l).length.fst) $ M.assocs $ hairpinLookup trnr+ ys = map snd $ filter ((==l).length.fst) $ M.assocs $ hairpinLookup trnrH++printLinearH s = printLinear (s ++ "_enthalpies")
+ Biobase/DataSource/Vienna/Import/Turner.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE RecordWildCards #-}++-- | Import data from a Turner table structure. Those can be imported using the+-- Turner.Import module.++module Biobase.DataSource.Vienna.Import.Turner+ ( fromTurner+ ) where++import Control.Arrow+import Data.Tuple.All+import qualified Data.Map as M++import Biobase.DataSource.Turner.Tables+import Biobase.DataSource.Turner+import Data.PrimitiveArray+import Biobase.Constants+import Biobase.RNA+import Biobase.RNA.ViennaPair++import Biobase.DataSource.Vienna+-- | Convert from Turner keys to Vienna keys and all values from Double to Int++fromTurner :: TurnerTables -> ViennaIntTables+fromTurner Turner2004{..} = Turner2004+ { stack = convert pp stack+ , dangle3 = convert pb dangle3+ , dangle5 = convert pb dangle5+ , hairpinL = amap f2i hairpinL+ , hairpinMM = convert pbb hairpinMM+ , hairpinLookup = M.map f2i hairpinLookup+ , bulgeL = amap f2i bulgeL+ , iloop1x1 = convert uu iloop1x1+ , iloop1x2 = convert uu iloop1x2+ , iloop2x2 = convert uu iloop2x2+ , iloopMM = convert pbb iloopMM+ , iloop2x3MM = convert pbb iloop2x3MM+ , iloop1xnMM = convert pbb iloop1xnMM+ , iloopL = amap f2i iloopL+ , multiMM = convert pbb multiMM+ , ninio = f2i ninio+ , maxNinio = f2i maxNinio+ , multiOffset = f2i multiOffset+ , multiNuc = f2i multiNuc+ , multiHelix = f2i multiHelix+ , extMM = convert pbb extMM+ , largeLoop = largeLoop * 100 -- scale to decacals+ , termAU = f2i termAU+ , intermolecularInit = f2i intermolecularInit+ }++++-- * Helper functions.++-- | Vienna values are Int's that have 2-digit precision.++f2i :: Double -> Int+f2i d = round $ d * 100+++-- | Deep breath ;-)++pp = both mkViennaPair+pb = first mkViennaPair+pbb t = upd1 (mkViennaPair $ sel1 t) t+uu t = upd2 (mkViennaPair $ sel2 t) $ upd1 (mkViennaPair $ sel1 t) t+both f = first f . second f++-- | Do the conversion, both on keys and values.++convert fk = fromAssocs minBound maxBound eInf . map (first fk . second f2i) . assocs
+ Biobase/DataSource/Vienna/Import/ViennaPar.hs view
@@ -0,0 +1,124 @@+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RecordWildCards #-}++module Biobase.DataSource.Vienna.Import.ViennaPar+ ( importPar+ ) where++import Text.Parsec hiding ((<|>), many, optional)+import Text.Parsec.String+import Text.Parsec.Char+import Text.Parsec.Combinator hiding (optional)+import Control.Applicative+import Data.List+import qualified Data.Map as M++import Text.Parsec.Numbers+import Biobase.Constants+import Biobase.RNA+import Biobase.RNA.ViennaPair+import Biobase.DataSource.Turner.Tables+import Data.PrimitiveArray++import Biobase.DataSource.Vienna++++-- | Imports Vienna tables from a given string.++importPar :: String -> (ViennaIntTables,ViennaIntTables)+importPar s+ | Right _ <- p = foldr updateTables (trnr,trnrH) bs+ | Left err <- p = error $ show err+ where+ p = parse blocks "(stdin)" s+ Right bs = p+ (bgs,bhs) = partition (not . isHblock) bs+ trnr = foldr updateTable emptyTables bgs+ trnrH = foldr updateTable emptyTables bhs++-- | Apply all parsed blocks to a Turner2004 structure.++updateTable :: Block -> ViennaIntTables -> ViennaIntTables+updateTable Block{..} trnr -- @Turner2004{..}+ | bhdr =? "stack" = trnr{stack = fromAssocs minBound maxBound z $ zip pp ints}+ | bhdr =? "dangle3" = trnr{dangle3 = fromAssocs minBound (vpNS,nucU) z $ zip pb ints}+ | bhdr =? "dangle5" = trnr{dangle5 = fromAssocs minBound (vpNS,nucU) z $ zip pb ints}+ | bhdr =? "hairpin" = trnr{hairpinL = fromList 0 30 ints}+ | bhdr =? "mismatch_hairpin" = trnr{hairpinMM = fromAssocs minBound (vpNS,nucU,nucU) z $ zip pbb ints}+ | bhdr =? "bulge" = trnr{bulgeL = fromList 0 30 ints}+ | bhdr =? "int11" = trnr{iloop1x1 = fromAssocs minBound (vpNS,vpNS,nucU,nucU) z $ zip ppbb ints}+ | bhdr =? "int21" = trnr{iloop1x2 = fromAssocs minBound (vpNS,vpNS,nucU,nucU,nucU) z $ zip ppbbb ints}+ | bhdr =? "int22" = trnr{iloop2x2 = fromAssocs minBound (vpNS,vpNS,nucU,nucU,nucU,nucU) z $ zip ppbbbb ints}+ | bhdr =? "mismatch_interior" = trnr{iloopMM = fromAssocs minBound (vpNS,nucU,nucU) z $ zip pbb ints}+ | bhdr =? "mismatch_interior_23" = trnr{iloop2x3MM = fromAssocs minBound (vpNS,nucU,nucU) z $ zip pbb ints}+ | bhdr =? "mismatch_interior_1n" = trnr{iloop1xnMM = fromAssocs minBound (vpNS,nucU,nucU) z $ zip pbb ints}+ | bhdr =? "interior" = trnr{iloopL = fromList 0 30 ints}+ | bhdr =? "mismatch_multi" = trnr{multiMM = fromAssocs minBound (vpNS,nucU,nucU) z $ zip pbb ints}+ | bhdr =? "mismatch_exterior" = trnr{extMM = fromAssocs minBound (vpNS,nucU,nucU) z $ zip pbb ints}+ | otherwise = trnr -- unknown block!+updateTable ABlock{..} trnr+ | otherwise = trnr -- CORRECT!++-- | update with info where no separation between G/H was done.++updateTables Block{..} (trnr,trnrH)+ | bhdr =? "ML_params"+ = ( trnr {multiNuc = ints!!0, multiOffset = ints!!2, multiHelix = ints!!4}+ , trnrH{multiNuc = ints!!1, multiOffset = ints!!3, multiHelix = ints!!5}+ )+ | bhdr =? "NINIO"+ = ( trnr {ninio = ints!!0, maxNinio = ints!!2}+ , trnrH {ninio = ints!!1}+ )+ | bhdr =? "Misc"+ = ( trnr {intermolecularInit = ints!!0, termAU = ints!!2}+ , trnrH {intermolecularInit = ints!!1, termAU = ints!!3}+ )+ | otherwise = (trnr,trnrH)+updateTables ABlock{..} (trnr,trnrH)+ | bhdr =? "Triloops" || bhdr =? "Tetraloops" || bhdr =? "Hexaloops"+ = ( trnr {hairpinLookup = hairpinLookup trnr `M.union` (M.fromList $ map (\(k,v,w) -> (s2ns k,v)) ascs)}+ , trnrH {hairpinLookup = hairpinLookup trnrH `M.union` (M.fromList $ map (\(k,v,w) -> (s2ns k,w)) ascs)}+ )+ | otherwise = (trnr,trnrH)++pp = [(x,y) | x<-cgnsP,y<-cgnsP]+pb = [(x,y) | x<-cgnsP,y<-eacgu]+pbb = [(x,y,z) | x<-cgnsP,y<-eacgu,z<-eacgu]+ppbb = [(p1,p2,b1,b2) | p1<-cgnsP,p2<-cgnsP,b1<-eacgu,b2<-eacgu]+ppbbb = [(p1,p2,b1,b2,b3) | p1<-cgnsP,p2<-cgnsP,b1<-eacgu,b2<-eacgu,b3<-eacgu]+ppbbbb = [(p1,p2,b1,b2,b3,b4) | p1<-cguaP,p2<-cguaP,b1<-acgu,b2<-acgu,b3<-acgu,b4<-acgu]+z = eInf+-- xs is the block header name, ys the constant string+xs =? ys = xs == ys || xs == ys++"_enthalpies" -- and $ zipWith (==) xs ys+s2ns = map mkNuc++-- * Simple parser for the vienna 2.0 format.++isHblock :: Block -> Bool+isHblock b = "enthalpies" `elem` (tails $ bhdr b)++data Block+ = Block {bhdr :: String, ints :: [Int]}+ | ABlock {bhdr :: String, ascs :: [(String,Int,Int)]}+ deriving (Show)++blocks :: GenParser Char st [Block]+blocks = vrna2 *> spaces *> (try assocBlock <|> try block) `sepEndBy1` spaces <* string "#END" <* spaces <* eof++vrna2 = string "## RNAfold parameter file v2.0"++block :: GenParser Char st Block+block = Block <$> header <* spaces <*> num `sepEndBy1` (try comment <|> spaces) where+ num = ((eInf <$ string "INF") <|> parseIntegral)++assocBlock :: GenParser Char st Block+assocBlock = ABlock <$> header <* spaces <*> asc `sepEndBy1` spaces where+ asc = (,,) <$> (many1 $ oneOf "ACGU") <* spaces <*> parseIntegral <* spaces <*> parseIntegral++header :: GenParser Char st String+header = char '#' *> space *> (alphaNum <|> char '_') `manyTill` newline++comment :: GenParser Char st ()+comment = const () <$ spaces <*> between (string "/*") (string "*/") (many $ noneOf "/*") <* spaces
+ Biobase/DataSource/Vienna/Modification/NonStandard.hs view
@@ -0,0 +1,122 @@++-- | This module provides facilities to modify values in the tables and return+-- the modified tables. The main reason for the modules' existence are the 'E'+-- nucleotides and 'NS' base pairs used by the ViennaRNA package to denote+-- unknown or missing nucleotides. For each table type, we have a small+-- function.++module Biobase.DataSource.Vienna.Modification.NonStandard+ ( nonStandardMax+ ) where++import Biobase.RNA+import Biobase.RNA.ViennaPair+import Biobase.DataSource.Vienna+import Biobase.DataSource.Turner.Tables+import Data.Ix.Tuple+import Biobase.Constants+import Biobase.Types.Energy++import Data.PrimitiveArray+++-- | Each table-changing operation makes the promise that all individual+-- changes in a batch are independent of the changes in the same batch++changeTable f tbl = fromAssocs l u z . map (f tbl) $ assocs tbl where+ (l,u) = bounds tbl+ z = Energy eInf++++-- |* Replace each occurrance of a value with a strange key according to this+-- rule. The rule is to take the maximum over all sane keys in the+-- neighborhood. Yes, this takes long...++fPPBBBBmax tbl (k@(p1,p2,b1,b2,b3,b4),v)+ | p1==vpNP || p2==vpNP = (k,v) -- don't do anything+ | otherwise = (k,maximum'+ [ tbl ! (p1n,p2n,b1n,b2n,b3n,b4n)+ | p1n <- genKeyP p1+ , p2n <- genKeyP p2+ , b1n <- genKeyB b1+ , b2n <- genKeyB b2+ , b3n <- genKeyB b3+ , b4n <- genKeyB b4+ ])++fPPBBBmax tbl (k@(p1,p2,b1,b2,b3),v)+ | p1==vpNP || p2==vpNP = (k,v)+ | otherwise = (k,maximum'+ [ tbl ! (p1n,p2n,b1n,b2n,b3n)+ | p1n <- genKeyP p1+ , p2n <- genKeyP p2+ , b1n <- genKeyB b1+ , b2n <- genKeyB b2+ , b3n <- genKeyB b3+ ])++fPPBBmax tbl (k@(p1,p2,b1,b2),v)+ | p1==vpNP || p2==vpNP = (k,v)+ | otherwise = (k,maximum'+ [ tbl ! (p1n,p2n,b1n,b2n)+ | p1n <- genKeyP p1+ , p2n <- genKeyP p2+ , b1n <- genKeyB b1+ , b2n <- genKeyB b2+ ])++fPPmax tbl (k@(p1,p2),v)+ | p1==vpNP || p2==vpNP = (k,v)+ | otherwise = (k,maximum'+ [ tbl ! (p1n,p2n)+ | p1n <- genKeyP p1+ , p2n <- genKeyP p2+ ])++fPBBmax tbl (k@(p1,b1,b2),v)+ | p1==vpNP = (k,v)+ | otherwise = (k,maximum'+ [ tbl ! (p1n,b1n,b2n)+ | p1n <- genKeyP p1+ , b1n <- genKeyB b1+ , b2n <- genKeyB b2+ ])++fPBmax tbl (k@(p1,b1),v)+ | p1==vpNP = (k,v)+ | otherwise = (k,maximum'+ [ tbl ! (p1n,b1n)+ | p1n <- genKeyP p1+ , b1n <- genKeyB b1+ ])++maximum' = Energy . maximum . map unEnergy+++-- * Generate keys. If the key is of the non-standard kind, then we go fishing,+-- otherwise we keep the key itself.++genKeyP k = if k==vpNS then cguaP else [k]+genKeyB k = if k==nucE then acgu else [k]++++-- | The max operation applied to all relevant tables. (This serves as a+-- pointer, which tables to manipulate).++nonStandardMax :: ViennaEnergyTables -> ViennaEnergyTables+nonStandardMax tbl = tbl+ { iloop1x1 = changeTable fPPBBmax $ iloop1x1 tbl+ , iloop1x2 = changeTable fPPBBBmax $ iloop1x2 tbl+ , iloop2x2 = changeTable fPPBBBBmax $ iloop2x2 tbl+ , hairpinMM = changeTable fPBBmax $ hairpinMM tbl+ , iloopMM = changeTable fPBBmax $ iloopMM tbl+ , iloop1xnMM = changeTable fPBBmax $ iloop1xnMM tbl+ , iloop2x3MM = changeTable fPBBmax $ iloop2x3MM tbl+ , multiMM = changeTable fPBBmax $ multiMM tbl+ , extMM = changeTable fPBBmax $ extMM tbl+ , dangle3 = changeTable fPBmax $ dangle3 tbl+ , dangle5 = changeTable fPBmax $ dangle5 tbl+ , stack = changeTable fPPmax $ stack tbl+ }
+ Biobase/DataSource/Vienna/Modification/Partition.hs view
@@ -0,0 +1,51 @@++-- | Small module for converting Vienna energy tables to partition function+-- value tables.+--+-- Temperature scaling should happen on the level of energy tables, followed by+-- conversion here.+--+-- TODO after the switch to the Energy type, change too, the partitionTables+-- generation++module Biobase.DataSource.Vienna.Modification.Partition+ ( partitionTables+ ) where++import Biobase.Types.Partition+import Biobase.Types.Energy+import Biobase.DataSource.Turner.Tables+import Biobase.DataSource.Vienna+import Biobase.Constants+++-- Testing++{-+import Biobase.DataSource.Vienna.Default+import Data.PrimitiveArray+import Debug.Trace.Tools+import Biobase.RNA+import Biobase.Types.Ring++(g,h) = turner2004GH++-- x = toList $ stack $ partitionTables 37 g+x = {- toList $ -} (stack $ partitionTables 37 g) ! (vpGC,vpGC)+-}++-- | Create partition tables out of normal energy tables. Note that these+-- values are not normalized. An additional term 1/Z(1/kt) would be required+-- which is missing until we are done calculating the partition function.+--+-- All energy contributions are rescaled from dekacals back to kcal/mol.+--+-- We explicitly set all probabilities =0 where the energy is >= eMax.++partitionTables :: Temperature -> ViennaEnergyTables -> ViennaPartitionTables+partitionTables tempe trnr = dmap f trnr where+ kt = (tempe + kelvinC0) * gasconst+ -- convert energy into probability; encapsulate as a (logFloat) partition+ f (Energy e') = {- traceVal (show (e',e,p)) -} p where+ e = fromIntegral e' / 100+ p = if e' >= eMax then Partition 0 else Partition . exp $ -e / kt -- can NOT use mkPartition as these values are NOT NORMALIZED
+ Biobase/DataSource/Vienna/Modification/Temperature.hs view
@@ -0,0 +1,34 @@++-- | Given entropy and enthalpy sets, allow modification of the folding+-- temperature (from the default 37 Celsius)++module Biobase.DataSource.Vienna.Modification.Temperature+ ( adjustTemperature+ ) where++import Biobase.DataSource.Vienna+import Biobase.DataSource.Turner.Tables+import Biobase.Constants++++-- temperature scaling is a generalized zip: let g and h be a scalar, t the+-- temperature. Then: g_t = h - (h-g)*((t+k_0)/t_m). Where k_0 = 273.15 (Kelvin+-- of 37 Celsius) and t_m = 37+k_0+--+-- TODO abstract over table type?+--+-- TODO this does not take into account that dangles are supposed to _always_+-- be beneficial. We should therefor transform the energies and then apply 'min+-- 0' onto all dangle types.+--+-- TODO use EnergyTables (Int is just for im-/export)++adjustTemperature :: ViennaIntTables -> ViennaIntTables -> Temperature -> ViennaIntTables+adjustTemperature trnrG trnrH cels = dZipWith f trnrG trnrH where+ f vG vH =+ let g = fromIntegral vG+ h = fromIntegral vH+ k_0 = kelvinC0+ t_m = 37 + k_0+ in round $ h - (h-g) * ((cels+k_0)/t_m)
− Biobase/Infernal/CM.hs
@@ -1,326 +0,0 @@------- Stores Infernal Covariance Model data. Built for ease of use, not speed but--- should work reasonably well.------- TODO Data.Vector?------ TODO use generics?------ TODO functions to change to probabilities!------ TODO cmCanonize function!------ TODO put functions into their own modules, a bit of cleanup------ TODO add functions to insert a new node between two already existing nodes; think about how to handle BIF------ TODO add ability to remove node; think about how to handle BIF------ NOTE maybe BIF should not be insertable/removable right now?--module Biobase.Infernal.CM where---import Data.Array.IArray-import Data.List (genericLength)--import Biobase.RNA hiding (nucE) -- "E type" nucleotides do not happen in CMs!------ * Data types for Covariance Models---- {{{ Data types---- | A complete covariance model. Each node and each state can be tagged with--- additional data. Typically, say after parsing, the tag will be ().--data CM n s = CM- { nodes :: Array Int (Node n)- , states :: Array Int (State s)- , header :: [(String,String)] -- keeps the list of header entries sorted!- , localBegin :: Array Int Double- , localEnd :: Array Int Double- , cmType :: CMType- , nullModel :: Array Nucleotide Double- } deriving (Show)---- | Describes one node--data Node n = Node- { nid :: Int- , ntype :: NodeType- , nparents :: [Int] -- TODO can there be more than one?- , nchildren :: [Int]- , nstates :: [Int]- , ntag :: n- } deriving (Show)---- | One state--data State s = State- { sid :: Int- , stype :: StateType- , snode :: Int- , sparents :: [Int]- , schildren :: [Transition]- , semission :: [Emission]- , stag :: s- } deriving (Show)---- | CMType is important if we want to set localBegin / localEnd!--data CMType = CMProb | CMScore- deriving (Show,Eq)---- | can emit either one nucleotide or a pair--data Emission- = EmitS {eNuc :: Nucleotide, escore :: Double}- | EmitP { eNucL :: Nucleotide, eNucR :: Nucleotide, escore :: Double}- deriving (Show)---- | branches are transition without attached probability becaue both branches are always taken--data Transition- = Branch {tchild :: Int}- | Transition {tchild :: Int, tscore :: Double}- deriving (Show)---- | the different node types--data NodeType = MATP | MATL | MATR | BIF | ROOT | BEGL | BEGR | END- deriving (Read,Show,Eq,Ord,Enum,Bounded)---- | the different state types--data StateType = MP | IL | IR | D | ML | MR | B | S | E- deriving (Read,Show,Eq,Ord,Enum,Bounded)---- }}}----- * make a local model out of a global one---- | generate a local model with local begin prob and local end prob--cmMakeLocal :: Double -> Double -> CM n s -> CM n s-cmMakeLocal pbegin pend cm = cmMakeLocalBegin pbegin $ cmMakeLocalEnd pend cm----cmMakeLocalBegin :: Double -> CM n s -> CM n s-cmMakeLocalBegin pbegin cm = cm{localBegin = localBegin cm // changes} where- changes = rootS : (start : intern)- rootS = (0, prob2Score 0 1.0) -- root disabled!- start = (head . nstates $ nodes cm ! 1, prob2Score (1-pbegin) 1.0) -- the first state after "root 0"- intern = map (\k -> (sid $ nodeMainState cm k,prob2Score (pbegin / l) 1.0)) nds- nds = filter (localBeginPossible cm) . elems $ nodes cm- l = genericLength nds------ TODO have to change the transition score, too!--cmMakeLocalEnd :: Double -> CM n s -> CM n s-cmMakeLocalEnd pend cm = cm{localEnd = localEnd cm // changes} where- changes = map (\k -> (sid $ nodeMainState cm k,prob2Score (pend / l) 1.0)) nds- nds = filter (localBeginPossible cm) . elems $ nodes cm- l = genericLength nds------ * Transform between score and probability mode---- | given a CM in score mode, change it to probability mode--cmScore2Prob :: CM n s -> CM n s-cmScore2Prob cm' = if cmType cm' == CMProb then cm' else CM- (nodes cm)- (statesScore2Prob cm $ states cm)- (header cm)- (localBeginScore2Prob $ localBegin cm)- (localEndScore2Prob $ localEnd cm)- CMProb- nm- where- nm = amap (flip score2Prob 0.25) $ nullModel cm'- cm = cm' {nullModel = nm}----- | Given a CM in prob mode, change to score mode--cmProb2Score :: CM n s -> CM n s-cmProb2Score cm' = if cmType cm' == CMScore then cm' else CM- (nodes cm)- (statesProb2Score cm $ states cm)- (header cm)- (localBeginProb2Score $ localBegin cm)- (localEndProb2Score $ localEnd cm)- CMScore- nm- where- nm = amap (flip prob2Score 0.25) $ nullModel cm'- cm = cm' {nullModel = nm}------ | normalize all PROBabilities in a CM--cmNormalizeProbabilities :: CM n s -> CM n s-cmNormalizeProbabilities cm- | cmType cm == CMScore = error "cannot normalize score-type CM"- | otherwise = cm -- TODO have to map normalization over all scores!------ {{{ CM score/prob conversion helpers--statesScore2Prob :: CM n s -> Array Int (State s) -> Array Int (State s)-statesScore2Prob cm sA = amap f sA where- f s = s {schildren = map fT $ schildren s, semission = map fE $ semission s}- fT b@(Branch _) = b- fT (Transition k v) = Transition k (score2Prob v 1.0)- fE (EmitS k v) = EmitS k (score2Prob v $ nullModel cm ! k)- fE (EmitP k1 k2 v) = EmitP k1 k2 (score2Prob v $ (nullModel cm ! k1) * (nullModel cm ! k2))----localBeginScore2Prob :: Array Int Double -> Array Int Double-localBeginScore2Prob sA = amap f sA where- f s = score2Prob s 1.0----localEndScore2Prob :: Array Int Double -> Array Int Double-localEndScore2Prob sA = amap f sA where- f s = score2Prob s 1.0----statesProb2Score :: CM n s -> Array Int (State s) -> Array Int (State s)-statesProb2Score cm sA = amap f sA where- f s = s {schildren = map fT $ schildren s, semission = map fE $ semission s}- fT b@(Branch _) = b- fT (Transition k v) = Transition k (prob2Score v 1.0)- fE (EmitS k v) = EmitS k (prob2Score v $ nullModel cm ! k)- fE (EmitP k1 k2 v) = EmitP k1 k2 (prob2Score v $ (nullModel cm ! k1) * (nullModel cm ! k2))----localBeginProb2Score :: Array Int Double -> Array Int Double-localBeginProb2Score sA = amap f sA where- f s = prob2Score s 1.0----localEndProb2Score :: Array Int Double -> Array Int Double-localEndProb2Score sA = amap f sA where- f s = score2Prob s 1.0---- }}}------- * Helper Functions---- {{{ helper functions---- | extract the main state for each node (eg MP state for MATP node)---- TODO shouldn't this just be "head $ nstates n"?--nodeMainState :: CM n s -> Node n -> State s-nodeMainState cm n = head $ filter ((==st) . stype) ss where- (Just st) = (ntype n) `lookup` nodeMainStateAssocs- ss = map (states cm !) $ nstates n----- | Checks for each node, if it can be target of a local begin.--localBeginPossible :: CM n s -> Node n -> Bool-localBeginPossible cm n =- if ntype n `elem` okNodes- && (not . any (==0) $ nparents n) -- nodes reachable from "root" (that is: node 1) have handled specially- then True- else False- where- okNodes = [MATP,MATL,MATR,BIF]------ | Checks for each node if it can lead to a local end.--localEndPossible :: CM n s -> Node n -> Bool-localEndPossible cm n =- if ntype n `elem` okNodes- && (END /= (ntype $ nodes cm ! (nid n +1)))- then True- else False- where- okNodes = [MATP,MATL,MATR,BEGL,BEGR]------ | transform scores into probabilities, given a nullmodel for x---- TODO quickcheck!--score2Prob x null- | x == (-1/0) = 0- | otherwise = exp (x * log 2) * null------ | back into scores--prob2Score x null- | x == 0 = (-1/0)- | otherwise = log (x / null) / log 2------ | Transform a state, setting probabilities instead of scores. Requires CM--- knowledge for background model.---- TODO actually use the background model--stateScore2Prob :: CM n s -> State s -> State s-stateScore2Prob cm s = error "implement me"------ | Transform a state, setting scores instead of probabilities.--stateProb2Score :: CM n s -> State s -> State s-stateProb2Score cm s = error "implement me"-transitionTargets :: [Transition] -> [Int]-transitionTargets xs = map f xs where- f (Branch x) = x- f (Transition x _) = x---nodeMainStateAssocs :: [(NodeType,StateType)]-nodeMainStateAssocs =- [ (MATP, MP)- , (MATL, ML)- , (MATR, MR)- , (BIF, B)- , (ROOT, S)- , (BEGL, S)- , (BEGR, S)- , (END, E)- ]---- }}}------ TODO score -> prob : exp (x / log 2) -- CHECK THIS!!!--- score -> prob : exp (x * log 2)--- prob -> score : (log x) / log 2--- TODO mkGlobal (needed?)--- TODO use logsum : log (exp x + exp y) = x + log (1 + exp (y-x)), where x>y
− Biobase/Infernal/CM/Export.hs
@@ -1,76 +0,0 @@-{-# LANGUAGE RecordWildCards #-}---- | write an Infernal model. We aim for version 1.0.2 of Infernal but right--- now, there is no explicit version management! We just return header--- information as we read it. So we are compatible to all versions that can be--- parsed but have no safeguards in place.------ NOTE: exported model can apparently be calibrated.------ TODO make sure that (Export.toString . Import.fromString == id); the other--- way around is not absolutely necessary (except if the Infernal parser should--- require this at some point)------ TODO put functions like stringS into another module?--module Biobase.Infernal.CM.Export where--import qualified Data.Array.IArray as A-import Text.Printf--import Biobase.Infernal.CM--import Biobase.Infernal.CM.Import -- TODO for testing only!------ | Main export function for CMs. Creates a string that is accepted by--- Infernal--toString :: CM n s -> String-toString cm@CM{..} = unlines $ hdr ++ ["MODEL:"] ++ nds ++ ["//"]- where- hdr = map (\(k,v) -> k ++ " " ++ v) header- nds = concatMap (nodeToString cm) $ A.elems nodes------ | export a specific node, used by 'toString'--nodeToString :: CM n s -> Node n -> [String]-nodeToString cm Node{..} = printf "\t\t\t\t[ %s %d ]" (show ntype) nid : map (stateToString cm . (states cm A.!)) nstates------ | export a specific states, used by 'nodeToString'--stateToString :: CM n s -> State s -> String-stateToString cm State{..} = printf " %2s %6d %6d %2d %6d %6d %-55s %s" (show stype) sid maxP numP minC numC tscores escores- where- maxP- | null sparents = -1- | otherwise = maximum sparents- numP = length sparents- minC- | null schildren = -1- | otherwise = minimum $ map tchild schildren- numC- | stype == B = maximum $ map tchild schildren- | otherwise = length schildren- tscores :: String- tscores- | stype == B = ""- | otherwise = concatMap (printf "%s " . stringS . tscore) schildren- escores :: String- escores- | null semission = ""- | otherwise = concatMap (printf "%.3f " . escore) semission------ | export scores for transitions with the Infernal-specific "-infinity" value--- of "*"--stringS x- | x == (-1/0) = " *"- | otherwise = printf "%.3f" x
− Biobase/Infernal/CM/Import.hs
@@ -1,194 +0,0 @@------- A parser for Infernal's Covariance Models (CM). Should work with version 1.0--- of Infernal.------- TODO use generics?------ TODO importing the cmcalibrate calibration data is currently broken! (data is parsed as separate lines)--module Biobase.Infernal.CM.Import (fromFile,fromString) where--import Data.Maybe (fromJust)-import qualified Data.Array.IArray as A-import qualified Data.List as L-import Text.ParserCombinators.Parsec hiding (State)--import Biobase.Infernal.CM-import Biobase.RNA hiding (nucE)------ {{{ Parsec--myChar = alphaNum <|> char '-' <|> char '_' <|> char '.'-headerChar = myChar <|> char '[' <|> char ']'-floating = many1 $ digit <|> char '.' <|> char 'e' <|> char '-'--headerLine = do- key <- many1 headerChar- --spaces- many1 $ char ' '- val <- many1 (headerChar <|> char ' ' <|> char '/' <|> char ':')- newline- return (key,val)--unknownNumbers = do- many1 $ char ' '- ns <- floating `sepEndBy` (many1 $ char ' ')- newline- return ("",concat ns)--theHeader = do- hs <- many $ (try headerLine <|> try unknownNumbers)- string "MODEL:"- newline- return hs---- }}}---- {{{ Node--node = do- spaces- string "[ "- name <- many letter- spaces- num <- many digit >>= (return . read)- spaces- string "]"- newline- states <- many $ try (state num)- return $ (Node- { ntype = read name- , nid = num- , nstates = map sid states- , nparents = []- , nchildren = []- , ntag = ()- }- , states)---- }}}---- {{{ stuff---- TODO put some of this into HsTools/Parsec stuff--aNum = many1 $ char '-' <|> digit-addneginf :: String -> Double-addneginf "*" = (-1)/0 --"-1000000000.0"-addneginf x = read x---- }}}---- {{{ State--state nodeID = do- spaces- name <- many1 myChar- spaces- sid <- aNum >>= (return . read)- spaces- plast <- aNum >>= (return . read)- spaces- pnum <- aNum >>= (return . read)- spaces- cfirst <- aNum >>= (return . read)- spaces- cnum <- aNum >>= (return . read)- probs <- ( (many $ myChar <|> char '*') `sepBy` (many1 $ char ' ') >>=- return . map addneginf . filter ((/=) "") )- newline- let s = case name of- "B" -> State- { stype = read name- , sid = sid- , snode = nodeID- , sparents = [plast-pnum+1 .. plast]- , schildren = [Branch cfirst, Branch cnum]- , semission = []- , stag = ()- }- _ -> State- { stype = read name- , sid = sid- , snode = nodeID- , sparents = [plast-pnum+1 .. plast]- , schildren = zipWith Transition [cfirst .. cfirst+cnum-1] probs- , semission = let keep = drop cnum probs in- case length keep of- 0 -> []- 4 -> zipWith EmitS acgu keep- 16 -> zipWith (\(k1,k2) v -> EmitP k1 k2 v) acguPairs keep- _ -> error $ "strange number of probabilities" ++ show (keep)- , stag = ()- }- return s---- }}}---- {{{ Model--models = do- ms <- many model- eof- return ms--model = do- h <- theHeader- ns <- many node- let states = concatMap snd ns- let nodes = map (addPCinfo states . fst) ns- -- just add all the node parent / child info- string "//"- newline- -- eof -- removed, we want to be able to read concatenated models!- return $ CM- { nodes = A.array (0, length nodes -1) $ zip (map nid nodes) nodes- , states = A.array (0, length states -1) $ zip (map sid states) states- , header = h- , localBegin = A.array (0, length states -1) $ zip [0 .. length states -1] (0.0 : repeat (-1/0))- , localEnd = A.array (0, length states -1) $ zip [0 .. length states -1] (repeat (-1/0))- , cmType = CMScore- , nullModel = A.array (nucA,nucU) $ zip acgu (map read . words . fromJust $ "NULL" `lookup` h) -- TODO circumvents the whole parsing stuff!- }---- }}}---- {{{ Stuff--addPCinfo states n =- let- s = nstates n- sp = L.nub $ L.sort $ concatMap (sparents . (states !!)) s- sc = L.nub $ L.sort $ concatMap (transitionTargets . schildren . (states !!)) s- np = (L.nub $ L.sort $ map (snode . (states !!)) sp) L.\\ [nid n]- nc = (L.nub $ L.sort $ map (snode . (states !!)) sc) L.\\ [nid n]- in- n {nparents = np, nchildren = nc}------ | Two types of parsing, once using a file and once by parsing a string.--fromFile f = parseFromFile models f-fromString s = parse models "(stdin)" s---- }}}---- | Helper function to remove impossible state transitions (those that have--- -infty score).---- TODO move to InfernalCM.hs and have it for Prob and Score both--{--canonize cm = cm {states = A.amap f $ states cm} where- f s = s {schildren = filter g $ schildren s}- g (Branch _) = True- g (Transition _ v) = - h (_,s)- | s == (-1)/0 = False- | otherwise = True--}
− Biobase/Infernal/Stockholm.hs
@@ -1,16 +0,0 @@---- | The beginnings of a Stockholm File parser.--module Biobase.Infernal.Stockholm where---- | Stockholm format data. We have a set of sequences with sequence data, a--- set of column annotations and unknown data (actually: known, but we do not--- care).--data Stockholm = Stockholm- { sequences :: [(String,String)]- , colAnnotations :: [(String,String)] -- #=GC tag- , exAnnotations :: [(String,String)] -- NOTE this is not in the Stockholm format!- , unknown :: [String]- }- deriving (Show)
− Biobase/Infernal/Stockholm/Import.hs
@@ -1,35 +0,0 @@---- | A simple parser for Stockholm data. As we do not interpret most stuff--- right now, Parsec is not required.--module Biobase.Infernal.Stockholm.Import where--import Biobase.Infernal.Stockholm-import Data.List--fromFile :: String -> IO Stockholm-fromFile fname = do- ls <- readFile fname >>= return . filter (not . null) . lines- let (colanno, rest1) = partition (\x -> length x >= 4 && (and $ zipWith (==) "#=GC" x)) ls- let (seqdata, rest2) = partition (\(x:_) -> x/='#' && x/='/') rest1- let (exdata , unk) = partition (\x -> length x >= 4 && (and $ zipWith (==) "#=EX" x)) rest2- {-- print colanno- print rest1- print seqdata- print rest2- print exdata- print unk- -}- return Stockholm- { sequences = map (mkPair . words) seqdata- , colAnnotations = map (mkPair . drop 1 . words) colanno- , exAnnotations = map (mkPair . drop 1 . words) exdata- , unknown = unk- }----mkPair [] = error "empty list"-mkPair [x] = error $ "just one element: " ++ show x-mkPair (x:xs) = (x,unwords xs)
Biobase/RNA.hs view
@@ -1,247 +1,168 @@+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-} -- | Encodings for nucleotides and pairs. Currently very ViennaRNA-centric. -- This might change over time. -- -- TODO do not export Nucleotide ctor? ----- TODO consider adding "nucAmpersand" as a chain seperator. This could make--- some things easier.+-- TODO With GHC 7.2 we should be able to activate Read,Show for the overlapped+-- VU.Vector Nucleotide and get better string representations for 'Primary'.+--+-- TODO nucE -> nucN ?+--+-- TODO add all possible characters? module Biobase.RNA where +import Control.DeepSeq import Data.Char (toUpper) import Data.Ix-import qualified Data.Vector.Unboxed as VU+import Data.Primitive.Types+import qualified Data.ByteString.Char8 as BSS+import qualified Data.ByteString.Lazy.Char8 as BSL import qualified Data.Vector.Generic as VG import qualified Data.Vector.Generic.Mutable as VGM-import Data.Primitive.Types+import qualified Data.Vector.Unboxed as VU -import Data.PrimitiveArray-import Data.PrimitiveArray.Ix+import Biobase.RNA.NucBounds -- * single nucleotide encoding +-- | Represent nucleotides as machine 'Int's+ newtype Nucleotide = Nucleotide Int- deriving (Eq,Ord,Ix)+ deriving (Eq,Ord,Ix,NFData) -(nucE:nucA:nucC:nucG:nucU:_) = map Nucleotide [0..]+-- | We have the canonical nucleotides A,C,G,U, unknown nucleotides as E and a+-- chain symbol used to separate different nucleotide chains. -nucCharList :: [(Int,Char)]-nucCharList = zip [0..] "EACGU"-charNucList :: [(Char,Int)]-charNucList = zip "EACGU" [0..]+(nucE: nucA:nucC:nucG:nucU: nucChain:_) = map Nucleotide [0..] -deriving instance Prim Nucleotide-deriving instance VGM.MVector VU.MVector Nucleotide-deriving instance VG.Vector VU.Vector Nucleotide-deriving instance VU.Unbox Nucleotide+-- | Conversion to and from nucleotides. --- TODO maybe use 'assert' and do not catch errors in optimized operation?!+class MkNucleotide a where+ mkNuc :: a -> Nucleotide+ fromNuc :: Nucleotide -> a +-- | instance for characters++instance MkNucleotide Char where+ mkNuc c'+ | Just n <- c `lookup` c2n = n+ | c=='&' = nucChain+ | otherwise = nucE+ where+ c2n = zip "ACGU" [nucA..nucU]+ c = toUpper c'+ fromNuc n+ | Just c <- n `lookup` n2c = c+ | n == nucChain = '&'+ | otherwise = 'E'+ where n2c = zip [nucA..nucU] "ACGU"++-- | The enum instance.+ instance Enum Nucleotide where toEnum x- | x>=0 && x<=4 = Nucleotide x+ | x>=0 && x<=5 = Nucleotide x | otherwise = error $ "can't make to enum" ++ show x fromEnum (Nucleotide x) = x {-# INLINE toEnum #-} {-# INLINE fromEnum #-} +deriving instance Prim Nucleotide+deriving instance VGM.MVector VU.MVector Nucleotide+deriving instance VG.Vector VU.Vector Nucleotide+deriving instance VU.Unbox Nucleotide++-- | The Bounded instance uses bounds that are explicitly "too small" as other+-- symbols have special meaning and should not be used with normal bounds.+--+-- TODO think about better ways to handle this!+ instance Bounded Nucleotide where minBound = nucE- maxBound = nucU+ maxBound = nucChain +-- | The typical lookup table should use 'NucBounds' instead of 'Bounded' and+-- here 'minExtended' and 'maxExtended' as this covers all characters one would+-- typically expect.++instance NucBounds Nucleotide where+ minNormal = nucA+ maxNormal = nucU+ minExtended = nucE+ maxExtended = nucU+ instance Show Nucleotide where- show (Nucleotide x)- | Just s <- x `lookup` nucCharList = [s]+ show n = [fromNuc n] instance Read Nucleotide where readsPrec p [] = [] readsPrec p (x:xs) | x ==' ' = readsPrec p xs- | Just n <- x `lookup` charNucList = [(Nucleotide n,xs)]+ | Just n <- x `lookup` c2n = [(n,xs)] | otherwise = []--charToNucleotide :: Char -> Nucleotide-charToNucleotide = f . toUpper where- f x- | Just n <- x `lookup` charNucList = Nucleotide n- | otherwise = nucE---- | Since this function is used rather often.--char2nuc = charToNucleotide--nucleotideToChar :: Nucleotide -> Char-nucleotideToChar (Nucleotide n) = f n where- f x- | Just c <- x `lookup` nucCharList = c+ where+ c2n = zip "EACGU&" [nucE .. nucChain] --- * Represent nucleotide sequences using a PrimArray.------ TODO switch back to Unboxed.Vector? Test speed of both approaches!--type Primary = PrimArray Int Nucleotide---- |------ TODO is this fast enough?+-- * Representing nucleotide chains, aka primary sequence -instance Eq Primary where- xs == ys = bounds xs == bounds ys && toList xs == toList ys+-- | We use plain unboxed vectors for the primary sequence -instance Show Primary where- show p = "mkPrimary " ++ unPrimary p+type Primary = VU.Vector Nucleotide -instance Read Primary where- readsPrec p xs- | "mkPrimary " == chk = [(mkPrimary ps,ys)]- | otherwise = error $ show (chk,others,ps,ys)- where- (chk,others) = splitAt 10 xs- (ps,ys) = span (`elem` "ACGUE") others+-- | Conversion from/to primary sequence class MkPrimary a where mkPrimary :: a -> Primary unPrimary :: Primary -> a -instance MkPrimary String where- mkPrimary xs = fromList 0 (length xs -1) $ map charToNucleotide xs- unPrimary v = map nucleotideToChar $ toList v- {-# INLINE mkPrimary #-}- {-# INLINE unPrimary #-}--instance MkPrimary (VU.Vector Char) where- mkPrimary = mkPrimary . VU.toList- unPrimary = VU.fromList . unPrimary- {-# INLINE mkPrimary #-}- {-# INLINE unPrimary #-}------ * Encoding of Watson-Crick and Wobble Pairs in the Vienna RNA package style.--newtype ViennaPair = ViennaPair Int- deriving (Eq,Ord,Ix)--(vpNP:vpCG:vpGC:vpGU:vpUG:vpAU:vpUA:vpNS:_) = map ViennaPair [0..]--vpStrList :: [(Int,String)]-vpStrList = zip [0..] ["NP","CG","GC","GU","UG","AU","UA","NS"]-strVpList :: [(String,Int)]-strVpList = zip ["NP","CG","GC","GU","UG","AU","UA","NS"] [0..]--deriving instance VGM.MVector VU.MVector ViennaPair-deriving instance VG.Vector VU.Vector ViennaPair-deriving instance VU.Unbox ViennaPair-deriving instance Prim ViennaPair--instance Enum ViennaPair where- toEnum x- | x>=0 && x<=7 = ViennaPair x- | otherwise = error $ "can't make to enum" ++ show x- fromEnum (ViennaPair x) = x- {-# INLINE toEnum #-}- {-# INLINE fromEnum #-}+instance MkPrimary [Nucleotide] where+ mkPrimary = VU.fromList+ unPrimary = VU.toList -instance Bounded ViennaPair where- minBound = vpNP- maxBound = vpNS+instance MkPrimary String where+ mkPrimary = VU.fromList . map mkNuc+ unPrimary = map fromNuc . VU.toList -instance Show ViennaPair where- show (ViennaPair x)- | Just s <- x `lookup` vpStrList = s+instance MkPrimary BSL.ByteString where+ mkPrimary = VU.fromList . map mkNuc . BSL.unpack+ unPrimary = BSL.pack . map fromNuc . VU.toList -instance Read ViennaPair where- readsPrec p [] = []- readsPrec p [x] = []- readsPrec p (x:y:xs)- | x ==' ' = readsPrec p (y:xs)- | Just n <- (x:y:[]) `lookup` strVpList = [(ViennaPair n,xs)]- | otherwise = []+instance MkPrimary BSS.ByteString where+ mkPrimary = VU.fromList . map mkNuc . BSS.unpack+ unPrimary = BSS.pack . map fromNuc . VU.toList --- * convenience lists--acgu = [nucA .. nucU]-acguStr = map show acgu-acguPairs = [(b1,b2) | b1<-acgu, b2<-acgu]-eacgu = [nucE .. nucU]-npnsP = [vpNP .. vpNS]-cguaP = [vpCG .. vpUA]-cgnsP = [vpCG .. vpNS]+-- * Some convenience structures +eacgu = [nucE..nucU]+acgu = [nucA..nucU]+acguPairs = [(x,y)|x<-acgu,y<-acgu] --- * Transformations between Nucleotide and ViennaPair+-- * Currently impossible instances (changing with ghc 7.2) -pairTable = fromAssocs (nucE,nucE) (nucU,nucU) vpNP- [ ((nucC,nucG),vpCG)- , ((nucG,nucC),vpGC)- , ((nucG,nucU),vpGU)- , ((nucU,nucG),vpUG)- , ((nucA,nucU),vpAU)- , ((nucU,nucA),vpUA)- ]-{- NOINLINE pairTable #-}+{- TODO reactivate these instances with a later version of GHC+instance Show Primary where+ show p = "mkPrimary " ++ unPrimary p -toPair :: Nucleotide -> Nucleotide -> ViennaPair-toPair x y = pairTable ! (x,y)-{-- | x==nucC&&y==nucG = vpCG- | x==nucG&&y==nucC = vpGC- | x==nucG&&y==nucU = vpGU- | x==nucU&&y==nucG = vpUG- | x==nucA&&y==nucU = vpAU- | x==nucU&&y==nucA = vpUA- | otherwise = vpNP+instance Read Primary where+ readsPrec p xs+ | "mkPrimary " == chk = [(mkPrimary ps,ys)]+ | otherwise = error $ show (chk,others,ps,ys)+ where+ (chk,others) = splitAt 10 xs+ (ps,ys) = span (`elem` "ACGUE") others -}-{-# INLINE toPair #-}--pairs :: Nucleotide -> Nucleotide -> Bool-pairs a b = (>vpNP) $ toPair a b-{-# INLINE pairs #-}--vienna2Tuple p- | p==vpCG = (nucC,nucG)- | p==vpGC = (nucG,nucC)- | p==vpGU = (nucG,nucU)- | p==vpUG = (nucU,nucG)- | p==vpAU = (nucA,nucU)- | p==vpUA = (nucU,nucA)- | otherwise = error "non-standard pairs can't be backcasted"-{-# INLINE vienna2Tuple #-}--vienna2RevTuple p- | p==vpCG = (nucG,nucC)- | p==vpGC = (nucC,nucG)- | p==vpGU = (nucU,nucG)- | p==vpUG = (nucG,nucU)- | p==vpAU = (nucU,nucA)- | p==vpUA = (nucA,nucU)- | otherwise = error "non-standard pairs can't be backcasted"-{-# INLINE vienna2RevTuple #-}--tuple2Vienna (b1,b2)- | b1==nucC&&b2==nucG = vpCG- | b1==nucG&&b2==nucC = vpGC- | b1==nucG&&b2==nucU = vpGU- | b1==nucU&&b2==nucG = vpUG- | b1==nucA&&b2==nucU = vpAU- | b1==nucU&&b2==nucA = vpUA- | otherwise = vpNS-{-# INLINE tuple2Vienna #-}--tuple2RevVienna (a,b) = tuple2Vienna (b,a)-{-# INLINE tuple2RevVienna #-}
+ Biobase/RNA/Complex.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}++-- | Internal representation of RNA complexes. Ideally, each DataSource should+-- define an instance of 'MkComplex' for easy importing of foreign data.+--+-- TODO unify with Biobase.Structure.Complex++module Biobase.RNA.Complex where++import Control.DeepSeq+import qualified Data.Vector.Unboxed as VU++import Biobase.RNA+import Biobase.RNA.Pairs++++-- | An RNA complex. One or more RNA molecules linearly encoding as a+-- 'sequence'. Structure is stored as an unboxed vector. The (unspecified) type+-- is most likely either a 'CwwPair' or an 'ExtPair'. The 'chain' encodes (for+-- more than one participating nucleotide sequence) to which chain each+-- nucleotide in the sequence belongs.+--+-- NOTE 'chain' may be empty and there may be "ampersand" markers in the+-- 'sequence' which then define split positions.++data (VU.Unbox a, Show a, Read a) => Complex a = Complex+ { sequence :: Primary+ , structure :: Pairs a+ , chain :: VU.Vector Char+ }+ deriving (Read,Show)++-- | Create 'Complex'es from data sources.++class MkComplex a b where+ mkComplex :: a -> Complex b++++-- * 'CwwPair' instances++-- | Create a complex where only sequence is given.++instance MkComplex String CwwPair where+ mkComplex s = error "write me" -- Complex (mkPrimary s) (mkSecondary "") (VU.empty)++-- | Default interactive instance. Given sequence and dot-bracket string, both+-- as strings, create an instance.++instance MkComplex (String,String) CwwPair where+ mkComplex (s,p) = error "write me" -- Complex (mkPrimary s) (mkSecondary p) (VU.empty)++++-- * 'ExtPair' instances++instance MkComplex String ExtPair where+ mkComplex s = error "write me" -- Complex (mkPrimary s) (mkExtended "") (VU.empty)++++-- * Instances for Complex++-- | The NFData instance. Since these are unboxed vectors, we just need to make+-- sure that evaluation begins.++instance (NFData a, Read a, Show a, VU.Unbox a) => NFData (Complex a) where+ rnf Complex{..} = rnf (VU.length sequence) `seq` rnf structure `seq` rnf (VU.length chain) `seq` ()
+ Biobase/RNA/Hashes.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++-- | Fast hash functions for 'Primary' sequences.++module Biobase.RNA.Hashes where++import Control.DeepSeq+import Control.Exception.Base (assert)+import Data.Ix+import qualified Data.Vector.Unboxed as VU++import Biobase.RNA++newtype HashedPrimary = HashedPrimary Int+ deriving (Eq,Ord,Ix,NFData,Read,Show,Enum,Bounded)++-- | Given a piece of primary sequence information, reduce it to an index.+--+-- Will throw an assertion in debug code if 'ps' are not within bounds. Note+-- that "mkPrimary [minBound]" and "mkPrimary [minBound,minBound]" map to the+-- same index. Meaning that indices are only unique within the same length+-- group. Furthermore, indices with different (l,u)-bounds are not compatible+-- with each other. All indices start at 0.+--+-- The empty input produces an index of 0.++mkHashedPrimary :: (Nucleotide,Nucleotide) -> Primary -> HashedPrimary+mkHashedPrimary (l,u) ps = assert (VU.all (\p -> l<=p && p<=u) ps) $ HashedPrimary idx where+ idx = VU.sum $ VU.zipWith f ps (VU.enumFromStepN (VU.length ps -1) (-1) (VU.length ps))+ f p c = (fromEnum p - fromEnum l) * (cnst^c)+ cnst = fromEnum u - fromEnum l + 1+{-# INLINE mkHashedPrimary #-}
+ Biobase/RNA/NucBounds.hs view
@@ -0,0 +1,54 @@++-- | A special class of bounds for RNA/pair encodings that are used to index+-- into tables. We typically encode more in the alphabets than we want to use+-- to index, so in order to keep things simple, we have specialized bounds.++module Biobase.RNA.NucBounds where++import GHC.Tuple++++-- | 'minNormal' and 'maxNormal' encode for, say, ACGU; while 'minExtended' and+-- 'maxExtended' would allow 'N' as well. See Biobase.RNA and+-- Biobase.RNA.ViennaPair for instances.++class Bounded a => NucBounds a where+ minNormal :: a+ maxNormal :: a+ minExtended :: a+ maxExtended :: a++++-- * Instances for tuples of size 2-6++instance (NucBounds a, NucBounds b) => NucBounds (a,b) where+ minNormal = (minNormal, minNormal)+ maxNormal = (maxNormal, maxNormal)+ minExtended = (minExtended, minExtended)+ maxExtended = (maxExtended, maxExtended)++instance (NucBounds a, NucBounds b, NucBounds c) => NucBounds (a,b,c) where+ minNormal = (minNormal, minNormal, minNormal)+ maxNormal = (maxNormal, maxNormal, maxNormal)+ minExtended = (minExtended, minExtended, minExtended)+ maxExtended = (maxExtended, maxExtended, maxExtended)++instance (NucBounds a, NucBounds b, NucBounds c, NucBounds d) => NucBounds (a,b,c,d) where+ minNormal = (minNormal, minNormal, minNormal, minNormal)+ maxNormal = (maxNormal, maxNormal, maxNormal, maxNormal)+ minExtended = (minExtended, minExtended, minExtended, minExtended)+ maxExtended = (maxExtended, maxExtended, maxExtended, maxExtended)++instance (NucBounds a, NucBounds b, NucBounds c, NucBounds d, NucBounds e) => NucBounds (a,b,c,d,e) where+ minNormal = (minNormal, minNormal, minNormal, minNormal, minNormal)+ maxNormal = (maxNormal, maxNormal, maxNormal, maxNormal, maxNormal)+ minExtended = (minExtended, minExtended, minExtended, minExtended, minExtended)+ maxExtended = (maxExtended, maxExtended, maxExtended, maxExtended, maxExtended)++instance (NucBounds a, NucBounds b, NucBounds c, NucBounds d, NucBounds e, NucBounds f) => NucBounds (a,b,c,d,e,f) where+ minNormal = (minNormal, minNormal, minNormal, minNormal, minNormal, minNormal)+ maxNormal = (maxNormal, maxNormal, maxNormal, maxNormal, maxNormal, maxNormal)+ minExtended = (minExtended, minExtended, minExtended, minExtended, minExtended, minExtended)+ maxExtended = (maxExtended, maxExtended, maxExtended, maxExtended, maxExtended, maxExtended)
+ Biobase/RNA/Pairs.hs view
@@ -0,0 +1,124 @@+{-# LANGUAGE ParallelListComp #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeSynonymInstances #-}++-- | We want to be able to generate secondary structure representations from a+-- wide variety of inputs.+--+-- TODO include DotBracket, CT, lists of pairs,... some lossy conversions from+-- FamPair to CwwPair, etc...++module Biobase.RNA.Pairs where++import Control.DeepSeq+import Data.Vector.Unboxed.Read+import qualified Data.Vector.Unboxed as VU+import Data.List (nub)++-- | Canonical secondary structures, with the Watson-Crick cis pair family.++class MkSecondary a where+ mkSecondary :: a -> Pairs CwwPair++-- | Extended secondary structures, with any kind of pair family for each pair.++class MkExtended a where+ mkExtended :: a -> Pairs ExtPair++-- | Pair container. We store the sequence length as well in order to be able+-- to reconstruct the unpaired nucleotides without having to store them+-- explicitly.++data (VU.Unbox a, Show a, Read a) => Pairs a = Pairs+ { seqLength :: Int+ , pairs :: VU.Vector a+ }+ deriving (Eq,Show,Read)++++-- * Canonical secondary structures++-- | Most specific instance, just wrapping length and vector++instance MkSecondary (Int,VU.Vector CwwPair) where+ mkSecondary (l,xs) = Pairs l xs++-- | Only conversion to vector from list++instance MkSecondary (Int,[CwwPair]) where+ mkSecondary (l,xs) = mkSecondary (l,VU.fromList xs)++-- | Instance for MkSecondary++instance MkSecondary String where+ mkSecondary xs = mkPairList xs++++-- * Extended secondary structures++-- | The most specific instance possible++instance MkExtended (Int,VU.Vector ExtPair) where+ mkExtended (l,xs) = Pairs l xs++-- | Just turn list into a vector++instance MkExtended (Int,[ExtPair]) where+ mkExtended (l,xs) = mkExtended (l,VU.fromList xs)++-- | Create from a string. Here, we do not have pair family information and so+-- assume that all pairs are of the cWW type.++instance MkExtended String where+ mkExtended xs = mkExtended $ mkSecondary xs++-- | Create extended structure from CwwPair structure.+--+-- TODO still undefined until we have isostericity included++instance MkExtended (Pairs CwwPair) where+ mkExtended Pairs{..} = Pairs seqLength (VU.map (\(i,j) -> (i,j,error "mkExtended needs to know about isostericity")) pairs)++++-- * A basic dot-bracket parser. Not a datasource due to it being universally needed.++-- | We only return 'CwwPair's as dot-bracket pairs, others can not be encoded.++mkPairList :: String -> Pairs CwwPair+mkPairList s = mkSecondary (length s, concatMap (\b -> mkPairListWith b s) bs) where+ z = nub s+ bs = filter (\[l,r] -> l `elem` z && r `elem` z) defBrackets++-- | Generic dot-bracket parser accepting more than one bracket type.++mkPairListWith :: String -> String -> [CwwPair]+mkPairListWith [l,r] s = f [] 0 s where+ f _ _ [] = []+ f s k (x:xs)+ | x==l = f (k:s) (k+1) xs+ | x==r = (head s, k) : f (tail s) (k+1) xs+ | otherwise = f s (k+1) xs++-- | These are the default bracket types to consider++defBrackets =+ [ "()"+ , "{}"+ , "[]"+ , "<>"+ ] +++ [ [b,s] | b <- ['A'..'Z'] | s <- ['a'..'z'] ]++++-- * Types and instances++type CwwPair = (Int,Int)+type ExtPair = (Int,Int,Int)++instance (NFData a, Read a, Show a, VU.Unbox a) => NFData (Pairs a) where+ rnf Pairs{..} = rnf seqLength `seq` rnf (VU.length pairs) `seq` ()
+ Biobase/RNA/ViennaPair.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE StandaloneDeriving #-}++-- | Encoding of Watson-Crick and Wobble Pairs in the Vienna RNA package style.++module Biobase.RNA.ViennaPair where++import Data.Ix+import qualified Data.Vector.Generic as VG+import Data.Primitive.Types+import qualified Data.Vector.Generic.Mutable as VGM+import qualified Data.Vector.Unboxed as VU+import Data.Tuple.HT (swap)++import Biobase.RNA+import Biobase.RNA.NucBounds++++-- | Use machine Ints internally++newtype ViennaPair = ViennaPair Int+ deriving (Eq,Ord,Ix)++(vpNP:vpCG:vpGC:vpGU:vpUG:vpAU:vpUA:vpNS:_) = map ViennaPair [0..]++class MkViennaPair a where+ mkViennaPair :: a -> ViennaPair+ fromViennaPair :: ViennaPair -> a++instance MkViennaPair (Nucleotide,Nucleotide) where+ mkViennaPair (b1,b2)+ | b1==nucC&&b2==nucG = vpCG+ | b1==nucG&&b2==nucC = vpGC+ | b1==nucG&&b2==nucU = vpGU+ | b1==nucU&&b2==nucG = vpUG+ | b1==nucA&&b2==nucU = vpAU+ | b1==nucU&&b2==nucA = vpUA+ | otherwise = vpNS+ fromViennaPair p+ | p==vpCG = (nucC,nucG)+ | p==vpGC = (nucG,nucC)+ | p==vpGU = (nucG,nucU)+ | p==vpUG = (nucU,nucG)+ | p==vpAU = (nucA,nucU)+ | p==vpUA = (nucU,nucA)+ | otherwise = error "non-standard pairs can't be backcasted"++deriving instance VGM.MVector VU.MVector ViennaPair+deriving instance VG.Vector VU.Vector ViennaPair+deriving instance VU.Unbox ViennaPair+deriving instance Prim ViennaPair++instance Enum ViennaPair where+ toEnum x+ | x>=0 && x<=7 = ViennaPair x+ | otherwise = error $ "can't make to enum" ++ show x+ fromEnum (ViennaPair x) = x+ {-# INLINE toEnum #-}+ {-# INLINE fromEnum #-}++instance Bounded ViennaPair where+ minBound = vpNP+ maxBound = vpNS++instance NucBounds ViennaPair where+ minNormal = vpCG+ maxNormal = vpUA+ minExtended = vpNP+ maxExtended = vpNS++instance Show ViennaPair where+ show x+ | Just s <- x `lookup` pairToString = s++instance Read ViennaPair where+ readsPrec p [] = []+ readsPrec p [x] = []+ readsPrec p (x:y:xs)+ | x ==' ' = readsPrec p (y:xs)+ | Just n <- (x:y:[]) `lookup` s2p = [(n,xs)]+ | otherwise = []+ where s2p = (map swap pairToString)++++-- | reverse a vienna pair++revPair :: ViennaPair -> ViennaPair+revPair p+ | p==vpCG = vpGC+ | p==vpGC = vpCG+ | p==vpGU = vpUG+ | p==vpUG = vpGU+ | p==vpAU = vpUA+ | p==vpUA = vpAU+ | p==vpNP = vpNP+ | p==vpNS = vpNS++++-- * Convenience structures++cguaP = [vpCG..vpUA]+cgnsP = [vpCG..vpNS]+pairToString = [(vpCG,"CG"),(vpGC,"GC"),(vpUA,"UA"),(vpAU,"AU"),(vpGU,"GU"),(vpUG,"UG"),(vpNS,"NS"),(vpNP,"NP")]
− Biobase/Turner.hs
@@ -1,41 +0,0 @@-{-# LANGUAGE TypeSynonymInstances #-}---- | Mathews / Turner nearest neighbor energy tables for interactions between--- RNA-RNA and DNA-DNA. Using lazy tables for easy filling of missing data.--- Transform tables into uvectors for efficient access.--module Biobase.Turner where--import Biobase.RNA (Nucleotide)-import qualified Biobase.Turner.Tables as T------ | Data structure containing all necessary tables for the Turner 2004 model.--- Note the temperature, using an additional function, rescaling becomes--- possible. A Show and a Read instance are automatically derived but one--- should use the Turner and/or Vienna import/export facilities. All data uses--- complete tables, where any base can pair with any other. Missing data ('.'--- in tables) is given by 'Nothing', otherwise we have 'Just Int'.--- --- In general, have a look here:--- \url{http://rna.urmc.rochester.edu/NNDB/turner04/index.html} where--- parameters are explained.--- --- Conversion from Turner to Vienna is only possible in one direction as a--- number of parameters are not used in Vienna RNA Folding.------ We are missing tables for DNA-RNA data: helixdr.dat, stackdr.dat,--- stackdr.dh. Several other files have unknown data, too. These are:--- dnadynalign*, fam\_hmm\_pars.dat, helix.dat, int22-exp.dh--type TurnerTables = T.Turner2004 Basepair Nucleotide Double--type TurnerEntropy = TurnerTables-type TurnerEnthalpy = TurnerTables-type Temperature = Double-type TurnerSet = (Temperature,TurnerEntropy,TurnerEnthalpy)--type Basepair = (Nucleotide,Nucleotide)
− Biobase/Turner/Import.hs
@@ -1,176 +0,0 @@-{-# LANGUAGE NoMonomorphismRestriction #-}---- | Turner file parser. Returns a Turner2004 data structure. We store data in--- the same way it is stored in the ViennaRNA package. Pairs are tuples--- however.------ How is 'stack' data stored:------ AX--- UY -> ((A,U),(Y,X))------ How 'iloop1x1' is stored:------ X--- A G--- U C -> ((A,U),(C,G),X,Y)--- Y------ Now 'iloop1x2' is stored:------ X--- A G--- U C -> ((A,U),(C,G),X,C,Y), single (X) first, then 5' to 3'--- YC------ 'iloop2x2' is stored:------ XY--- A G--- U C -> ((A,U),(C,G),X,Y,y,x), X-->Y then x<--y--- xy------TODO not sure if dangle3/dangle5 are correctly split or if they should switch--module Biobase.Turner.Import- ( parseTurner- ) where--import Control.Applicative-import Control.Arrow (first)-import Control.Monad-import Data.Either-import Data.List.Split (splitEvery)-import Data.List (transpose)-import qualified Data.Map as M-import System.FilePath.Find-import Text.Parsec hiding ((<|>), many)-import Text.Parsec.String--import Biobase.RNA-import Data.Ix.Tuple-import Data.PrimitiveArray-import Data.PrimitiveArray.Ix-import Text.Parsec.Numbers--import Biobase.Turner.Tables------ * Associate every file with a parse.--minp = (nucA,nucA)-maxp = (nucU,nucU)-minpb = (minp,nucA)-maxpb = (maxp,nucU)-minpp = (minp,minp)-maxpp = (maxp,maxp)-minppbb = (minp,minp,nucA,nucA)-maxppbb = (maxp,maxp,nucU,nucU)-minppbbb = (minp,minp,nucA,nucA,nucA)-maxppbbb = (maxp,maxp,nucU,nucU,nucU)-minppbbbb = (minp,minp,nucA,nucA,nucA,nucA)-maxppbbbb = (maxp,maxp,nucU,nucU,nucU,nucU)-minpbb = (minp,nucA,nucA)-maxpbb = (maxp,nucU,nucU)--- (4,3) switched for vienna rna compatibility-keyspp = [((k1,k2),(k4,k3)) | k1 <- acgu, k3 <- acgu, k2 <- acgu, k4 <- acgu]-keyspb = [((k1,k2),k3) | k1 <- acgu, k2 <- acgu, k3 <- acgu]-keyspbb = [((k1,k2),k3,k4) | k1 <- acgu, k3 <- acgu, k2 <- acgu, k4 <- acgu]-plist11 = [(nucA,nucU),(nucC,nucG),(nucG,nucC),(nucU,nucA),(nucG,nucU),(nucU,nucG)]-plist22 = [(nucA,nucU),(nucC,nucG),(nucG,nucC),(nucG,nucU),(nucU,nucA),(nucU,nucG)]--- (4,3) switched for vienna rna compatibility-keysppbb = [((k1,k2),(k4,k3),k5,k6) | (k1,k2) <- plist11, k5 <- acgu, (k3,k4) <- plist11, k6 <- acgu]--- (4,3) switched for vienna rna compatibility-keysppbbb = [((k1,k2),(k4,k3),k5,k6,k7) | (k1,k2) <- plist11, k6 <- acgu, k5 <- acgu, (k3,k4) <- plist11, k7 <- acgu]--- (4,3) switched for vienna rna compatibility, 5786 is 5'3' order top, bottom!-keysppbbbb = [((k1,k2),(k4,k3),k5,k6,k7,k8) | (k1,k2) <- plist22, (k3,k4) <- plist22, k5 <- acgu, k8 <- acgu, k6 <- acgu, k7 <- acgu]-z = 999999------ | Given the base dir and a suffix (.dat/.dh most likely), parse the relevant--- files. The prefix can be used for, eg., dna file--parseTurner prefix basedir fsuffix = do- vstack <- grabB basedir fsuffix $ prefix ++ "stack"- vdangles <- grabB basedir fsuffix $ prefix ++ "dangle"- vlengths <- grabB basedir fsuffix $ prefix ++ "loop"- vhairmm <- grabB basedir fsuffix $ prefix ++ "tstackh"- viloopmm <- grabB basedir fsuffix $ prefix ++ "tstacki"- viloop23mm <- grabB basedir fsuffix $ prefix ++ "tstacki23"- viloop1nmm <- grabB basedir fsuffix $ prefix ++ "tstacki1n"- vmultimm <- grabB basedir fsuffix $ prefix ++ "tstackm"- vextmm <- grabB basedir fsuffix $ prefix ++ "tstack"- viloop11 <- grabB basedir fsuffix $ prefix ++ "int11"- viloop12 <- grabB basedir fsuffix $ prefix ++ "int21"- viloop22 <- grabB basedir fsuffix $ prefix ++ "int22"- vlookups <- fmap (map (first (map charToNucleotide)) . concat) $ mapM (\f -> grabA basedir fsuffix $ prefix ++ f) ["triloop","tloop","hexaloop"]- vmisc <- grabB basedir fsuffix $ prefix ++ "miscloop"- let (vdangle3,vdangle5) = splitAt (length vdangles `div` 2) vdangles- let (_:viloopl:vbulgel:vhairpinl:[]) = transpose $ splitEvery 4 vlengths- return $ Turner2004- { stack = fromAssocs minpp maxpp z $ zip keyspp vstack- , dangle3 = fromAssocs minpb maxpb z $ zip keyspb vdangle3- , dangle5 = fromAssocs minpb maxpb z $ zip keyspb vdangle5- , hairpinL = fromAssocs 0 30 z $ zip [1..] vhairpinl- , bulgeL = fromAssocs 0 30 z $ zip [1..] vbulgel- , iloopL = fromAssocs 0 30 z $ zip [1..] viloopl- , hairpinMM = fromAssocs minpbb maxpbb z $ zip keyspbb vhairmm- , iloopMM = fromAssocs minpbb maxpbb z $ zip keyspbb viloopmm- , iloop2x3MM = fromAssocs minpbb maxpbb z $ zip keyspbb viloop23mm- , iloop1xnMM = fromAssocs minpbb maxpbb z $ zip keyspbb viloop1nmm- , multiMM = fromAssocs minpbb maxpbb z $ zip keyspbb vmultimm- , extMM = fromAssocs minpbb maxpbb z $ zip keyspbb vextmm- , hairpinLookup = M.fromList vlookups- , iloop1x1 = fromAssocs minppbb maxppbb z $ zip keysppbb viloop11- , iloop1x2 = fromAssocs minppbbb maxppbbb z $ zip keysppbbb viloop12- , iloop2x2 = fromAssocs minppbbbb maxppbbbb z $ zip keysppbbbb viloop22- , ninio = vmisc !! 2- , maxNinio = vmisc !! 1- , multiOffset = vmisc !! 6- , multiNuc = vmisc !! 7- , multiHelix = vmisc !! 8- , largeLoop = vmisc !! 0- , termAU = vmisc !! 14- , intermolecularInit = vmisc !! 19- }--grabB basedir fsuffix fname = do- p <- parseFromFile pBlockFile (basedir ++ "/" ++ fname ++ fsuffix)- case p of- (Right ans) -> return ans- (Left err) -> error $ show err--grabA basedir fsuffix fname = do- p <- parseFromFile pAssocFile (basedir ++ "/" ++ fname ++ fsuffix)- case p of- (Right ans) -> return ans- (Left err) -> error $ show err------ * File parser: We do not want to understand the format, just extract all--- data.---- | Blocks of data.--pBlockFile = concat <$> many (try numberRow <|> infoRow) <* eof where- -- a line with a least one number- numberRow = many (char ' ') *> (number <* notFollowedBy (char '\'')) `sepEndBy1` (many $ char ' ') <* newline- -- a number is a dot or some extended floating point number- number = (try dotFloat) <|> (999999 <$ char '.') <|> parseExtFloat <?> "floating point number"---- | A File with associations.--pAssocFile = concat <$> many1 (try assocRow <|> infoRow) where- -- one assocs of string, value- assocRow = (\a b -> [(a,b)]) <$ many (char ' ') <*> many1 (oneOf nuc) <* many (char ' ') <*> parseExtFloat <* many (char ' ')---- a line with crap-infoRow = [] <$ anyChar `manyTill` newline---- a rather stupid float-dotFloat = (\s a b -> read $ s:'0':a:b) <$> (char '-' <|> pure ' ') <*> char '.' <*> many1 digit--nuc = "ACGUT"
− Biobase/Turner/Tables.hs
@@ -1,133 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TypeSynonymInstances #-}---- | Turner Nearest Neighbor Energy Tables}---- TODO (Read) instance? (Vector has no Read instance...)--module Biobase.Turner.Tables where--import qualified Data.Map as M--import Data.PrimitiveArray-import Data.PrimitiveArray.Ix------ | A data structure describing all fields as used by the Turner 2004--- parameter set. Some fields are commented out until they are being used.--data Turner2004 a b c = Turner2004- { stack :: PrimArray (a,a) c- , dangle3 :: PrimArray (a,b) c- , dangle5 :: PrimArray (a,b) c- , hairpinL :: PrimArray Int c- , hairpinMM :: PrimArray (a,b,b) c- , hairpinLookup :: M.Map [b] c--- , hairpinGGG :: c--- , hairpinCslope :: c--- , hairpinCintercept :: c--- , hairpinC3 :: c- , bulgeL :: PrimArray Int c--- , bulgeSingleC :: c- , iloop1x1 :: PrimArray (a,a,b,b) c- , iloop1x2 :: PrimArray (a,a,b,b,b) c- , iloop2x2 :: PrimArray (a,a,b,b,b,b) c- , iloopMM :: PrimArray (a,b,b) c- , iloop2x3MM :: PrimArray (a,b,b) c- , iloop1xnMM :: PrimArray (a,b,b) c- , iloopL :: PrimArray Int c- , multiMM :: PrimArray (a,b,b) c- , ninio :: c- , maxNinio :: c- , multiOffset :: c- , multiNuc :: c- , multiHelix :: c--- , multiAsym :: c--- , multiStrain :: c- , extMM :: PrimArray (a,b,b) c--- , coaxStack :: PrimArray (a,a) c--- , coaxStackOpen :: PrimArray (a,b,b) c--- , coaxStackCont :: PrimArray (a,b,b) c- , largeLoop :: Double- , termAU :: c- , intermolecularInit :: c- }------ | Map functions over the payload.--dmap f Turner2004{..} = Turner2004- { stack = amap f stack- , dangle3 = amap f dangle3- , dangle5 = amap f dangle5- , hairpinL = amap f hairpinL- , hairpinMM = amap f hairpinMM- , hairpinLookup = fmap f hairpinLookup--- , hairpinGGG = f hairpinGGG--- , hairpinCslope = f hairpinCslope--- , hairpinCintercept = f hairpinCintercept--- , hairpinC3 = f hairpinC3- , bulgeL = amap f bulgeL--- , bulgeSingleC = f bulgeSingleC- , iloop1x1 = amap f iloop1x1- , iloop1x2 = amap f iloop1x2- , iloop2x2 = amap f iloop2x2- , iloopMM = amap f iloopMM- , iloop2x3MM = amap f iloop2x3MM- , iloop1xnMM = amap f iloop1xnMM- , iloopL = amap f iloopL- , multiMM = amap f multiMM- , ninio = f ninio- , maxNinio = f maxNinio- , multiOffset = f multiOffset- , multiNuc = f multiNuc- , multiHelix = f multiHelix--- , multiAsym = f multiAsym--- , multiStrain = f multiStrain- , extMM = amap f extMM--- , coaxStack = amap f coaxStack--- , coaxStackOpen = amap f coaxStackOpen--- , coaxStackCont = amap f coaxStackCont- , largeLoop = largeLoop- , termAU = f termAU- , intermolecularInit = f intermolecularInit- }------ | Zip two payloads.------ TODO right now, we have undefined behaviour when some arrrays are of different length--dZipWith f t1 t2 = Turner2004- { stack = zipWithPA f (stack t1) (stack t2)- , dangle3 = zipWithPA f (dangle3 t1) (dangle3 t2)- , dangle5 = zipWithPA f (dangle5 t1) (dangle5 t2)- , hairpinL = zipWithPA f (hairpinL t1) (hairpinL t2)- , hairpinMM = zipWithPA f (hairpinMM t1) (hairpinMM t2)- , hairpinLookup = undefined -- zipWithPA f (hairpinLookup t1) (hairpinLookup t2)- , bulgeL = zipWithPA f (bulgeL t1) (bulgeL t2)- , iloop1x1 = zipWithPA f (iloop1x1 t1) (iloop1x1 t2)- , iloop1x2 = zipWithPA f (iloop1x2 t1) (iloop1x2 t2)- , iloop2x2 = zipWithPA f (iloop2x2 t1) (iloop2x2 t2)- , iloopMM = zipWithPA f (iloopMM t1) (iloopMM t2)- , iloop2x3MM = zipWithPA f (iloop2x3MM t1) (iloop2x3MM t2)- , iloop1xnMM = zipWithPA f (iloop1xnMM t1) (iloop1xnMM t2)- , iloopL = zipWithPA f (iloopL t1) (iloopL t2)- , multiMM = zipWithPA f (multiMM t1) (multiMM t2)- , ninio = f (ninio t1) (ninio t2)- , maxNinio = f (maxNinio t1) (maxNinio t2)- , multiOffset = f (multiOffset t1) (multiOffset t2)- , multiNuc = f (multiNuc t1) (multiNuc t2)- , multiHelix = f (multiHelix t1) (multiHelix t2)- , extMM = zipWithPA f (extMM t1) (extMM t2)- , largeLoop = largeLoop t1 -- no zipping here! TODO make this a constant somewhere!- , termAU = f (termAU t1) (termAU t2)- , intermolecularInit = f (intermolecularInit t1) (intermolecularInit t2)- }--zipWithPA f a1 a2 = let (l,u) = bounds a1 in fromList l u $ zipWith f (toList a1) (toList a2)
− Biobase/Vienna.hs
@@ -1,89 +0,0 @@-{-# LANGUAGE NoMonomorphismRestriction #-}---- | Turner energy data as used in the ViennaRNA package.------ TODO should use energy type for tables, not int!--module Biobase.Vienna where--import Data.Map (Map,empty)--import Data.Ix.Tuple-import Data.PrimitiveArray.Ix-import Data.PrimitiveArray-import Biobase.Types.Partition-import Biobase.Types.Energy--import Biobase.RNA-import Biobase.Turner.Tables-import Biobase.Constants------ Type for Vienna Tables---- type ViennaEnergySet = (Temperature, ViennaTables, ViennaTables)--type ViennaIntTables = Turner2004 ViennaPair Nucleotide Int-type ViennaEnergyTables = Turner2004 ViennaPair Nucleotide Energy-type ViennaPartitionTables = Turner2004 ViennaPair Nucleotide Partition--type Temperature = Double------ | An empty Turner2004 set, with Vienna-style keys for tables. Unused fields--- are commented out. Activate them in BiobaseTurner before doing the same--- here!--emptyTables :: ViennaIntTables-emptyTables = Turner2004- --stack- { stack = emptyIV- --dangle- , dangle3 = emptyIV- , dangle5 = emptyIV- --hairpin- , hairpinL = emptyV- , hairpinMM = emptyIV- , hairpinLookup = empty- --eInf- --eInf- --eInf- --eInf- --bulge- , bulgeL = emptyV- --eInf- --internal- , iloop1x1 = emptyIV- , iloop1x2 = emptyIV- , iloop2x2 = emptyIV- , iloopMM = emptyIV- , iloop2x3MM = emptyIV- , iloop1xnMM = emptyIV- , iloopL = emptyV- --multibranch- , multiMM = emptyIV- , ninio = eInf- , maxNinio = eInf- , multiOffset = eInf- , multiNuc = eInf- , multiHelix = eInf- --eInf- --eInf- --exterior- , extMM = emptyIV- --coaxial stacking- --emptyIV- --emptyIV- --emptyIV- --scalar values- , largeLoop = fInf -- large loop is always double- , termAU = eInf- , intermolecularInit = eInf- }--emptyIV = fromAssocs minBound maxBound eInf []---- TODO should be an empty a-emptyV = fromAssocs 0 30 eInf []
− Biobase/Vienna/Default.hs
@@ -1,27 +0,0 @@--{-# LANGUAGE TemplateHaskell #-}---- | Embedding of a default set of parameters. These are encoded in Vienna style and--- use the Turner2004 set of parameters.--module Biobase.Vienna.Default- ( turner2004GH- ) where--import Data.FileEmbed-import qualified Data.ByteString.Char8 as B--import Biobase.Vienna.Import.ViennaPar-import Biobase.Turner.Tables-import Biobase.Vienna-import Biobase.Types.Energy----defaultPars :: B.ByteString-defaultPars = $(embedFile "parfiles/Turner2004GH.par")---- Turner entropy and enthalpy tables.--turner2004GH = (dmap Energy ta,dmap Energy tb) where- (ta,tb) = importPar $ B.unpack defaultPars
− Biobase/Vienna/Export/ViennaC.hs
@@ -1,264 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}---- | Exports the Vienna energy tables as a number of C files (one .c file, a--- number .h files). For this reason, files are written into a target--- directory!--module Biobase.Vienna.Export.ViennaC- ( export- ) where--import Prelude hiding (pi)-import Text.Printf-import System.Directory-import Data.List.Split-import Data.List-import qualified Data.Map as M-import Data.FileEmbed-import qualified Data.ByteString.Char8 as B--import Biobase.Turner.Tables-import Biobase.Vienna-import Data.PrimitiveArray-import Biobase.RNA--import Biobase.Vienna.Default--(g,h) = turner2004GH----type Directory = FilePath---- | Export the files required for default values in the ViennaRNA 2.0 C--- package.--export :: ViennaIntTables -> ViennaIntTables -> Directory -> IO ()-export trnrG trnrH target = mapM_ (\f -> f trnrG trnrH target) [exportC, export11, export21, export22]------ | Export the main C file--exportC :: ViennaIntTables -> ViennaIntTables -> Directory -> IO ()-exportC trnrG trnrH target = writeFile (target ++ "/energy_par.c") out where- out = unlines [ B.unpack $(embedFile "templates/cheader") , xs, stck, lps, mms, dngls, tris, tets, hexs,includes]- xs = unlines- [ pd "lxc37" $ largeLoop trnrG- , pi "ML_intern37" $ multiHelix trnrG- , pi "ML_interndH" $ multiHelix trnrH- , pi "ML_closing37" $ multiOffset trnrG- , pi "ML_closingdH" $ multiOffset trnrH- , pi "ML_BASE37" $ multiNuc trnrG- , pi "ML_BASEdH" $ multiNuc trnrH- , pi "MAX_NINIO" $ maxNinio trnrG- , pi "ninio37" $ ninio trnrG- , pi "niniodH" $ ninio trnrH- , pi "TerminalAU37" $ termAU trnrG- , pi "TerminalAUdH" $ termAU trnrH- , pi "DuplexInit37" $ intermolecularInit trnrG- , pi "DuplexInitdH" $ intermolecularInit trnrH- , pi "TripleC37" 100- , pi "TripleCdH" 1860- , pi "MultipleCA37" 30- , pi "MultipleCAdH" 340- , pi "MultipleCB37" 160- , pi "MultipleCBdH" 760- ]- stck = unlines- [ "PUBLIC int stack37[NBPAIRS+1][NBPAIRS+1] ="- , (block2 8 . toList $ stack trnrG)- , "PUBLIC int stackdH[NBPAIRS+1][NBPAIRS+1] ="- , (block2 8 . toList $ stack trnrH)- ]- lps = unlines- [ "PUBLIC int hairpin37[31] = {" ++ (concat . intersperse "," . map printNum . toList $ hairpinL trnrG) ++ "};"- , "PUBLIC int hairpindH[31] = {" ++ (concat . intersperse "," . map printNum . toList $ hairpinL trnrH) ++ "};"- , "PUBLIC int bulge37[31] = {" ++ (concat . intersperse "," . map printNum . toList $ bulgeL trnrG) ++ "};"- , "PUBLIC int bulgedH[31] = {" ++ (concat . intersperse "," . map printNum . toList $ bulgeL trnrH) ++ "};"- , "PUBLIC int internal_loop37[31] = {" ++ (concat . intersperse "," . map printNum . toList $ iloopL trnrG) ++ "};"- , "PUBLIC int internal_loopdH[31] = {" ++ (concat . intersperse "," . map printNum . toList $ iloopL trnrH) ++ "};"- ]- mms = unlines- [ writeMM "I" iloopMM trnrG trnrH- , writeMM "H" hairpinMM trnrG trnrH- , writeMM "M" multiMM trnrG trnrH- , writeMM "1nI" iloop1xnMM trnrG trnrH- , writeMM "23I" iloop2x3MM trnrG trnrH- , writeMM "Ext" extMM trnrG trnrH- ]- dngls = unlines- [ "PUBLIC int dangle3_37[NBPAIRS+1][5] ="- , block2 5 . toList $ dangle3 trnrG- , "PUBLIC int dangle3_dH[NBPAIRS+1][5] ="- , block2 5 . toList $ dangle3 trnrH- , "PUBLIC int dangle5_37[NBPAIRS+1][5] ="- , block2 5 . toList $ dangle5 trnrG- , "PUBLIC int dangle5_dH[NBPAIRS+1][5] ="- , block2 5 . toList $ dangle5 trnrH- ]- t3 = getLookup 3 trnrG trnrH- t4 = getLookup 4 trnrG trnrH- t6 = getLookup 6 trnrG trnrH- tris = writeTabbed 3 "Triloop" t3- tets = writeTabbed 4 "Tetraloop" t4- hexs = writeTabbed 6 "Hexaloop" t6-- includes = unlines $ map ((++ "\"") . ("#include \""++))- [ "intl11.h"- , "intl11dH.h"- , "intl21.h"- , "intl21dH.h"- , "intl22.h"- , "intl22dH.h"- ]------ | Export iloops 1x1--export11 :: ViennaIntTables -> ViennaIntTables -> Directory -> IO ()-export11 trnrG trnrH target = writeFile (target ++ "/intl11.h") outG >> writeFile (target ++ "/intl11dH.h") outH where- outG = unlines- [ "PUBLIC int int11_37[NBPAIRS+1][NBPAIRS+1][5][5] ="- , (block4 8 5 5 . toList $ iloop1x1 trnrG)- ]- outH = unlines- [ "PUBLIC int int11_dH[NBPAIRS+1][NBPAIRS+1][5][5] ="- , (block4 8 5 5 . toList $ iloop1x1 trnrH)- ]------ | Export iloops 2x1--export21 :: ViennaIntTables -> ViennaIntTables -> Directory -> IO ()-export21 trnrG trnrH target = writeFile (target ++ "/intl21.h") outG >> writeFile (target ++ "/intl21dH.h") outH where- outG = unlines- [ "PUBLIC int int21_37[NBPAIRS+1][NBPAIRS+1][5][5][5] ="- , (block5 8 5 5 5 . toList $ iloop1x2 trnrG)- ]- outH = unlines- [ "PUBLIC int int21_dH[NBPAIRS+1][NBPAIRS+1][5][5][5] ="- , (block5 8 5 5 5 . toList $ iloop1x2 trnrH)- ]------ | Export iloops 2x2--export22 :: ViennaIntTables -> ViennaIntTables -> Directory -> IO ()-export22 trnrG trnrH target = writeFile (target ++ "/intl22.h") outG >> writeFile (target ++ "/intl22dH.h") outH where- outG = unlines- [ "PUBLIC int int22_37[NBPAIRS+1][NBPAIRS+1][5][5][5][5] ="- , (block6 8 5 5 5 5 . toList $ iloop2x2 trnrG)- ]- outH = unlines- [ "PUBLIC int int22_dH[NBPAIRS+1][NBPAIRS+1][5][5][5][5] ="- , (block6 8 5 5 5 5 . toList $ iloop2x2 trnrH)- ]------ * Helper functions--writeTabbed (ksize :: Int) key (ns,gs,hs) = unlines- [ printf "PUBLIC char %ss[%d] =" key ((ksize+3)*40+1)- , ns- , ";"- ] ++ printf "PUBLIC int %s37[40] = " key ++ gs ++ ";\n"- ++ printf "PUBLIC int %sdH[40] = " key ++ hs ++ ";\n"--getLookup k trnrG trnrH = (nsF,gs,hs) where- nsF = concat $ intersperse "\n" $ map ((++ " \"") . (" \"" ++) . map nucleotideToChar) ns- ns = filter ((==(k+2)) . length) . M.keys $ hairpinLookup trnrG- gs = lkup trnrG- hs = lkup trnrH- lkup tbl = ("{"++) . (++"}") . concat . intersperse "," $ map (printNum . (hairpinLookup tbl M.!)) ns--writeMM typ fun trnrG trnrH = unlines- [ printf "PUBLIC int mismatch%s37[NBPAIRS+1][5][5] =" typ- , block3 5 5 . toList $ fun trnrG- , printf "PUBLIC int mismatch%sdH[NBPAIRS+1][5][5] =" typ- , block3 5 5 . toList $ fun trnrH- ]--block2 s2 xs- = (++ "};")- . ("{" ++)- . concat- . intersperse "\n,"- . map ((++ "}") . ("{" ++) . concat . intersperse ",")- . splitEvery s2- $ map printNum xs--block3 s2 s3 xs- = (++ "};")- . ("{" ++)- . concat- . intersperse "\n,"- . map ((++ "}") . ("{" ++) . concat . intersperse ",")- . splitEvery s2- . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")- . splitEvery s3- $ map printNum xs--block4 s2 s3 s4 xs- = (++ "};")- . ("{" ++)- . concat- . intersperse "\n,"- . map ((++ "}") . ("{" ++) . concat . intersperse ",")- . splitEvery s2- . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")- . splitEvery s3- . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")- . splitEvery s4- $ map printNum xs--block5 s2 s3 s4 s5 xs- = (++ "};")- . ("{" ++)- . concat- . intersperse "\n,"- . map ((++ "}") . ("{" ++) . concat . intersperse ",")- . splitEvery s2- . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")- . splitEvery s3- . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")- . splitEvery s4- . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")- . splitEvery s5- $ map printNum xs--block6 s2 s3 s4 s5 s6 xs- = (++ "};")- . ("{" ++)- . concat- . intersperse "\n,"- . map ((++ "}") . ("{" ++) . concat . intersperse ",")- . splitEvery s2- . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")- . splitEvery s3- . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")- . splitEvery s4- . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")- . splitEvery s5- . map ((++ "}\n ") . ("{" ++) . concat . intersperse ",")- . splitEvery s6- $ map printNum xs---pd :: String -> Double -> String-pd k v = printf "PUBLIC double %s=%f;" k v--pi :: String -> Int -> String-pi k v = printf "PUBLIC int %s=%d;" k v--printNum :: Int -> String-printNum n- | n >= maxN = " INF"- | otherwise = printf "%6d" n- where- maxN = 10000
− Biobase/Vienna/Export/ViennaPar.hs
@@ -1,139 +0,0 @@--{-# LANGUAGE NoMonomorphismRestriction #-}--module Biobase.Vienna.Export.ViennaPar- ( export- ) where--import Data.Tuple.Select-import Data.List.Split-import Text.Printf-import Control.Arrow-import Data.List (intersperse)-import qualified Data.Map as M--import Data.PrimitiveArray-import Biobase.Turner.Tables-import Biobase.RNA-import Biobase.Constants--import Biobase.Vienna----export :: ViennaIntTables -> ViennaIntTables -> String-export trnr trnrH = hdr ++ blocks ++ mlps ++ ninios ++ misc ++ triloops ++ tetra ++ hexa ++ "\n#END" where- hdr = "## RNAfold parameter file v2.0\n\n"- mlps = printf "# ML_params\n%7d %7d %7d %7d %7d %7d\n\n"- (multiNuc trnr) (multiNuc trnrH)- (multiOffset trnr) (multiOffset trnrH)- (multiHelix trnr) (multiHelix trnrH)- ninios = printf "# NINIO\n%7d %7d %7d\n\n"- (ninio trnr) (ninio trnrH) (maxNinio trnr)- misc = printf "# Misc\n %7d %7d %7d %7d\n\n"- (intermolecularInit trnr) (intermolecularInit trnrH) (termAU trnr) (termAU trnrH)- triloops = "# Triloops\n" ++ printHairpinAssocs 5 trnr trnrH ++ "\n"- tetra = "# Tetraloops\n" ++ printHairpinAssocs 6 trnr trnrH ++ "\n"- hexa = "# Hexaloops\n" ++ printHairpinAssocs 8 trnr trnrH ++ "\n"- blocks = concat $ zipWith (++)- -- entropy terms- [ printBlock "stack" 7 pp2lkey $ stack trnr- , printBlock "mismatch_hairpin" 5 pbb2lkey $ hairpinMM trnr- , printBlock "mismatch_interior" 5 pbb2lkey $ iloopMM trnr- , printBlock "mismatch_interior_1n" 5 pbb2lkey $ iloop1xnMM trnr- , printBlock "mismatch_interior_23" 5 pbb2lkey $ iloop2x3MM trnr- , printBlock "mismatch_multi" 5 pbb2lkey $ multiMM trnr- , printBlock "mismatch_exterior" 5 pbb2lkey $ extMM trnr- , printBlock "dangle5" 5 pb2lkey $ dangle5 trnr- , printBlock "dangle3" 5 pb2lkey $ dangle3 trnr- , printBlock "int11" 5 ppbb2lkey $ iloop1x1 trnr- , printBlock "int21" 5 ppbbb2lkey $ iloop1x2 trnr- , printBlock22 "int22" 4 ppbbbb2lkey $ iloop2x2 trnr- , printLinear "hairpin" 10 $ hairpinL trnr- , printLinear "bulge" 10 $ bulgeL trnr- , printLinear "interior" 10 $ iloopL trnr- ]- -- enthalpy terms- [ printBlockH "stack" 7 pp2lkey $ stack trnrH- , printBlockH "mismatch_hairpin" 5 pbb2lkey $ hairpinMM trnrH- , printBlockH "mismatch_interior" 5 pbb2lkey $ iloopMM trnrH- , printBlockH "mismatch_interior_1n" 5 pbb2lkey $ iloop1xnMM trnrH- , printBlockH "mismatch_interior_23" 5 pbb2lkey $ iloop2x3MM trnrH- , printBlockH "mismatch_multi" 5 pbb2lkey $ multiMM trnrH- , printBlockH "mismatch_exterior" 5 pbb2lkey $ extMM trnrH- , printBlockH "dangle5" 5 pb2lkey $ dangle5 trnrH- , printBlockH "dangle3" 5 pb2lkey $ dangle3 trnrH- , printBlockH "int11" 5 ppbb2lkey $ iloop1x1 trnrH- , printBlockH "int21" 5 ppbbb2lkey $ iloop1x2 trnrH- , printBlock22H "int22" 4 ppbbbb2lkey $ iloop2x2 trnrH- , printLinearH "hairpin" 10 $ hairpinL trnrH- , printLinearH "bulge" 10 $ bulgeL trnrH- , printLinearH "interior" 10 $ iloopL trnrH- ]------ * Helper functions---- | Show the key of the line, minus the changing last key--showKey :: [(LKey,Int)] -> String-showKey xs =- " /* " ++- (concat $ intersperse "," $ init $ (map show ps) ++ (map show ns)) ++- " */"- where- (ps,ns) = fst $ head xs---- | Transform from tuple-based keys to a pair of list-based keys.--type LKey = ([ViennaPair],[Nucleotide])--pb2lkey (p1,b1) = ([p1],[b1])-pbb2lkey (p1,b1,b2) = ([p1],[b1,b2])-pp2lkey (k1,k2) = ([k1,k2],[])-ppbb2lkey (p1,p2,b1,b2) = ([p1,p2],[b1,b2])-ppbbb2lkey (p1,p2,b1,b2,b3) = ([p1,p2],[b1,b2,b3])-ppbbbb2lkey (p1,p2,b1,b2,b3,b4) = ([p1,p2],[b1,b2,b3,b4])---- | Print a block.--printBlock = printBlockG noNP where- noNP ((ps,ns),v) = not $ any (==vpNP) ps--printBlockH s = printBlock (s ++ "_enthalpies")--printBlock22 = printBlockG noNSNPE where- noNSNPE ((ps,ns),v) = not $ any (==vpNP) ps || any (==vpNS) ps || any (==nucE) ns--printBlock22H s = printBlock22 (s ++ "_enthalpies")--printBlockG fltr s k tolkey xs' =- let- xs = filter fltr $ map (first tolkey) $ assocs xs'- in- printf "# %s\n" s ++- (concatMap printLine $ splitEvery k xs) ++- "\n"--printLine xs =- concatMap printVal xs ++ " " ++ showKey xs ++- printf "\n"--printVal (k,v)- | v > eMax = printf " INF"- | otherwise = printf "%6d" v---- | A linear block is more boring--printLinear s k xs' = let xs = assocs xs' in- printf "# %s\n" s ++- (concatMap (\ys -> concatMap printVal ys ++ "\n") $ splitEvery k xs) ++- "\n"--printHairpinAssocs l trnr trnrH = res where- res = concat $ zipWith (\(k,v) vH -> printf "%s %7d %7d\n" (concatMap show k) v vH) xs ys- xs = filter ((==l).length.fst) $ M.assocs $ hairpinLookup trnr- ys = map snd $ filter ((==l).length.fst) $ M.assocs $ hairpinLookup trnrH--printLinearH s = printLinear (s ++ "_enthalpies")
− Biobase/Vienna/Import/Turner.hs
@@ -1,71 +0,0 @@-{-# LANGUAGE RecordWildCards #-}---- | Import data from a Turner table structure. Those can be imported using the--- Turner.Import module.--module Biobase.Vienna.Import.Turner- ( fromTurner- ) where--import Control.Arrow-import Data.Tuple.All-import qualified Data.Map as M--import Biobase.Turner.Tables-import Biobase.Turner-import Data.PrimitiveArray-import Biobase.Constants-import Biobase.RNA--import Biobase.Vienna--- | Convert from Turner keys to Vienna keys and all values from Double to Int--fromTurner :: TurnerTables -> ViennaIntTables-fromTurner Turner2004{..} = Turner2004- { stack = convert pp stack- , dangle3 = convert pb dangle3- , dangle5 = convert pb dangle5- , hairpinL = amap f2i hairpinL- , hairpinMM = convert pbb hairpinMM- , hairpinLookup = M.map f2i hairpinLookup- , bulgeL = amap f2i bulgeL- , iloop1x1 = convert uu iloop1x1- , iloop1x2 = convert uu iloop1x2- , iloop2x2 = convert uu iloop2x2- , iloopMM = convert pbb iloopMM- , iloop2x3MM = convert pbb iloop2x3MM- , iloop1xnMM = convert pbb iloop1xnMM- , iloopL = amap f2i iloopL- , multiMM = convert pbb multiMM- , ninio = f2i ninio- , maxNinio = f2i maxNinio- , multiOffset = f2i multiOffset- , multiNuc = f2i multiNuc- , multiHelix = f2i multiHelix- , extMM = convert pbb extMM- , largeLoop = largeLoop * 100 -- scale to decacals- , termAU = f2i termAU- , intermolecularInit = f2i intermolecularInit- }------ * Helper functions.---- | Vienna values are Int's that have 2-digit precision.--f2i :: Double -> Int-f2i d = round $ d * 100----- | Deep breath ;-)--pp = both tuple2Vienna-pb = first tuple2Vienna-pbb t = upd1 (tuple2Vienna $ sel1 t) t-uu t = upd2 (tuple2Vienna $ sel2 t) $ upd1 (tuple2Vienna $ sel1 t) t-both f = first f . second f---- | Do the conversion, both on keys and values.--convert fk = fromAssocs minBound maxBound eInf . map (first fk . second f2i) . assocs
− Biobase/Vienna/Import/ViennaPar.hs
@@ -1,123 +0,0 @@-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RecordWildCards #-}--module Biobase.Vienna.Import.ViennaPar- ( importPar- ) where--import Text.Parsec hiding ((<|>), many, optional)-import Text.Parsec.String-import Text.Parsec.Char-import Text.Parsec.Combinator hiding (optional)-import Control.Applicative-import Data.List-import qualified Data.Map as M--import Text.Parsec.Numbers-import Biobase.Constants-import Biobase.RNA-import Biobase.Turner.Tables-import Data.PrimitiveArray--import Biobase.Vienna------ | Imports Vienna tables from a given string.--importPar :: String -> (ViennaIntTables,ViennaIntTables)-importPar s- | Right _ <- p = foldr updateTables (trnr,trnrH) bs- | Left err <- p = error $ show err- where- p = parse blocks "(stdin)" s- Right bs = p- (bgs,bhs) = partition (not . isHblock) bs- trnr = foldr updateTable emptyTables bgs- trnrH = foldr updateTable emptyTables bhs---- | Apply all parsed blocks to a Turner2004 structure.--updateTable :: Block -> ViennaIntTables -> ViennaIntTables-updateTable Block{..} trnr -- @Turner2004{..}- | bhdr =? "stack" = trnr{stack = fromAssocs minBound maxBound z $ zip pp ints}- | bhdr =? "dangle3" = trnr{dangle3 = fromAssocs minBound maxBound z $ zip pb ints}- | bhdr =? "dangle5" = trnr{dangle5 = fromAssocs minBound maxBound z $ zip pb ints}- | bhdr =? "hairpin" = trnr{hairpinL = fromList 0 30 ints}- | bhdr =? "mismatch_hairpin" = trnr{hairpinMM = fromAssocs minBound maxBound z $ zip pbb ints}- | bhdr =? "bulge" = trnr{bulgeL = fromList 0 30 ints}- | bhdr =? "int11" = trnr{iloop1x1 = fromAssocs minBound maxBound z $ zip ppbb ints}- | bhdr =? "int21" = trnr{iloop1x2 = fromAssocs minBound maxBound z $ zip ppbbb ints}- | bhdr =? "int22" = trnr{iloop2x2 = fromAssocs minBound maxBound z $ zip ppbbbb ints}- | bhdr =? "mismatch_interior" = trnr{iloopMM = fromAssocs minBound maxBound z $ zip pbb ints}- | bhdr =? "mismatch_interior_23" = trnr{iloop2x3MM = fromAssocs minBound maxBound z $ zip pbb ints}- | bhdr =? "mismatch_interior_1n" = trnr{iloop1xnMM = fromAssocs minBound maxBound z $ zip pbb ints}- | bhdr =? "interior" = trnr{iloopL = fromList 0 30 ints}- | bhdr =? "mismatch_multi" = trnr{multiMM = fromAssocs minBound maxBound z $ zip pbb ints}- | bhdr =? "mismatch_exterior" = trnr{extMM = fromAssocs minBound maxBound z $ zip pbb ints}- | otherwise = trnr -- unknown block!-updateTable ABlock{..} trnr- | otherwise = trnr -- CORRECT!---- | update with info where no separation between G/H was done.--updateTables Block{..} (trnr,trnrH)- | bhdr =? "ML_params"- = ( trnr {multiNuc = ints!!0, multiOffset = ints!!2, multiHelix = ints!!4}- , trnrH{multiNuc = ints!!1, multiOffset = ints!!3, multiHelix = ints!!5}- )- | bhdr =? "NINIO"- = ( trnr {ninio = ints!!0, maxNinio = ints!!2}- , trnrH {ninio = ints!!1}- )- | bhdr =? "Misc"- = ( trnr {intermolecularInit = ints!!0, termAU = ints!!2}- , trnrH {intermolecularInit = ints!!1, termAU = ints!!3}- )- | otherwise = (trnr,trnrH)-updateTables ABlock{..} (trnr,trnrH)- | bhdr =? "Triloops" || bhdr =? "Tetraloops" || bhdr =? "Hexaloops"- = ( trnr {hairpinLookup = hairpinLookup trnr `M.union` (M.fromList $ map (\(k,v,w) -> (s2ns k,v)) ascs)}- , trnrH {hairpinLookup = hairpinLookup trnrH `M.union` (M.fromList $ map (\(k,v,w) -> (s2ns k,w)) ascs)}- )- | otherwise = (trnr,trnrH)--pp = [(x,y) | x<-cgnsP,y<-cgnsP]-pb = [(x,y) | x<-cgnsP,y<-eacgu]-pbb = [(x,y,z) | x<-cgnsP,y<-eacgu,z<-eacgu]-ppbb = [(p1,p2,b1,b2) | p1<-cgnsP,p2<-cgnsP,b1<-eacgu,b2<-eacgu]-ppbbb = [(p1,p2,b1,b2,b3) | p1<-cgnsP,p2<-cgnsP,b1<-eacgu,b2<-eacgu,b3<-eacgu]-ppbbbb = [(p1,p2,b1,b2,b3,b4) | p1<-cguaP,p2<-cguaP,b1<-acgu,b2<-acgu,b3<-acgu,b4<-acgu]-z = eInf--- xs is the block header name, ys the constant string-xs =? ys = xs == ys || xs == ys++"_enthalpies" -- and $ zipWith (==) xs ys-s2ns = map charToNucleotide---- * Simple parser for the vienna 2.0 format.--isHblock :: Block -> Bool-isHblock b = "enthalpies" `elem` (tails $ bhdr b)--data Block- = Block {bhdr :: String, ints :: [Int]}- | ABlock {bhdr :: String, ascs :: [(String,Int,Int)]}- deriving (Show)--blocks :: GenParser Char st [Block]-blocks = vrna2 *> spaces *> (try assocBlock <|> try block) `sepEndBy1` spaces <* string "#END" <* spaces <* eof--vrna2 = string "## RNAfold parameter file v2.0"--block :: GenParser Char st Block-block = Block <$> header <* spaces <*> num `sepEndBy1` (try comment <|> spaces) where- num = ((eInf <$ string "INF") <|> parseIntegral)--assocBlock :: GenParser Char st Block-assocBlock = ABlock <$> header <* spaces <*> asc `sepEndBy1` spaces where- asc = (,,) <$> (many1 $ oneOf "ACGU") <* spaces <*> parseIntegral <* spaces <*> parseIntegral--header :: GenParser Char st String-header = char '#' *> space *> (alphaNum <|> char '_') `manyTill` newline--comment :: GenParser Char st ()-comment = const () <$ spaces <*> between (string "/*") (string "*/") (many $ noneOf "/*") <* spaces
− Biobase/Vienna/Modification/NonStandard.hs
@@ -1,121 +0,0 @@---- | This module provides facilities to modify values in the tables and return--- the modified tables. The main reason for the modules' existence are the 'E'--- nucleotides and 'NS' base pairs used by the ViennaRNA package to denote--- unknown or missing nucleotides. For each table type, we have a small--- function.--module Biobase.Vienna.Modification.NonStandard- ( nonStandardMax- ) where--import Biobase.RNA-import Biobase.Vienna-import Biobase.Turner.Tables-import Data.Ix.Tuple-import Biobase.Constants-import Biobase.Types.Energy--import Data.PrimitiveArray----- | Each table-changing operation makes the promise that all individual--- changes in a batch are independent of the changes in the same batch--changeTable f tbl = fromAssocs l u z . map (f tbl) $ assocs tbl where- (l,u) = bounds tbl- z = Energy eInf------ |* Replace each occurrance of a value with a strange key according to this--- rule. The rule is to take the maximum over all sane keys in the--- neighborhood. Yes, this takes long...--fPPBBBBmax tbl (k@(p1,p2,b1,b2,b3,b4),v)- | p1==vpNP || p2==vpNP = (k,v) -- don't do anything- | otherwise = (k,maximum'- [ tbl ! (p1n,p2n,b1n,b2n,b3n,b4n)- | p1n <- genKeyP p1- , p2n <- genKeyP p2- , b1n <- genKeyB b1- , b2n <- genKeyB b2- , b3n <- genKeyB b3- , b4n <- genKeyB b4- ])--fPPBBBmax tbl (k@(p1,p2,b1,b2,b3),v)- | p1==vpNP || p2==vpNP = (k,v)- | otherwise = (k,maximum'- [ tbl ! (p1n,p2n,b1n,b2n,b3n)- | p1n <- genKeyP p1- , p2n <- genKeyP p2- , b1n <- genKeyB b1- , b2n <- genKeyB b2- , b3n <- genKeyB b3- ])--fPPBBmax tbl (k@(p1,p2,b1,b2),v)- | p1==vpNP || p2==vpNP = (k,v)- | otherwise = (k,maximum'- [ tbl ! (p1n,p2n,b1n,b2n)- | p1n <- genKeyP p1- , p2n <- genKeyP p2- , b1n <- genKeyB b1- , b2n <- genKeyB b2- ])--fPPmax tbl (k@(p1,p2),v)- | p1==vpNP || p2==vpNP = (k,v)- | otherwise = (k,maximum'- [ tbl ! (p1n,p2n)- | p1n <- genKeyP p1- , p2n <- genKeyP p2- ])--fPBBmax tbl (k@(p1,b1,b2),v)- | p1==vpNP = (k,v)- | otherwise = (k,maximum'- [ tbl ! (p1n,b1n,b2n)- | p1n <- genKeyP p1- , b1n <- genKeyB b1- , b2n <- genKeyB b2- ])--fPBmax tbl (k@(p1,b1),v)- | p1==vpNP = (k,v)- | otherwise = (k,maximum'- [ tbl ! (p1n,b1n)- | p1n <- genKeyP p1- , b1n <- genKeyB b1- ])--maximum' = Energy . maximum . map unEnergy----- * Generate keys. If the key is of the non-standard kind, then we go fishing,--- otherwise we keep the key itself.--genKeyP k = if k==vpNS then cguaP else [k]-genKeyB k = if k==nucE then acgu else [k]------ | The max operation applied to all relevant tables. (This serves as a--- pointer, which tables to manipulate).--nonStandardMax :: ViennaEnergyTables -> ViennaEnergyTables-nonStandardMax tbl = tbl- { iloop1x1 = changeTable fPPBBmax $ iloop1x1 tbl- , iloop1x2 = changeTable fPPBBBmax $ iloop1x2 tbl- , iloop2x2 = changeTable fPPBBBBmax $ iloop2x2 tbl- , hairpinMM = changeTable fPBBmax $ hairpinMM tbl- , iloopMM = changeTable fPBBmax $ iloopMM tbl- , iloop1xnMM = changeTable fPBBmax $ iloop1xnMM tbl- , iloop2x3MM = changeTable fPBBmax $ iloop2x3MM tbl- , multiMM = changeTable fPBBmax $ multiMM tbl- , extMM = changeTable fPBBmax $ extMM tbl- , dangle3 = changeTable fPBmax $ dangle3 tbl- , dangle5 = changeTable fPBmax $ dangle5 tbl- , stack = changeTable fPPmax $ stack tbl- }
− Biobase/Vienna/Modification/Partition.hs
@@ -1,51 +0,0 @@---- | Small module for converting Vienna energy tables to partition function--- value tables.------ Temperature scaling should happen on the level of energy tables, followed by--- conversion here.------ TODO after the switch to the Energy type, change too, the partitionTables--- generation--module Biobase.Vienna.Modification.Partition- ( partitionTables- ) where--import Biobase.Types.Partition-import Biobase.Types.Energy-import Biobase.Turner.Tables-import Biobase.Vienna-import Biobase.Constants----- Testing--{--import Biobase.Vienna.Default-import Data.PrimitiveArray-import Debug.Trace.Tools-import Biobase.RNA-import Biobase.Types.Ring--(g,h) = turner2004GH---- x = toList $ stack $ partitionTables 37 g-x = {- toList $ -} (stack $ partitionTables 37 g) ! (vpGC,vpGC)--}---- | Create partition tables out of normal energy tables. Note that these--- values are not normalized. An additional term 1/Z(1/kt) would be required--- which is missing until we are done calculating the partition function.------ All energy contributions are rescaled from dekacals back to kcal/mol.------ We explicitly set all probabilities =0 where the energy is >= eMax.--partitionTables :: Temperature -> ViennaEnergyTables -> ViennaPartitionTables-partitionTables tempe trnr = dmap f trnr where- kt = (tempe + kelvinC0) * gasconst- -- convert energy into probability; encapsulate as a (logFloat) partition- f (Energy e') = {- traceVal (show (e',e,p)) -} p where- e = fromIntegral e' / 100- p = if e' >= eMax then Partition 0 else Partition . exp $ -e / kt -- can NOT use mkPartition as these values are NOT NORMALIZED
− Biobase/Vienna/Modification/Temperature.hs
@@ -1,34 +0,0 @@---- | Given entropy and enthalpy sets, allow modification of the folding--- temperature (from the default 37 Celsius)--module Biobase.Vienna.Modification.Temperature- ( adjustTemperature- ) where--import Biobase.Vienna-import Biobase.Turner.Tables-import Biobase.Constants------ temperature scaling is a generalized zip: let g and h be a scalar, t the--- temperature. Then: g_t = h - (h-g)*((t+k_0)/t_m). Where k_0 = 273.15 (Kelvin--- of 37 Celsius) and t_m = 37+k_0------ TODO abstract over table type?------ TODO this does not take into account that dangles are supposed to _always_--- be beneficial. We should therefor transform the energies and then apply 'min--- 0' onto all dangle types.------ TODO use EnergyTables (Int is just for im-/export)--adjustTemperature :: ViennaIntTables -> ViennaIntTables -> Temperature -> ViennaIntTables-adjustTemperature trnrG trnrH cels = dZipWith f trnrG trnrH where- f vG vH =- let g = fromIntegral vG- h = fromIntegral vH- k_0 = kelvinC0- t_m = 37 + k_0- in round $ h - (h-g) * ((cels+k_0)/t_m)
templates/cheader view
@@ -2,15 +2,14 @@ /* Automatically generated using the TurnerParser- TurnerParser (c) 2008,2009,2010+ TurnerParser (c) 2008,2009,2010,2011 Christian Hoener zu Siederdissen, TBI Vienna choener (at) tbi.univie.ac.at - The library enabling this can be found at:- http://hackage.haskell.org/package/BiobaseVienna- the program can be found at:- (sorry, not yet)- install using cabal: cabal install (sorry, not yet)+ Important links:+ http://hackage.haskell.org/package/Biobase+ http://www.tbi.univie.ac.at/~choener/+ http://www.biohaskell.org/ */ /*