ClustalParser 1.2.3 → 1.3.0
raw patch · 10 files changed
+525/−488 lines, 10 filesdep ~parsecPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: parsec
API changes (from Hackage documentation)
- Bio.ClustalParser: ClustalAlignment :: [ClustalAlignmentEntry] -> Text -> ClustalAlignment
- Bio.ClustalParser: ClustalAlignmentEntry :: Text -> Text -> ClustalAlignmentEntry
- Bio.ClustalParser: ClustalAlignmentEntrySlice :: String -> String -> Int -> ClustalAlignmentEntrySlice
- Bio.ClustalParser: ClustalAlignmentSlice :: [ClustalAlignmentEntrySlice] -> String -> ClustalAlignmentSlice
- Bio.ClustalParser: ClustalSummary :: Text -> Text -> [SequenceParameters] -> [PairwiseAlignmentSummary] -> Text -> Int -> [GroupSummary] -> Int -> Text -> ClustalSummary
- Bio.ClustalParser: GroupSummary :: Int -> Maybe Int -> Maybe Int -> GroupSummary
- Bio.ClustalParser: PairwiseAlignmentSummary :: Int -> Int -> Int -> PairwiseAlignmentSummary
- Bio.ClustalParser: SequenceParameters :: Int -> Text -> Int -> SequenceParameters
- Bio.ClustalParser: StructuralClustalAlignment :: [ClustalAlignmentEntry] -> Text -> Double -> StructuralClustalAlignment
- Bio.ClustalParser: StructuralClustalAlignmentEntrySlice :: String -> String -> StructuralClustalAlignmentEntrySlice
- Bio.ClustalParser: [alignmentEntries] :: ClustalAlignment -> [ClustalAlignmentEntry]
- Bio.ClustalParser: [alignmentFileName] :: ClustalSummary -> Text
- Bio.ClustalParser: [alignmentGroupIndex] :: GroupSummary -> Int
- Bio.ClustalParser: [alignmentScore] :: ClustalSummary -> Int
- Bio.ClustalParser: [clustalw2version] :: ClustalSummary -> Text
- Bio.ClustalParser: [conservationTrackSlice] :: ClustalAlignmentSlice -> String
- Bio.ClustalParser: [conservationTrack] :: ClustalAlignment -> Text
- Bio.ClustalParser: [energy] :: StructuralClustalAlignment -> Double
- Bio.ClustalParser: [entryAlignedSequence] :: ClustalAlignmentEntry -> Text
- Bio.ClustalParser: [entryAlignedSliceSequence] :: ClustalAlignmentEntrySlice -> String
- Bio.ClustalParser: [entrySequenceIdentifier] :: ClustalAlignmentEntry -> Text
- Bio.ClustalParser: [entrySequenceSliceIdentifier] :: ClustalAlignmentEntrySlice -> String
- Bio.ClustalParser: [entrySlices] :: ClustalAlignmentSlice -> [ClustalAlignmentEntrySlice]
- Bio.ClustalParser: [firstSequenceIndex] :: PairwiseAlignmentSummary -> Int
- Bio.ClustalParser: [groupNumber] :: ClustalSummary -> Int
- Bio.ClustalParser: [groupScore] :: GroupSummary -> Maybe Int
- Bio.ClustalParser: [groupSummaries] :: ClustalSummary -> [GroupSummary]
- Bio.ClustalParser: [guideTreeFileName] :: ClustalSummary -> Text
- Bio.ClustalParser: [inputSequenceIdentifier] :: SequenceParameters -> Text
- Bio.ClustalParser: [inputSequenceIndex] :: SequenceParameters -> Int
- Bio.ClustalParser: [inputSequenceLength] :: SequenceParameters -> Int
- Bio.ClustalParser: [numberOfAlignedSequences] :: GroupSummary -> Maybe Int
- Bio.ClustalParser: [pairwiseAlignmentScore] :: PairwiseAlignmentSummary -> Int
- Bio.ClustalParser: [pairwiseAlignmentSummaries] :: ClustalSummary -> [PairwiseAlignmentSummary]
- Bio.ClustalParser: [parametersOfInputSequences] :: ClustalSummary -> [SequenceParameters]
- Bio.ClustalParser: [secondSequenceIndex] :: PairwiseAlignmentSummary -> Int
- Bio.ClustalParser: [secondaryStructureTrack] :: StructuralClustalAlignment -> Text
- Bio.ClustalParser: [sequenceFormat] :: ClustalSummary -> Text
- Bio.ClustalParser: [spacerLength] :: ClustalAlignmentEntrySlice -> Int
- Bio.ClustalParser: [structuralAlignmentEntries] :: StructuralClustalAlignment -> [ClustalAlignmentEntry]
- Bio.ClustalParser: [structuralEntryAlignedSliceSequence] :: StructuralClustalAlignmentEntrySlice -> String
- Bio.ClustalParser: [structuralEntrySequenceSliceIdentifier] :: StructuralClustalAlignmentEntrySlice -> String
- Bio.ClustalParser: data ClustalAlignment
- Bio.ClustalParser: data ClustalAlignmentEntry
- Bio.ClustalParser: data ClustalAlignmentEntrySlice
- Bio.ClustalParser: data ClustalAlignmentSlice
- Bio.ClustalParser: data ClustalSummary
- Bio.ClustalParser: data GroupSummary
- Bio.ClustalParser: data PairwiseAlignmentSummary
- Bio.ClustalParser: data SequenceParameters
- Bio.ClustalParser: data StructuralClustalAlignment
- Bio.ClustalParser: data StructuralClustalAlignmentEntrySlice
- Bio.ClustalParser: parseClustalAlignment :: String -> Either ParseError ClustalAlignment
- Bio.ClustalParser: parseClustalSummary :: String -> Either ParseError ClustalSummary
- Bio.ClustalParser: parseStructuralClustalAlignment :: String -> Either ParseError StructuralClustalAlignment
- Bio.ClustalParser: readClustalAlignment :: String -> IO (Either ParseError ClustalAlignment)
- Bio.ClustalParser: readClustalSummary :: String -> IO (Either ParseError ClustalSummary)
- Bio.ClustalParser: readStructuralClustalAlignment :: String -> IO (Either ParseError StructuralClustalAlignment)
- Bio.ClustalParser: showAlignment :: Int -> Int -> Int -> [ClustalAlignmentEntry] -> Text -> String
- Bio.ClustalParser: showAlignmentBlock :: Int -> Int -> [ClustalAlignmentEntry] -> Text -> String
- Bio.ClustalParser: showAlignmentLine :: Int -> Int -> ClustalAlignmentEntry -> String
+ Biobase.Clustal.Import: parseClustalAlignment :: String -> Either ParseError ClustalAlignment
+ Biobase.Clustal.Import: parseClustalSummary :: String -> Either ParseError ClustalSummary
+ Biobase.Clustal.Import: parseStructuralClustalAlignment :: String -> Either ParseError StructuralClustalAlignment
+ Biobase.Clustal.Import: readClustalAlignment :: String -> IO (Either ParseError ClustalAlignment)
+ Biobase.Clustal.Import: readClustalSummary :: String -> IO (Either ParseError ClustalSummary)
+ Biobase.Clustal.Import: readStructuralClustalAlignment :: String -> IO (Either ParseError StructuralClustalAlignment)
+ Biobase.Clustal.Types: ClustalAlignment :: [ClustalAlignmentEntry] -> Text -> ClustalAlignment
+ Biobase.Clustal.Types: ClustalAlignmentEntry :: Text -> Text -> ClustalAlignmentEntry
+ Biobase.Clustal.Types: ClustalAlignmentEntrySlice :: String -> String -> Int -> ClustalAlignmentEntrySlice
+ Biobase.Clustal.Types: ClustalAlignmentSlice :: [ClustalAlignmentEntrySlice] -> String -> ClustalAlignmentSlice
+ Biobase.Clustal.Types: ClustalSummary :: Text -> Text -> [SequenceParameters] -> [PairwiseAlignmentSummary] -> Text -> Int -> [GroupSummary] -> Int -> Text -> ClustalSummary
+ Biobase.Clustal.Types: GroupSummary :: Int -> Maybe Int -> Maybe Int -> GroupSummary
+ Biobase.Clustal.Types: PairwiseAlignmentSummary :: Int -> Int -> Int -> PairwiseAlignmentSummary
+ Biobase.Clustal.Types: SequenceParameters :: Int -> Text -> Int -> SequenceParameters
+ Biobase.Clustal.Types: StructuralClustalAlignment :: [ClustalAlignmentEntry] -> Text -> Double -> StructuralClustalAlignment
+ Biobase.Clustal.Types: StructuralClustalAlignmentEntrySlice :: String -> String -> StructuralClustalAlignmentEntrySlice
+ Biobase.Clustal.Types: [alignmentEntries] :: ClustalAlignment -> [ClustalAlignmentEntry]
+ Biobase.Clustal.Types: [alignmentFileName] :: ClustalSummary -> Text
+ Biobase.Clustal.Types: [alignmentGroupIndex] :: GroupSummary -> Int
+ Biobase.Clustal.Types: [alignmentScore] :: ClustalSummary -> Int
+ Biobase.Clustal.Types: [clustalw2version] :: ClustalSummary -> Text
+ Biobase.Clustal.Types: [conservationTrackSlice] :: ClustalAlignmentSlice -> String
+ Biobase.Clustal.Types: [conservationTrack] :: ClustalAlignment -> Text
+ Biobase.Clustal.Types: [energy] :: StructuralClustalAlignment -> Double
+ Biobase.Clustal.Types: [entryAlignedSequence] :: ClustalAlignmentEntry -> Text
+ Biobase.Clustal.Types: [entryAlignedSliceSequence] :: ClustalAlignmentEntrySlice -> String
+ Biobase.Clustal.Types: [entrySequenceIdentifier] :: ClustalAlignmentEntry -> Text
+ Biobase.Clustal.Types: [entrySequenceSliceIdentifier] :: ClustalAlignmentEntrySlice -> String
+ Biobase.Clustal.Types: [entrySlices] :: ClustalAlignmentSlice -> [ClustalAlignmentEntrySlice]
+ Biobase.Clustal.Types: [firstSequenceIndex] :: PairwiseAlignmentSummary -> Int
+ Biobase.Clustal.Types: [groupNumber] :: ClustalSummary -> Int
+ Biobase.Clustal.Types: [groupScore] :: GroupSummary -> Maybe Int
+ Biobase.Clustal.Types: [groupSummaries] :: ClustalSummary -> [GroupSummary]
+ Biobase.Clustal.Types: [guideTreeFileName] :: ClustalSummary -> Text
+ Biobase.Clustal.Types: [inputSequenceIdentifier] :: SequenceParameters -> Text
+ Biobase.Clustal.Types: [inputSequenceIndex] :: SequenceParameters -> Int
+ Biobase.Clustal.Types: [inputSequenceLength] :: SequenceParameters -> Int
+ Biobase.Clustal.Types: [numberOfAlignedSequences] :: GroupSummary -> Maybe Int
+ Biobase.Clustal.Types: [pairwiseAlignmentScore] :: PairwiseAlignmentSummary -> Int
+ Biobase.Clustal.Types: [pairwiseAlignmentSummaries] :: ClustalSummary -> [PairwiseAlignmentSummary]
+ Biobase.Clustal.Types: [parametersOfInputSequences] :: ClustalSummary -> [SequenceParameters]
+ Biobase.Clustal.Types: [secondSequenceIndex] :: PairwiseAlignmentSummary -> Int
+ Biobase.Clustal.Types: [secondaryStructureTrack] :: StructuralClustalAlignment -> Text
+ Biobase.Clustal.Types: [sequenceFormat] :: ClustalSummary -> Text
+ Biobase.Clustal.Types: [spacerLength] :: ClustalAlignmentEntrySlice -> Int
+ Biobase.Clustal.Types: [structuralAlignmentEntries] :: StructuralClustalAlignment -> [ClustalAlignmentEntry]
+ Biobase.Clustal.Types: [structuralEntryAlignedSliceSequence] :: StructuralClustalAlignmentEntrySlice -> String
+ Biobase.Clustal.Types: [structuralEntrySequenceSliceIdentifier] :: StructuralClustalAlignmentEntrySlice -> String
+ Biobase.Clustal.Types: data ClustalAlignment
+ Biobase.Clustal.Types: data ClustalAlignmentEntry
+ Biobase.Clustal.Types: data ClustalAlignmentEntrySlice
+ Biobase.Clustal.Types: data ClustalAlignmentSlice
+ Biobase.Clustal.Types: data ClustalSummary
+ Biobase.Clustal.Types: data GroupSummary
+ Biobase.Clustal.Types: data PairwiseAlignmentSummary
+ Biobase.Clustal.Types: data SequenceParameters
+ Biobase.Clustal.Types: data StructuralClustalAlignment
+ Biobase.Clustal.Types: data StructuralClustalAlignmentEntrySlice
+ Biobase.Clustal.Types: instance GHC.Classes.Eq Biobase.Clustal.Types.ClustalAlignment
+ Biobase.Clustal.Types: instance GHC.Classes.Eq Biobase.Clustal.Types.ClustalAlignmentEntry
+ Biobase.Clustal.Types: instance GHC.Classes.Eq Biobase.Clustal.Types.ClustalAlignmentEntrySlice
+ Biobase.Clustal.Types: instance GHC.Classes.Eq Biobase.Clustal.Types.ClustalAlignmentSlice
+ Biobase.Clustal.Types: instance GHC.Classes.Eq Biobase.Clustal.Types.ClustalSummary
+ Biobase.Clustal.Types: instance GHC.Classes.Eq Biobase.Clustal.Types.GroupSummary
+ Biobase.Clustal.Types: instance GHC.Classes.Eq Biobase.Clustal.Types.PairwiseAlignmentSummary
+ Biobase.Clustal.Types: instance GHC.Classes.Eq Biobase.Clustal.Types.SequenceParameters
+ Biobase.Clustal.Types: instance GHC.Classes.Eq Biobase.Clustal.Types.StructuralClustalAlignment
+ Biobase.Clustal.Types: instance GHC.Classes.Eq Biobase.Clustal.Types.StructuralClustalAlignmentEntrySlice
+ Biobase.Clustal.Types: instance GHC.Show.Show Biobase.Clustal.Types.ClustalAlignment
+ Biobase.Clustal.Types: instance GHC.Show.Show Biobase.Clustal.Types.ClustalAlignmentEntry
+ Biobase.Clustal.Types: instance GHC.Show.Show Biobase.Clustal.Types.ClustalAlignmentEntrySlice
+ Biobase.Clustal.Types: instance GHC.Show.Show Biobase.Clustal.Types.ClustalAlignmentSlice
+ Biobase.Clustal.Types: instance GHC.Show.Show Biobase.Clustal.Types.ClustalSummary
+ Biobase.Clustal.Types: instance GHC.Show.Show Biobase.Clustal.Types.GroupSummary
+ Biobase.Clustal.Types: instance GHC.Show.Show Biobase.Clustal.Types.PairwiseAlignmentSummary
+ Biobase.Clustal.Types: instance GHC.Show.Show Biobase.Clustal.Types.SequenceParameters
+ Biobase.Clustal.Types: instance GHC.Show.Show Biobase.Clustal.Types.StructuralClustalAlignment
+ Biobase.Clustal.Types: instance GHC.Show.Show Biobase.Clustal.Types.StructuralClustalAlignmentEntrySlice
+ Biobase.Clustal.Types: showAlignment :: Int -> Int -> Int -> [ClustalAlignmentEntry] -> Text -> String
+ Biobase.Clustal.Types: showAlignmentBlock :: Int -> Int -> [ClustalAlignmentEntry] -> Text -> String
+ Biobase.Clustal.Types: showAlignmentLine :: Int -> Int -> ClustalAlignmentEntry -> String
Files
- Biobase/Clustal.hs +10/−0
- Biobase/Clustal/Import.hs +294/−0
- Biobase/Clustal/Types.hs +131/−0
- ChangeLog.md +57/−0
- ClustalParser.cabal +26/−23
- ClustalParserTest.hs +3/−4
- changelog +0/−30
- src/Bio/ClustalData.hs +0/−133
- src/Bio/ClustalParser.hs +0/−294
- test-suite/ClustalParserSpec.hs +4/−4
+ Biobase/Clustal.hs view
@@ -0,0 +1,10 @@+-- | Types and functions for Clustal+--++module Biobase.Clustal+ ( module Biobase.Clustal.Types+ , module Biobase.Clustal.Import+ ) where++import Biobase.Clustal.Import+import Biobase.Clustal.Types
+ Biobase/Clustal/Import.hs view
@@ -0,0 +1,294 @@+-- | Parse Clustal output+-- For more information on Clustal tools consult: <http://www.clustal.org/>+module Biobase.Clustal.Import (+ parseClustalAlignment,+ readClustalAlignment,+ parseStructuralClustalAlignment,+ readStructuralClustalAlignment,+ parseClustalSummary,+ readClustalSummary,+ module Biobase.Clustal.Types+ ) where++import Biobase.Clustal.Types+import Text.ParserCombinators.Parsec+import Control.Monad+import Data.List+import qualified Data.Text as T+readDouble :: String -> Double+readDouble = read++readInt :: String -> Int+readInt = read++-- | Parse the input as ClustalSummary datatype+genParserClustalSummary :: GenParser Char st ClustalSummary+genParserClustalSummary = do+ newline+ newline+ newline+ space+ string "CLUSTAL "+ version <- many1 (noneOf " ")+ many1 (noneOf "\n")+ newline+ newline+ newline+ string "Sequence format is "+ sequenceFormat' <- many1 (noneOf "\n")+ newline+ sequenceParametersList <- many1 (try genParserSequenceParameters)+ string "Start of Pairwise alignments"+ newline+ string "Aligning..."+ newline+ newline+ pairwiseAlignmentSummaryList <- many1 genParserPairwiseAlignmentSummary+ string "Guide tree file created: ["+ guideTreeFileName' <- many1 (noneOf "]")+ char ']'+ newline+ newline+ string "There are "+ numberOfGroups <- many1 digit+ string " groups"+ newline+ string "Start of Multiple Alignment"+ newline+ newline+ string "Aligning..."+ newline+ groupSummaryList <- many1 genParserGroupSummary+ string "Alignment Score "+ alignmentScore' <- many1 digit+ newline+ newline+ string "CLUSTAL-Alignment file created ["+ alignmentFileName' <- many1 (noneOf "]")+ char ']'+ newline+ newline+ eof+ return $ ClustalSummary (T.pack version) (T.pack sequenceFormat') sequenceParametersList pairwiseAlignmentSummaryList (T.pack guideTreeFileName') (readInt numberOfGroups) groupSummaryList (readInt alignmentScore') (T.pack alignmentFileName')++genParserGroupSummary :: GenParser Char st GroupSummary+genParserGroupSummary = do+ string "Group "+ groupIndex <- many1 digit+ string ":"+ optional space+ optional (string "Sequences:")+ many1 space+ sequenceNumber <- optionMaybe (many1 digit)+ optional (many1 space)+ string "Score:" <|> string "Delayed"+ groupScore' <- optionMaybe (many1 digit)+ newline+ return $ GroupSummary (readInt groupIndex) (liftM readInt sequenceNumber) (liftM readInt groupScore')++genParserPairwiseAlignmentSummary :: GenParser Char st PairwiseAlignmentSummary+genParserPairwiseAlignmentSummary = do+ string "Sequences ("+ firstSeqIndex <- many1 digit+ string ":"+ secondSeqIndex <- many1 digit+ string ") Aligned. Score:"+ many1 space+ pairwiseScore <- many1 digit+ newline+ return $ PairwiseAlignmentSummary (readInt firstSeqIndex) (readInt secondSeqIndex) (readInt pairwiseScore)++genParserSequenceParameters :: GenParser Char st SequenceParameters+genParserSequenceParameters = do+ string "Sequence "+ sequenceIndexParam <- many1 digit+ string ": "+ sequenceIdentifierParam <- many1 (noneOf " ")+ spaces+ sequenceLengthParam <- many1 digit+ space+ string "bp"+ newline+ return $ SequenceParameters (readInt sequenceIndexParam) (T.pack sequenceIdentifierParam) (readInt sequenceLengthParam)++-- | Parse the input as ClustalAlignment datatype+genParserClustalAlignment :: GenParser Char st ClustalAlignment+genParserClustalAlignment = do+ string "CLUSTAL"+ many1 (noneOf "\n")+ many1 (try newline)+ alignmentSlices <- many1 (try genParserClustalAlignmentSlice)+ optional newline+ eof+ return (mergealignmentSlices alignmentSlices)++mergealignmentSlices :: [ClustalAlignmentSlice] -> ClustalAlignment+mergealignmentSlices slices = alignment+ where entrySlicesList = concatMap entrySlices slices -- list of lists of entry slices+ sequenceIdentifiers = nub (map entrySequenceSliceIdentifier entrySlicesList)+ mergedAlignmentEntries = map (constructAlignmentEntries entrySlicesList) sequenceIdentifiers+ mergedConservationTrack = concatMap conservationTrackSlice slices+ alignment = ClustalAlignment mergedAlignmentEntries (T.pack mergedConservationTrack)++constructAlignmentEntries :: [ClustalAlignmentEntrySlice] -> String -> ClustalAlignmentEntry+constructAlignmentEntries slices entryIdentifier= entry+ where currentSlices = filter (\a -> entrySequenceSliceIdentifier a == entryIdentifier) slices+ entrySequence = concatMap entryAlignedSliceSequence currentSlices+ entry = ClustalAlignmentEntry (T.pack entryIdentifier) (T.pack entrySequence)++genParserClustalAlignmentSlice :: GenParser Char st ClustalAlignmentSlice+genParserClustalAlignmentSlice = do+ entrySlices' <- many1 genParserClustalEntrySlice+ --extract length of identifier and spacer to determine offset of conservation track+ let offsetLenght = length (entrySequenceSliceIdentifier (head entrySlices')) + spacerLength (head entrySlices')+ conservationTrackSliceChoice <- choice [(lookAhead (string "\n")), (try (genParserConservationTrackSlice offsetLenght))]+ --spacerAndConservationTrackSlice <- many1 (noneOf "\n")+ --let conservationTrackSlice' = drop offsetLenght spacerAndConservationTrackSlice+ --newline+ let conservationTrackSlice' = if (conservationTrackSliceChoice == "\n") then "" else conservationTrackSliceChoice+ optional newline+ return $ ClustalAlignmentSlice entrySlices' conservationTrackSlice'++genParserConservationTrackSlice :: Int -> GenParser Char st String+genParserConservationTrackSlice offsetLenght = do+ spacerAndConservationTrackSlice <- many1 (noneOf "\n")+ let conservationTrackSlice' = drop offsetLenght spacerAndConservationTrackSlice+ newline+ return $ conservationTrackSlice'++genParserClustalEntrySlice :: GenParser Char st ClustalAlignmentEntrySlice+genParserClustalEntrySlice = do+ sliceIdentifier <- many1 (noneOf " \n")+ spacer <- many1 (char ' ')+ sliceSequence <- parseNucleotideAlignmentEntry+ newline+ return $ ClustalAlignmentEntrySlice sliceIdentifier sliceSequence (length spacer)++--Structural Clustal Parser functions++-- | Parse the input as ClustalAlignment datatype as used in mlocarna+genParserStructuralClustalAlignment :: GenParser Char st StructuralClustalAlignment+genParserStructuralClustalAlignment = do+ genParseMlocarnaHeader+ alignmentSlices <- many1 (try genParserStructuralClustalAlignmentSlice)+ secondaryStructure <- genSecondaryStructure+ energy' <- genParseEnergy+ eof+ return (mergeStructuralAlignmentSlices (concat alignmentSlices) secondaryStructure energy')++genSecondaryStructure :: GenParser Char st String+genSecondaryStructure = do+ string "alifold"+ secondaryStructure <- many1 (try genSecondaryStructureSlice)+ return (concat secondaryStructure)++genSecondaryStructureSlice :: GenParser Char st String+genSecondaryStructureSlice = do+ many1 space+ secondaryStructureSlice <- many1 (try (oneOf ".()"))+ choice [try (string "\n"),try (string " ")]+ return secondaryStructureSlice++genParseEnergy :: GenParser Char st Double+genParseEnergy = do+ string "("+ many space+ energy' <- many1 (noneOf " ")+ optional space+ char ('=')+ many1 (noneOf "\n")+ newline+ return (readDouble energy')++genParseMlocarnaHeader :: GenParser Char st String+genParseMlocarnaHeader = do+ string "mLocARNA"+ many1 (choice [alphaNum,oneOf "-: ()."])+ newline+ string "Copyright"+ many1 (choice [alphaNum,char ' '])+ newline+ newline+ string "Compute pair probs ..."+ newline+ optional (try (string "Compute pairwise alignments ... "))+ optional (try newline)+ string "Perform progressive alignment ..."+ many1 newline+ return ""++mergeStructuralAlignmentSlices :: [StructuralClustalAlignmentEntrySlice] -> String -> Double -> StructuralClustalAlignment+mergeStructuralAlignmentSlices slices secondaryStructure energy' = alignment+ where sequenceIdentifiers = nub (map structuralEntrySequenceSliceIdentifier slices)+ mergedAlignmentEntries = map (constructStructuralAlignmentEntries slices) sequenceIdentifiers+ alignment = StructuralClustalAlignment mergedAlignmentEntries (T.pack secondaryStructure) energy'++constructStructuralAlignmentEntries :: [StructuralClustalAlignmentEntrySlice] -> String -> ClustalAlignmentEntry+constructStructuralAlignmentEntries slices entryIdentifier= entry+ where currentSlices = filter (\a -> structuralEntrySequenceSliceIdentifier a == entryIdentifier) slices+ entrySequence = concatMap structuralEntryAlignedSliceSequence currentSlices+ entry = ClustalAlignmentEntry (T.pack entryIdentifier) (T.pack entrySequence)++genParserStructuralClustalAlignmentSlice :: GenParser Char st [StructuralClustalAlignmentEntrySlice]+genParserStructuralClustalAlignmentSlice = do+ entrySlices' <- many1 (try genParserStructuralClustalEntrySlice)+ optional newline+ return entrySlices'++genParserStructuralClustalEntrySlice :: GenParser Char st StructuralClustalAlignmentEntrySlice+genParserStructuralClustalEntrySlice = do+ sliceIdentifier <- many1 (noneOf " ")+ many1 (char ' ')+ sliceSequence <- parseNucleotideAlignmentEntry+ newline+ return $ StructuralClustalAlignmentEntrySlice (filter (/='\n') sliceIdentifier) sliceSequence++-- exported functions++-- | Parse Clustal alignment (.aln) from String+parseClustalAlignment :: String -> Either ParseError ClustalAlignment+parseClustalAlignment = parse genParserClustalAlignment "genParserClustalAlignment"++-- | Parse Clustal alignment (.aln) from filehandle+readClustalAlignment :: String -> IO (Either ParseError ClustalAlignment)+readClustalAlignment = parseFromFile genParserClustalAlignment++-- | Parse Clustal alignment (.aln) with secondary structure in dot-bracket notation from String (as produced by mlocarna)+parseStructuralClustalAlignment :: String -> Either ParseError StructuralClustalAlignment+parseStructuralClustalAlignment = parse genParserStructuralClustalAlignment "genParserStructuralClustalAlignment"++-- | Parse Clustal alignment (.aln) with secondary structure in dot-bracket notation from filehandle (as produced by mlocarna)+readStructuralClustalAlignment :: String -> IO (Either ParseError StructuralClustalAlignment)+readStructuralClustalAlignment = parseFromFile genParserStructuralClustalAlignment++-- | Parse Clustal summary (printed to STDOUT) from String+parseClustalSummary :: String -> Either ParseError ClustalSummary+parseClustalSummary = parse genParserClustalSummary "genParserClustalSummary"++-- | Parse Clustal summary (printed to STDOUT) from file+readClustalSummary :: String -> IO (Either ParseError ClustalSummary)+readClustalSummary = parseFromFile genParserClustalSummary++-- | Parse nucleotide sequence. Allowed letters according to IUPAC+--parseNucleotideSequence :: GenParser Char st String+--parseNucleotideSequence = do+-- nucleotideSequence <- many1 (oneOf "RYSWKMBDHVNATUGCryswkmbdhvnatugc")+-- return $ nucleotideSequence++-- | Parse nucleotide alignment entry. Allowed letters according to IUPAC and commonly used gap characters+parseNucleotideAlignmentEntry :: GenParser Char st String+parseNucleotideAlignmentEntry = do+ entry <- many1 (oneOf "~_-.RYSWKMBDHVNATUGCryswkmbdhvnatugc")+ return $ entry++-- | Parse protein amino acid code sequence. Allowed letters according to IUPAC+--parseProteinSequence :: GenParser Char st String+--parseProteinSequence = do+-- proteinSequence <- many1 (oneOf "ABCDEFGHIKLMNPQRSTVWXYZabcdefghiklmnpqrstvwxyz")+-- return $ proteinSequence++-- | Parse protein amino acid code alignment entry. Allowed letters according to IUPAC and commonly used gap characters+--parseProteinAlignmentEntry :: GenParser Char st String+--parseProteinAlignmentEntry = do+-- entry <- many1 (oneOf "~_-.ABCDEFGHIKLMNPQRSTVWXYZabcdefghiklmnpqrstvwxyz")+-- return $ entry
+ Biobase/Clustal/Types.hs view
@@ -0,0 +1,131 @@+-- | This module contains data structures for the Clustal tools+-- For more information on Clustal tools consult: <http://www.clustal.org/>++module Biobase.Clustal.Types where+import qualified Data.Vector as V+import qualified Data.Text as T++-- | Data type for clustal summary, containing information about the alignment process, usually printed to STDOUT+data ClustalSummary = ClustalSummary+ {+ clustalw2version :: T.Text,+ sequenceFormat :: T.Text,+ parametersOfInputSequences :: [SequenceParameters],+ pairwiseAlignmentSummaries :: [PairwiseAlignmentSummary],+ guideTreeFileName :: T.Text,+ groupNumber :: Int,+ groupSummaries :: [GroupSummary],+ alignmentScore :: Int,+ alignmentFileName :: T.Text+ }+ deriving (Show, Eq)++data SequenceParameters = SequenceParameters+ {+ inputSequenceIndex :: Int,+ inputSequenceIdentifier :: T.Text,+ inputSequenceLength :: Int+ }+ deriving (Show, Eq)++data PairwiseAlignmentSummary = PairwiseAlignmentSummary+ {+ firstSequenceIndex :: Int,+ secondSequenceIndex :: Int,+ pairwiseAlignmentScore :: Int+ }+ deriving (Show, Eq)++data GroupSummary = GroupSummary+ {+ alignmentGroupIndex :: Int,+ numberOfAlignedSequences :: Maybe Int,+ groupScore :: Maybe Int+ }+ deriving (Show, Eq)++-- | Data structure for Clustal alignment format+data ClustalAlignment = ClustalAlignment+ {+ alignmentEntries :: [ClustalAlignmentEntry],+ conservationTrack :: T.Text+ }+ deriving (Eq)++instance Show ClustalAlignment where+ show (ClustalAlignment _alignmentEntries _conservationTrack )+ | not (null _alignmentEntries) = header ++ alignmentString+ | otherwise = header+ where header = "CLUSTAL W (1.8) multiple sequence alignment\n\n\n"+ longestSequenceIdLength = (maximum (map T.length (map entrySequenceIdentifier _alignmentEntries))) + 1+ totalSequenceLength = T.length (entryAlignedSequence (head _alignmentEntries))+ alignmentString = showAlignment totalSequenceLength longestSequenceIdLength 0 _alignmentEntries _conservationTrack++showAlignment :: Int -> Int -> Int -> [ClustalAlignmentEntry] -> T.Text -> String+showAlignment totalSequenceLength longestSequenceIdLength currentWindowPosition _alignmentEntries _conservationTrack+ | totalSequenceLength == 0 = []+ | currentWindowPosition < totalSequenceLength = showAlignmentBlock longestSequenceIdLength currentWindowPosition _alignmentEntries _conservationTrack ++ (showAlignment totalSequenceLength longestSequenceIdLength (currentWindowPosition + 60) _alignmentEntries _conservationTrack)+ | currentWindowPosition == totalSequenceLength = []+ | otherwise = ""++showAlignmentBlock :: Int -> Int -> [ClustalAlignmentEntry] -> T.Text -> String+showAlignmentBlock longestSequenceIdLength currentWindowPosition _alignmentEntries _conservationTrack = blockString+ where blockString = entries ++ extraTrack ++ "\n"+ entries = concatMap (showAlignmentLine longestSequenceIdLength currentWindowPosition) _alignmentEntries+ extraTrack = concat (replicate longestSequenceIdLength " ") ++ V.toList (V.slice currentWindowPosition 60 (V.fromList (T.unpack _conservationTrack))) ++ "\n"++showAlignmentLine :: Int -> Int -> ClustalAlignmentEntry -> String+showAlignmentLine longestSequenceIdLength currentWindowPosition _alignmentEntry = T.unpack (entrySequenceIdentifier _alignmentEntry) ++ concat (replicate (longestSequenceIdLength - T.length (entrySequenceIdentifier _alignmentEntry)) " ") ++ V.toList (V.slice currentWindowPosition 60 (V.fromList (T.unpack (entryAlignedSequence _alignmentEntry)))) ++ "\n"++data ClustalAlignmentEntry = ClustalAlignmentEntry+ {+ entrySequenceIdentifier :: T.Text,+ entryAlignedSequence :: T.Text+ }+ deriving (Show, Eq)++data ClustalAlignmentSlice = ClustalAlignmentSlice+ {+ entrySlices :: [ClustalAlignmentEntrySlice],+ conservationTrackSlice :: String+ }+ deriving (Show, Eq)++data ClustalAlignmentEntrySlice = ClustalAlignmentEntrySlice+ {+ entrySequenceSliceIdentifier :: String,+ entryAlignedSliceSequence :: String,+ spacerLength :: Int+ }+ deriving (Show, Eq)++-- | Data structure for structural Clustal alignment format+data StructuralClustalAlignment = StructuralClustalAlignment+ {+ structuralAlignmentEntries :: [ClustalAlignmentEntry],+ secondaryStructureTrack :: T.Text,+ energy :: Double+ }+ deriving (Eq)++instance Show StructuralClustalAlignment where+ show (StructuralClustalAlignment _alignmentEntries _secondaryStructureTrack _energy)+ | not (null _alignmentEntries) = header ++ alignmentString+ | otherwise = header+ where header = "CLUSTAL W \n\n"+ longestSequenceIdLength = (maximum (map T.length (map entrySequenceIdentifier _alignmentEntries))) + 1+ totalSequenceLength = T.length (entryAlignedSequence (head _alignmentEntries))+ alignmentString = showAlignment totalSequenceLength longestSequenceIdLength 0 _alignmentEntries _secondaryStructureTrack++-- data StructuralClustalAlignmentSlice = StructuralClustalAlignmentSlice+-- {+-- structuralEntrySlices :: [StructuralClustalAlignmentEntrySlice]+-- }+-- deriving (Show, Eq)++data StructuralClustalAlignmentEntrySlice = StructuralClustalAlignmentEntrySlice+ {+ structuralEntrySequenceSliceIdentifier :: String,+ structuralEntryAlignedSliceSequence :: String+ }+ deriving (Show, Eq)
+ ChangeLog.md view
@@ -0,0 +1,57 @@+-*-change-log-*-++### 1.3.0 [Florian Eggenhofer](mailto:egg@cs.uni-freiburg.de) 14. November 2019++ * Fixed requested tick number for compilation with GHC 8.6.*+ * Changed to Biobase style++### 1.2.3 [Florian Eggenhofer](mailto:egg@cs.uni-freiburg.de) 12. March 2018++ * Fixed parsing of additional newline in Biopythons AlignIO output without conservation track++### 1.2.2 [Florian Eggenhofer](mailto:egg@cs.uni-freiburg.de) 07. March 2018++ * Clustal parser can now parse alignments with missing consensus annotation++### 1.2.1 [Florian Eggenhofer](mailto:egg@cs.uni-freiburg.de) 06. February 2017++ * Structural alignment parser now works with multiline consensus structures++### 1.2.0 [Florian Eggenhofer](mailto:egg@cs.uni-freiburg.de) 07. January 2017++ * Changed datastructures for sequence identifers and sequences to Data.Text++### 1.1.4 [Florian Eggenhofer](mailto:egg@cs.uni-freiburg.de) 30. May 2016++ * Fixed a bug in output of clustal alignments with sequence length of 60++### 1.1.3 [Florian Eggenhofer](mailto:florian.eggenhofer@univie.ac.at) 4. July 2015++ * Nucleotide sequences are now parsed by a unified function in line with IUPAC nucleotide code++### 1.1.2 [Florian Eggenhofer](mailto:florian.eggenhofer@univie.ac.at) 3. July 2015++ * Included parsing of optional field in mlocarna clustal output++### 1.1.1 [Florian Eggenhofer](mailto:florian.eggenhofer@univie.ac.at) 2. July 2015++ * Added support for cmalign clustal output .++### 1.1.0 [Florian Eggenhofer](mailto:florian.eggenhofer@univie.ac.at) 1. July 2015++ * Added Hspec test-suite for parsing functions+ * Added Show instances for ClustalAlignment and StructuralClustalAlignment++### 1.0.3 [Florian Eggenhofer](mailto:florian.eggenhofer@univie.ac.at) 19. April 2015++ * Added Y (pyrimidine) and R (purine) to sequence characters++### 1.0.2 [Florian Eggenhofer](mailto:florian.eggenhofer@univie.ac.at> 19. March 2015++ * Linebreaks are now filtered from structural alignment sequence identifiers++### 1.0.1 [Florian Eggenhofer](mailto:florian.eggenhofer@univie.ac.at> 27. October 2014++ * Fixed compiler warnings and updated documentation to mention structural clustal format+ * Added -Wall and -O2 compiler options+ * Added support for clustal alignments with secondary structure annotation
ClustalParser.cabal view
@@ -1,29 +1,28 @@ name: ClustalParser-version: 1.2.3+version: 1.3.0 synopsis: Libary for parsing Clustal tools output description: Currently contains parsers and datatypes for: clustalw2, clustalo, mlocarna, cmalign . Clustal tools are multiple sequence alignment tools for biological sequence like DNA, RNA and Protein. For more information on clustal Tools refer to <http://www.clustal.org/>. .- Mlocarna is a multiple sequence alignment tool for RNA sequences with secondary structure output. + Mlocarna is a multiple sequence alignment tool for RNA sequences with secondary structure output. For more information on mlocarna refer to <http://www.bioinf.uni-freiburg.de/Software/LocARNA/>. . Cmalign is a multiple sequence alignment program based on RNA family models and produces ,among others, clustal output. It is part of infernal <http://infernal.janelia.org/>.- + license: GPL-3 license-file: LICENSE author: Florian Eggenhofer maintainer: egg@informatik.uni-freiburg.de--- copyright: category: Bioinformatics build-type: Simple-cabal-version: >=1.8-Tested-With: GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2+cabal-version: >=1.10.0+Tested-With: GHC == 8.4.4, GHC == 8.6.5, GHC == 8.8.1 extra-source-files:- README.md changelog+ README.md ChangeLog.md source-repository head type: git@@ -31,31 +30,35 @@ source-repository this type: git- location: https://github.com/eggzilla/ClustalParser/tree/1.2.3- tag: 1.2.3+ location: https://github.com/eggzilla/ClustalParser/tree/1.3.0+ tag: 1.3.0 -library- -- Modules exported by the library.- exposed-modules: Bio.ClustalParser- other-modules: Bio.ClustalData+Library+ Hs-Source-Dirs: .+ ghc-options: -Wall -fno-warn-unused-do-bind -fsimpl-tick-factor=500+ default-language: Haskell2010+ build-depends: base >=4.5 && <5,+ parsec>=3.1.9,+ vector,+ text+ Exposed-Modules: Biobase.Clustal+ Biobase.Clustal.Import+ Biobase.Clustal.Types - -- Other library packages from which modules are imported.- build-depends: base >=4.5 && <5, parsec>=3.1.9, vector, text - -- compiler options- ghc-options: -Wall -fno-warn-unused-do-bind- -- Directories containing source files.- hs-source-dirs: src- executable ClustalParserTest main-is: ClustalParserTest.hs- build-depends: base >= 4 && <= 5, cmdargs, ClustalParser, either-unwrap- -- compiler options - ghc-options: -Wall+ build-depends: base >= 4 && <= 5, cmdargs, ClustalParser, either-unwrap, text, vector, parsec+ -- compiler options+ ghc-options: -Wall -fno-warn-unused-do-bind -fsimpl-tick-factor=500+ default-language: Haskell2010+ other-modules: Biobase.Clustal.Import+ Biobase.Clustal.Types test-suite hspec build-depends: base, parsec, ClustalParser, hspec >= 2.0, text, hspec-discover hs-source-dirs: test-suite+ default-language: Haskell2010 main-is: Spec.hs type: exitcode-stdio-1.0 other-modules: ClustalParserSpec
ClustalParserTest.hs view
@@ -1,16 +1,15 @@ --runghc -package-db --ghc-arg=.cabal-sandbox/x86_64-linux-ghc-8.0.1-packages.conf.d ClustalParserTest.hs struct-multiline.mlocarna module Main where- + import System.Environment (getArgs)-import Bio.ClustalParser+import Biobase.Clustal.Import --import Data.Either.Unwrap main :: IO () main = do args <- getArgs- let input_file = (head args) + let input_file = (head args) -- read Clustal outputfile parsedinput <- readStructuralClustalAlignment input_file print parsedinput --print $ structuralAlignmentEntries (fromRight parsedinput)-
− changelog
@@ -1,30 +0,0 @@--*-change-log-*--1.2.3 Florian Eggenhofer <egg@cs.uni-freiburg.de> 12. March 2018- * Fixed parsing of additional newline in Biopythons AlignIO output without conservation track-1.2.2 Florian Eggenhofer <egg@cs.uni-freiburg.de> 07. March 2018- * Clustal parser can now parse alignments with missing consensus- annotation-1.2.1 Florian Eggenhofer <egg@cs.uni-freiburg.de> 06. February 2017- * Structural alignment parser now works with multiline consensus structures-1.2.0 Florian Eggenhofer <egg@cs.uni-freiburg.de> 07. January 2017- * Changed datastructures for sequence identifers and sequences to Data.Text-1.1.4 Florian Eggenhofer <egg@cs.uni-freiburg.de> 30. May 2016- * Fixed a bug in output of clustal alignments with sequence length of 60-1.1.3 Florian Eggenhofer <florian.eggenhofer@univie.ac.at> 4. July 2015- * Nucleotide sequences are now parsed by a unified function in line- with IUPAC nucleotide code-1.1.2 Florian Eggenhofer <florian.eggenhofer@univie.ac.at> 3. July 2015- * Included parsing of optional field in mlocarna clustal output-1.1.1 Florian Eggenhofer <florian.eggenhofer@univie.ac.at> 2. July 2015- * Added support for cmalign clustal output .-1.1.0 Florian Eggenhofer <florian.eggenhofer@univie.ac.at> 1. July 2015- * Added Hspec test-suite for parsing functions- * Added Show instances for ClustalAlignment and StructuralClustalAlignment-1.0.3 Florian Eggenhofer <florian.eggenhofer@univie.ac.at> 19. April 2015- * Added Y (pyrimidine) and R (purine) to sequence characters-1.0.2 Florian Eggenhofer <florian.eggenhofer@univie.ac.at> 19. March 2015- * Linebreaks are now filtered from structural alignment sequence identifiers-1.0.1 Florian Eggenhofer <florian.eggenhofer@univie.ac.at> 27. October 2014- * Fixed compiler warnings and updated documentation to mention structural clustal format- * Added -Wall and -O2 compiler options- * Added support for clustal alignments with secondary structure annotation
− src/Bio/ClustalData.hs
@@ -1,133 +0,0 @@--- | This module contains data structures for the Clustal tools --- For more information on Clustal tools consult: <http://www.clustal.org/>--module Bio.ClustalData where-import qualified Data.Vector as V-import qualified Data.Text as T- --- | Data type for clustal summary, containing information about the alignment process, usually printed to STDOUT-data ClustalSummary = ClustalSummary- {- clustalw2version :: T.Text,- sequenceFormat :: T.Text,- parametersOfInputSequences :: [SequenceParameters],- pairwiseAlignmentSummaries :: [PairwiseAlignmentSummary],- guideTreeFileName :: T.Text,- groupNumber :: Int,- groupSummaries :: [GroupSummary],- alignmentScore :: Int,- alignmentFileName :: T.Text- }- deriving (Show, Eq)--data SequenceParameters = SequenceParameters- {- inputSequenceIndex :: Int,- inputSequenceIdentifier :: T.Text,- inputSequenceLength :: Int- }- deriving (Show, Eq)--data PairwiseAlignmentSummary = PairwiseAlignmentSummary- {- firstSequenceIndex :: Int,- secondSequenceIndex :: Int,- pairwiseAlignmentScore :: Int- }- deriving (Show, Eq)--data GroupSummary = GroupSummary- {- alignmentGroupIndex :: Int,- numberOfAlignedSequences :: Maybe Int,- groupScore :: Maybe Int- }- deriving (Show, Eq)---- | Data structure for Clustal alignment format-data ClustalAlignment = ClustalAlignment- { - alignmentEntries :: [ClustalAlignmentEntry],- conservationTrack :: T.Text- }- deriving (Eq)--instance Show ClustalAlignment where- show (ClustalAlignment _alignmentEntries _conservationTrack ) - | not (null _alignmentEntries) = header ++ alignmentString- | otherwise = header- where header = "CLUSTAL W (1.8) multiple sequence alignment\n\n\n" - longestSequenceIdLength = (maximum (map T.length (map entrySequenceIdentifier _alignmentEntries))) + 1- totalSequenceLength = T.length (entryAlignedSequence (head _alignmentEntries))- alignmentString = showAlignment totalSequenceLength longestSequenceIdLength 0 _alignmentEntries _conservationTrack--showAlignment :: Int -> Int -> Int -> [ClustalAlignmentEntry] -> T.Text -> String-showAlignment totalSequenceLength longestSequenceIdLength currentWindowPosition _alignmentEntries _conservationTrack- | totalSequenceLength == 0 = [] - | currentWindowPosition < totalSequenceLength = showAlignmentBlock longestSequenceIdLength currentWindowPosition _alignmentEntries _conservationTrack ++ (showAlignment totalSequenceLength longestSequenceIdLength (currentWindowPosition + 60) _alignmentEntries _conservationTrack)- | currentWindowPosition == totalSequenceLength = [] - | otherwise = ""--showAlignmentBlock :: Int -> Int -> [ClustalAlignmentEntry] -> T.Text -> String-showAlignmentBlock longestSequenceIdLength currentWindowPosition _alignmentEntries _conservationTrack = blockString- where blockString = entries ++ extraTrack ++ "\n"- entries = concatMap (showAlignmentLine longestSequenceIdLength currentWindowPosition) _alignmentEntries- extraTrack = concat (replicate longestSequenceIdLength " ") ++ V.toList (V.slice currentWindowPosition 60 (V.fromList (T.unpack _conservationTrack))) ++ "\n"--showAlignmentLine :: Int -> Int -> ClustalAlignmentEntry -> String-showAlignmentLine longestSequenceIdLength currentWindowPosition _alignmentEntry = T.unpack (entrySequenceIdentifier _alignmentEntry) ++ concat (replicate (longestSequenceIdLength - T.length (entrySequenceIdentifier _alignmentEntry)) " ") ++ V.toList (V.slice currentWindowPosition 60 (V.fromList (T.unpack (entryAlignedSequence _alignmentEntry)))) ++ "\n"--data ClustalAlignmentEntry = ClustalAlignmentEntry- {- entrySequenceIdentifier :: T.Text,- entryAlignedSequence :: T.Text- }- deriving (Show, Eq)--data ClustalAlignmentSlice = ClustalAlignmentSlice- {- entrySlices :: [ClustalAlignmentEntrySlice],- conservationTrackSlice :: String- }- deriving (Show, Eq)--data ClustalAlignmentEntrySlice = ClustalAlignmentEntrySlice- {- entrySequenceSliceIdentifier :: String,- entryAlignedSliceSequence :: String,- spacerLength :: Int- }- deriving (Show, Eq)---- | Data structure for structural Clustal alignment format-data StructuralClustalAlignment = StructuralClustalAlignment- { - structuralAlignmentEntries :: [ClustalAlignmentEntry],- secondaryStructureTrack :: T.Text,- energy :: Double- }- deriving (Eq)--instance Show StructuralClustalAlignment where- show (StructuralClustalAlignment _alignmentEntries _secondaryStructureTrack _energy) - | not (null _alignmentEntries) = header ++ alignmentString- | otherwise = header- where header = "CLUSTAL W \n\n" - longestSequenceIdLength = (maximum (map T.length (map entrySequenceIdentifier _alignmentEntries))) + 1- totalSequenceLength = T.length (entryAlignedSequence (head _alignmentEntries))- alignmentString = showAlignment totalSequenceLength longestSequenceIdLength 0 _alignmentEntries _secondaryStructureTrack---- data StructuralClustalAlignmentSlice = StructuralClustalAlignmentSlice--- {--- structuralEntrySlices :: [StructuralClustalAlignmentEntrySlice]--- }--- deriving (Show, Eq)--data StructuralClustalAlignmentEntrySlice = StructuralClustalAlignmentEntrySlice- {- structuralEntrySequenceSliceIdentifier :: String,- structuralEntryAlignedSliceSequence :: String- }- deriving (Show, Eq)--
− src/Bio/ClustalParser.hs
@@ -1,294 +0,0 @@--- | Parse Clustal output--- For more information on Clustal tools consult: <http://www.clustal.org/>-module Bio.ClustalParser (- parseClustalAlignment,- readClustalAlignment,- parseStructuralClustalAlignment,- readStructuralClustalAlignment,- parseClustalSummary,- readClustalSummary,- module Bio.ClustalData- ) where--import Bio.ClustalData-import Text.ParserCombinators.Parsec -import Control.Monad-import Data.List-import qualified Data.Text as T-readDouble :: String -> Double-readDouble = read --readInt :: String -> Int-readInt = read---- | Parse the input as ClustalSummary datatype-genParserClustalSummary :: GenParser Char st ClustalSummary-genParserClustalSummary = do- newline- newline- newline- space- string "CLUSTAL "- version <- many1 (noneOf " ")- many1 (noneOf "\n")- newline- newline- newline- string "Sequence format is "- sequenceFormat' <- many1 (noneOf "\n")- newline- sequenceParametersList <- many1 (try genParserSequenceParameters)- string "Start of Pairwise alignments" - newline- string "Aligning..."- newline- newline- pairwiseAlignmentSummaryList <- many1 genParserPairwiseAlignmentSummary- string "Guide tree file created: ["- guideTreeFileName' <- many1 (noneOf "]")- char ']'- newline- newline- string "There are "- numberOfGroups <- many1 digit- string " groups"- newline- string "Start of Multiple Alignment"- newline- newline- string "Aligning..."- newline- groupSummaryList <- many1 genParserGroupSummary- string "Alignment Score "- alignmentScore' <- many1 digit- newline- newline- string "CLUSTAL-Alignment file created ["- alignmentFileName' <- many1 (noneOf "]")- char ']'- newline- newline- eof - return $ ClustalSummary (T.pack version) (T.pack sequenceFormat') sequenceParametersList pairwiseAlignmentSummaryList (T.pack guideTreeFileName') (readInt numberOfGroups) groupSummaryList (readInt alignmentScore') (T.pack alignmentFileName')--genParserGroupSummary :: GenParser Char st GroupSummary-genParserGroupSummary = do- string "Group " - groupIndex <- many1 digit- string ":"- optional space- optional (string "Sequences:")- many1 space- sequenceNumber <- optionMaybe (many1 digit)- optional (many1 space)- string "Score:" <|> string "Delayed"- groupScore' <- optionMaybe (many1 digit) - newline- return $ GroupSummary (readInt groupIndex) (liftM readInt sequenceNumber) (liftM readInt groupScore')--genParserPairwiseAlignmentSummary :: GenParser Char st PairwiseAlignmentSummary-genParserPairwiseAlignmentSummary = do- string "Sequences (" - firstSeqIndex <- many1 digit- string ":"- secondSeqIndex <- many1 digit- string ") Aligned. Score:"- many1 space- pairwiseScore <- many1 digit- newline- return $ PairwiseAlignmentSummary (readInt firstSeqIndex) (readInt secondSeqIndex) (readInt pairwiseScore)--genParserSequenceParameters :: GenParser Char st SequenceParameters-genParserSequenceParameters = do- string "Sequence " - sequenceIndexParam <- many1 digit- string ": "- sequenceIdentifierParam <- many1 (noneOf " ")- spaces- sequenceLengthParam <- many1 digit- space- string "bp"- newline- return $ SequenceParameters (readInt sequenceIndexParam) (T.pack sequenceIdentifierParam) (readInt sequenceLengthParam)---- | Parse the input as ClustalAlignment datatype-genParserClustalAlignment :: GenParser Char st ClustalAlignment-genParserClustalAlignment = do- string "CLUSTAL"- many1 (noneOf "\n")- many1 (try newline)- alignmentSlices <- many1 (try genParserClustalAlignmentSlice)- optional newline- eof - return (mergealignmentSlices alignmentSlices)--mergealignmentSlices :: [ClustalAlignmentSlice] -> ClustalAlignment-mergealignmentSlices slices = alignment- where entrySlicesList = concatMap entrySlices slices -- list of lists of entry slices- sequenceIdentifiers = nub (map entrySequenceSliceIdentifier entrySlicesList)- mergedAlignmentEntries = map (constructAlignmentEntries entrySlicesList) sequenceIdentifiers- mergedConservationTrack = concatMap conservationTrackSlice slices- alignment = ClustalAlignment mergedAlignmentEntries (T.pack mergedConservationTrack) --constructAlignmentEntries :: [ClustalAlignmentEntrySlice] -> String -> ClustalAlignmentEntry-constructAlignmentEntries slices entryIdentifier= entry- where currentSlices = filter (\a -> entrySequenceSliceIdentifier a == entryIdentifier) slices- entrySequence = concatMap entryAlignedSliceSequence currentSlices- entry = ClustalAlignmentEntry (T.pack entryIdentifier) (T.pack entrySequence)--genParserClustalAlignmentSlice :: GenParser Char st ClustalAlignmentSlice-genParserClustalAlignmentSlice = do- entrySlices' <- many1 genParserClustalEntrySlice- --extract length of identifier and spacer to determine offset of conservation track- let offsetLenght = length (entrySequenceSliceIdentifier (head entrySlices')) + spacerLength (head entrySlices')- conservationTrackSliceChoice <- choice [(lookAhead (string "\n")), (try (genParserConservationTrackSlice offsetLenght))]- --spacerAndConservationTrackSlice <- many1 (noneOf "\n")- --let conservationTrackSlice' = drop offsetLenght spacerAndConservationTrackSlice- --newline- let conservationTrackSlice' = if (conservationTrackSliceChoice == "\n") then "" else conservationTrackSliceChoice- optional newline- return $ ClustalAlignmentSlice entrySlices' conservationTrackSlice'--genParserConservationTrackSlice :: Int -> GenParser Char st String-genParserConservationTrackSlice offsetLenght = do- spacerAndConservationTrackSlice <- many1 (noneOf "\n")- let conservationTrackSlice' = drop offsetLenght spacerAndConservationTrackSlice- newline- return $ conservationTrackSlice'--genParserClustalEntrySlice :: GenParser Char st ClustalAlignmentEntrySlice-genParserClustalEntrySlice = do- sliceIdentifier <- many1 (noneOf " \n")- spacer <- many1 (char ' ')- sliceSequence <- parseNucleotideAlignmentEntry- newline- return $ ClustalAlignmentEntrySlice sliceIdentifier sliceSequence (length spacer)----Structural Clustal Parser functions---- | Parse the input as ClustalAlignment datatype as used in mlocarna-genParserStructuralClustalAlignment :: GenParser Char st StructuralClustalAlignment-genParserStructuralClustalAlignment = do- genParseMlocarnaHeader- alignmentSlices <- many1 (try genParserStructuralClustalAlignmentSlice)- secondaryStructure <- genSecondaryStructure - energy' <- genParseEnergy- eof - return (mergeStructuralAlignmentSlices (concat alignmentSlices) secondaryStructure energy')--genSecondaryStructure :: GenParser Char st String-genSecondaryStructure = do- string "alifold"- secondaryStructure <- many1 (try genSecondaryStructureSlice)- return (concat secondaryStructure)--genSecondaryStructureSlice :: GenParser Char st String-genSecondaryStructureSlice = do- many1 space - secondaryStructureSlice <- many1 (try (oneOf ".()"))- choice [try (string "\n"),try (string " ")]- return secondaryStructureSlice- -genParseEnergy :: GenParser Char st Double-genParseEnergy = do- string "("- many space - energy' <- many1 (noneOf " ")- optional space- char ('=')- many1 (noneOf "\n")- newline - return (readDouble energy')--genParseMlocarnaHeader :: GenParser Char st String-genParseMlocarnaHeader = do- string "mLocARNA"- many1 (choice [alphaNum,oneOf "-: ()."])- newline- string "Copyright"- many1 (choice [alphaNum,char ' '])- newline- newline - string "Compute pair probs ..."- newline- optional (try (string "Compute pairwise alignments ... "))- optional (try newline)- string "Perform progressive alignment ..."- many1 newline- return ""--mergeStructuralAlignmentSlices :: [StructuralClustalAlignmentEntrySlice] -> String -> Double -> StructuralClustalAlignment-mergeStructuralAlignmentSlices slices secondaryStructure energy' = alignment- where sequenceIdentifiers = nub (map structuralEntrySequenceSliceIdentifier slices)- mergedAlignmentEntries = map (constructStructuralAlignmentEntries slices) sequenceIdentifiers- alignment = StructuralClustalAlignment mergedAlignmentEntries (T.pack secondaryStructure) energy' --constructStructuralAlignmentEntries :: [StructuralClustalAlignmentEntrySlice] -> String -> ClustalAlignmentEntry-constructStructuralAlignmentEntries slices entryIdentifier= entry- where currentSlices = filter (\a -> structuralEntrySequenceSliceIdentifier a == entryIdentifier) slices- entrySequence = concatMap structuralEntryAlignedSliceSequence currentSlices- entry = ClustalAlignmentEntry (T.pack entryIdentifier) (T.pack entrySequence)--genParserStructuralClustalAlignmentSlice :: GenParser Char st [StructuralClustalAlignmentEntrySlice]-genParserStructuralClustalAlignmentSlice = do- entrySlices' <- many1 (try genParserStructuralClustalEntrySlice)- optional newline- return entrySlices'--genParserStructuralClustalEntrySlice :: GenParser Char st StructuralClustalAlignmentEntrySlice-genParserStructuralClustalEntrySlice = do- sliceIdentifier <- many1 (noneOf " ")- many1 (char ' ')- sliceSequence <- parseNucleotideAlignmentEntry- newline- return $ StructuralClustalAlignmentEntrySlice (filter (/='\n') sliceIdentifier) sliceSequence---- exported functions---- | Parse Clustal alignment (.aln) from String-parseClustalAlignment :: String -> Either ParseError ClustalAlignment -parseClustalAlignment = parse genParserClustalAlignment "genParserClustalAlignment"---- | Parse Clustal alignment (.aln) from filehandle -readClustalAlignment :: String -> IO (Either ParseError ClustalAlignment) -readClustalAlignment = parseFromFile genParserClustalAlignment---- | Parse Clustal alignment (.aln) with secondary structure in dot-bracket notation from String (as produced by mlocarna)-parseStructuralClustalAlignment :: String -> Either ParseError StructuralClustalAlignment -parseStructuralClustalAlignment = parse genParserStructuralClustalAlignment "genParserStructuralClustalAlignment"---- | Parse Clustal alignment (.aln) with secondary structure in dot-bracket notation from filehandle (as produced by mlocarna) -readStructuralClustalAlignment :: String -> IO (Either ParseError StructuralClustalAlignment) -readStructuralClustalAlignment = parseFromFile genParserStructuralClustalAlignment---- | Parse Clustal summary (printed to STDOUT) from String-parseClustalSummary :: String -> Either ParseError ClustalSummary-parseClustalSummary = parse genParserClustalSummary "genParserClustalSummary"---- | Parse Clustal summary (printed to STDOUT) from file-readClustalSummary :: String -> IO (Either ParseError ClustalSummary) -readClustalSummary = parseFromFile genParserClustalSummary---- | Parse nucleotide sequence. Allowed letters according to IUPAC---parseNucleotideSequence :: GenParser Char st String---parseNucleotideSequence = do--- nucleotideSequence <- many1 (oneOf "RYSWKMBDHVNATUGCryswkmbdhvnatugc") --- return $ nucleotideSequence---- | Parse nucleotide alignment entry. Allowed letters according to IUPAC and commonly used gap characters-parseNucleotideAlignmentEntry :: GenParser Char st String-parseNucleotideAlignmentEntry = do- entry <- many1 (oneOf "~_-.RYSWKMBDHVNATUGCryswkmbdhvnatugc") - return $ entry---- | Parse protein amino acid code sequence. Allowed letters according to IUPAC---parseProteinSequence :: GenParser Char st String---parseProteinSequence = do--- proteinSequence <- many1 (oneOf "ABCDEFGHIKLMNPQRSTVWXYZabcdefghiklmnpqrstvwxyz") --- return $ proteinSequence---- | Parse protein amino acid code alignment entry. Allowed letters according to IUPAC and commonly used gap characters---parseProteinAlignmentEntry :: GenParser Char st String---parseProteinAlignmentEntry = do--- entry <- many1 (oneOf "~_-.ABCDEFGHIKLMNPQRSTVWXYZabcdefghiklmnpqrstvwxyz") --- return $ entry
test-suite/ClustalParserSpec.hs view
@@ -1,6 +1,6 @@ module ClustalParserSpec (spec) where -import Bio.ClustalParser +import Biobase.Clustal.Import import Test.Hspec import Test.Hspec.QuickCheck import Text.Parsec.Error@@ -31,8 +31,8 @@ context "Parsing invalid input" $ do it "Returns ParseError" $ do (parseStructuralClustalAlignment "invalid input") `shouldBe` Left structuralClustalParseError- - ++ clustalParseError :: ParseError clustalParseError = (addErrorMessage (Expect "\"CLUSTAL\"") (newErrorMessage clustalErrorMessage clustalErrorSourcePosition)) @@ -59,7 +59,7 @@ structuralClustalExample :: String structuralClustalExample = "mLocARNA --- multiple Local (and global) Alignment of RNA --- LocARNA 1.8.0\nCopyright Sebastian Will\n\nCompute pair probs ...\nPerform progressive alignment ...\n\n\n\nAB001721.1/2735-2851 CCCGGUGACUAUAGAGAGAGGGCCACACCCGUUCCCAUCCCGAACACGGAAGUUAAGCCUCUCAUCGCUGAUGGUACUAUGUGGUUCGCUGCAUGGGAGAGUAGGACGUUGCCGGGU\ngi|451991584:1-117 CCCGGUGACUAUAGAGAGAGGGCCACACCCGUUCCCAUCCCGAACACGGAAGUUAAGCCUCUCAUCGCUGAUGGUACUAUGUGGUUCGCUGCAUGGGAGAGUAGGACGUUGCCGGGU\nalifold (((((((((....(.(((.(((.....))).))).)...(((....)))..(((..(((((((((.((.(.(((.(((....))))))).))))))))).))..)))))))))))). (-38.30 = -38.30 + 0.00)\n"- + structuralClustalResult :: StructuralClustalAlignment structuralClustalResult = StructuralClustalAlignment [ClustalAlignmentEntry (T.pack "AB001721.1/2735-2851") (T.pack "CCCGGUGACUAUAGAGAGAGGGCCACACCCGUUCCCAUCCCGAACACGGAAGUUAAGCCUCUCAUCGCUGAUGGUACUAUGUGGUUCGCUGCAUGGGAGAGUAGGACGUUGCCGGGU"),ClustalAlignmentEntry (T.pack "gi|451991584:1-117") (T.pack "CCCGGUGACUAUAGAGAGAGGGCCACACCCGUUCCCAUCCCGAACACGGAAGUUAAGCCUCUCAUCGCUGAUGGUACUAUGUGGUUCGCUGCAUGGGAGAGUAGGACGUUGCCGGGU")] (T.pack "(((((((((....(.(((.(((.....))).))).)...(((....)))..(((..(((((((((.((.(.(((.(((....))))))).))))))))).))..)))))))))))).") (-38.30)