cobot-io 0.1.5.5 → 0.1.5.7
raw patch · 14 files changed
+158/−108 lines, 14 filesdep −arraydep ~containersdep ~lensdep ~linearPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies removed: array
Dependency ranges changed: containers, lens, linear
API changes (from Hackage documentation)
+ Bio.Sequence: type family Marking s
- Bio.Sequence: bareSequ :: Lens' (BareSequence a) (Vector a)
+ Bio.Sequence: bareSequ :: forall a f. Functor f => (Vector a -> f (Vector a)) -> BareSequence a -> f (BareSequence a)
- Bio.Sequence: class (IsMarking (Marking s), IsWeight (Weight s)) => IsSequence s where {
+ Bio.Sequence: class (IsMarking Marking s, IsWeight Weight s) => IsSequence s where {
- Bio.Sequence: markings :: Getter (Sequence mk w a) [(mk, Range)]
+ Bio.Sequence: markings :: forall mk w a f. (Contravariant f, Functor f) => ([(mk, Range)] -> f [(mk, Range)]) -> Sequence mk w a -> f (Sequence mk w a)
- Bio.Sequence: sequ :: Getter (Sequence mk w a) (Vector a)
+ Bio.Sequence: sequ :: forall mk w a f. (Contravariant f, Functor f) => (Vector a -> f (Vector a)) -> Sequence mk w a -> f (Sequence mk w a)
- Bio.Sequence: type ContainsMarking s = (IsSequence s, NotUnit (Marking s))
+ Bio.Sequence: type ContainsMarking s = (IsSequence s, NotUnit Marking s)
- Bio.Sequence: type ContainsNoMarking s = (IsSequence s, Unit (Marking s))
+ Bio.Sequence: type ContainsNoMarking s = (IsSequence s, Unit Marking s)
- Bio.Sequence: type ContainsNoWeight s = (IsSequence s, Unit (Weight s))
+ Bio.Sequence: type ContainsNoWeight s = (IsSequence s, Unit Weight s)
- Bio.Sequence: type ContainsWeight s = (IsSequence s, NotUnit (Weight s))
+ Bio.Sequence: type ContainsWeight s = (IsSequence s, NotUnit Weight s)
- Bio.Sequence: type Element s :: Type;
+ Bio.Sequence: type Element s;
- Bio.Sequence: type IsBareSequence s = (IsSequence s, Unit (Marking s), Unit (Weight s))
+ Bio.Sequence: type IsBareSequence s = (IsSequence s, Unit Marking s, Unit Weight s)
- Bio.Sequence: type IsMarkedSequence s = (IsSequence s, NotUnit (Marking s), Unit (Weight s))
+ Bio.Sequence: type IsMarkedSequence s = (IsSequence s, NotUnit Marking s, Unit Weight s)
- Bio.Sequence: type IsWeightedSequence s = (IsSequence s, Unit (Marking s), NotUnit (Weight s))
+ Bio.Sequence: type IsWeightedSequence s = (IsSequence s, Unit Marking s, NotUnit Weight s)
- Bio.Sequence: type Marking s :: Type;
+ Bio.Sequence: type Marking s;
- Bio.Sequence: type Weight s :: Type;
+ Bio.Sequence: type Weight s;
- Bio.Sequence: weights :: Getter (Sequence mk w a) (Vector w)
+ Bio.Sequence: weights :: forall mk w a f. (Contravariant f, Functor f) => (Vector w -> f (Vector w)) -> Sequence mk w a -> f (Sequence mk w a)
- Bio.Sequence.Class: bareSequ :: Lens' (BareSequence a) (Vector a)
+ Bio.Sequence.Class: bareSequ :: forall a f. Functor f => (Vector a -> f (Vector a)) -> BareSequence a -> f (BareSequence a)
- Bio.Sequence.Class: class (IsMarking (Marking s), IsWeight (Weight s)) => IsSequence s where {
+ Bio.Sequence.Class: class (IsMarking Marking s, IsWeight Weight s) => IsSequence s where {
- Bio.Sequence.Class: markings :: Getter (Sequence mk w a) [(mk, Range)]
+ Bio.Sequence.Class: markings :: forall mk w a f. (Contravariant f, Functor f) => ([(mk, Range)] -> f [(mk, Range)]) -> Sequence mk w a -> f (Sequence mk w a)
- Bio.Sequence.Class: sequ :: Getter (Sequence mk w a) (Vector a)
+ Bio.Sequence.Class: sequ :: forall mk w a f. (Contravariant f, Functor f) => (Vector a -> f (Vector a)) -> Sequence mk w a -> f (Sequence mk w a)
- Bio.Sequence.Class: type ContainsMarking s = (IsSequence s, NotUnit (Marking s))
+ Bio.Sequence.Class: type ContainsMarking s = (IsSequence s, NotUnit Marking s)
- Bio.Sequence.Class: type ContainsNoMarking s = (IsSequence s, Unit (Marking s))
+ Bio.Sequence.Class: type ContainsNoMarking s = (IsSequence s, Unit Marking s)
- Bio.Sequence.Class: type ContainsNoWeight s = (IsSequence s, Unit (Weight s))
+ Bio.Sequence.Class: type ContainsNoWeight s = (IsSequence s, Unit Weight s)
- Bio.Sequence.Class: type ContainsWeight s = (IsSequence s, NotUnit (Weight s))
+ Bio.Sequence.Class: type ContainsWeight s = (IsSequence s, NotUnit Weight s)
- Bio.Sequence.Class: type Element s :: Type;
+ Bio.Sequence.Class: type Element s;
- Bio.Sequence.Class: type IsBareSequence s = (IsSequence s, Unit (Marking s), Unit (Weight s))
+ Bio.Sequence.Class: type IsBareSequence s = (IsSequence s, Unit Marking s, Unit Weight s)
- Bio.Sequence.Class: type IsMarkedSequence s = (IsSequence s, NotUnit (Marking s), Unit (Weight s))
+ Bio.Sequence.Class: type IsMarkedSequence s = (IsSequence s, NotUnit Marking s, Unit Weight s)
- Bio.Sequence.Class: type IsWeightedSequence s = (IsSequence s, Unit (Marking s), NotUnit (Weight s))
+ Bio.Sequence.Class: type IsWeightedSequence s = (IsSequence s, Unit Marking s, NotUnit Weight s)
- Bio.Sequence.Class: type Marking s :: Type;
+ Bio.Sequence.Class: type Marking s;
- Bio.Sequence.Class: type Weight s :: Type;
+ Bio.Sequence.Class: type Weight s;
- Bio.Sequence.Class: weights :: Getter (Sequence mk w a) (Vector w)
+ Bio.Sequence.Class: weights :: forall mk w a f. (Contravariant f, Functor f) => (Vector w -> f (Vector w)) -> Sequence mk w a -> f (Sequence mk w a)
Files
- ChangeLog.md +8/−5
- cobot-io.cabal +10/−10
- src/Bio/GB/Parser.hs +18/−15
- src/Bio/MMTF/Decode/MessagePack.hs +5/−1
- src/Bio/PDB.hs +4/−6
- src/Bio/PDB/BondRestoring.hs +22/−18
- src/Bio/PDB/Functions.hs +8/−7
- src/Bio/PDB/Reader.hs +1/−1
- src/Bio/Sequence/Functions/Marking.hs +1/−1
- src/Bio/Sequence/Functions/Weight.hs +1/−3
- src/Bio/Uniprot/Parser.hs +20/−9
- test/GB/pIntA-TRBV.gb +4/−4
- test/GB/spaces_in_locus.gb +20/−0
- test/GBParserSpec.hs +36/−28
ChangeLog.md view
@@ -2,6 +2,9 @@ ## [Unreleased] +## [0.1.5.6] - 2024-12-18+- Fix for gb-parser: spaces in name in LOCUS+ ## [0.1.5.5] - 2024-05-16 - Add `5ROX` modification to Fasta parser. @@ -64,12 +67,12 @@ - Update dependency versions. ## [0.1.3.20] - 2021-06-04-### Changed -- YLAB2-629: Fasta parser is now able to parse empty lines in the beginning. +### Changed+- YLAB2-629: Fasta parser is now able to parse empty lines in the beginning. ## [0.1.3.19] - 2021-04-30-### Changed -- Exports and instances for Biosset. +### Changed+- Exports and instances for Biosset. ## [0.1.3.18] - 2021-03-09 ### Fixed@@ -110,7 +113,7 @@ ## [0.1.3.9] - 2020-10-27 ### Fixed-- FASTA parser can now parse empty lines with spaces. +- FASTA parser can now parse empty lines with spaces. ## [0.1.3.8] - 2020-10-22 ### Fixed
cobot-io.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.3.+-- This file has been generated from package.yaml by hpack version 0.36.0. -- -- see: https://github.com/sol/hpack name: cobot-io-version: 0.1.5.5+version: 0.1.5.7 synopsis: Biological data file formats and IO description: Please see the README on GitHub at <https://github.com/biocad/cobot-io#readme> category: Bio@@ -24,6 +24,7 @@ || ==9.4.8 || ==9.6.3 || ==9.8.1+ || ==9.10.3 extra-source-files: README.md@@ -33,6 +34,7 @@ test/GB/pAAV-GFP-CellBioLab.gb test/GB/pAAV_CMV_RPE65_PolyA_linkers.gb test/GB/pIntA-TRBV.gb+ test/GB/spaces_in_locus.gb test/FASTA/correct.fasta test/FASTA/order1.fasta test/FASTA/order10.fasta@@ -188,20 +190,19 @@ TemplateHaskell FlexibleContexts build-depends:- array ==0.5.*- , attoparsec >=0.10 && <0.15+ attoparsec >=0.10 && <0.15 , base >=4.14 && <5 , binary >=0.8.3.0 && <1.0 , bytestring >=0.10.8.1 && <0.13 , cobot >=0.1.1.7- , containers >=0.5.7.1 && <0.7+ , containers >=0.5.7.1 && <0.9 , data-msgpack >=0.0.9 && <0.1 , deepseq >=1.4 && <1.6 , filepath , http-conduit ==2.3.* , hyraxAbif >=0.2.3.27 && <0.2.5.0- , lens >=4.16 && <5.3- , linear >=1.20 && <1.23+ , lens >=4.16 && <5.4+ , linear >=1.20 && <1.24 , megaparsec >=9.0.1 , mtl >=2.2.1 && <2.4 , parser-combinators >=1.2.1@@ -241,14 +242,13 @@ ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends: QuickCheck >=2.9.2 && <2.15- , array ==0.5.* , attoparsec >=0.10 && <0.15 , base >=4.14 && <5 , binary >=0.8.3.0 && <1.0 , bytestring >=0.10.8.1 && <0.13 , cobot >=0.1.1.7 , cobot-io- , containers >=0.5.7.1 && <0.7+ , containers >=0.5.7.1 && <0.9 , data-msgpack >=0.0.9 && <0.1 , deepseq >=1.4 && <1.6 , directory@@ -256,7 +256,7 @@ , hspec >=2.4.1 && <2.12 , http-conduit ==2.3.* , hyraxAbif >=0.2.3.27 && <0.2.5.0- , lens >=4.16 && <5.3+ , lens >=4.16 && <5.4 , linear , megaparsec , mtl >=2.2.1 && <2.4
src/Bio/GB/Parser.hs view
@@ -26,7 +26,7 @@ genBankP = GenBankSequence <$> (metaP <?> "Meta parser") <*> (gbSeqP <?> "GB sequence parser")- <* string "//" <* eolSpaceP + <* string "//" <* eolSpaceP -------------------------------------------------------------------------------- -- Block with meta-information.@@ -48,16 +48,19 @@ locusP :: Parser Locus locusP = string "LOCUS" *> space *> (Locus- <$> textP <* space -- name+ <$> nameP <* space -- name <*> decimal <* space <* string "bp" <* space -- sequence length <*> textP <* space -- molecule type- <*> optional formP <* space -- form of sequence- <*> optional (pack <$> some (satisfy isUpper)) <* space -- GenBank division+ <*> optional formP <* space -- form of sequence+ <*> optional (pack <$> some (satisfy isUpper)) <* space -- GenBank division <*> textP -- modification date <* eolSpaceP) where textP = takeWhile1P Nothing $ not . isSpace + nameP :: Parser Text+ nameP = textP <> (try (string " " <> nameP) <|> "")+ formP :: Parser Form formP = try (string "linear" $> Linear) <|> (string "circular" $> Circular) @@ -108,7 +111,7 @@ -------------------------------------------------------------------------------- featuresP :: Parser [(Feature, Range)]-featuresP = -- skip unknown fields and stop on line with "FEATURES" +featuresP = -- skip unknown fields and stop on line with "FEATURES" manyTill (textWithSpacesP <* eolSpaceP) (string "FEATURES") *> space *> textWithSpacesP <* eolSpaceP *> some (featureP <?> "Single feature parser")@@ -128,8 +131,8 @@ pure (Feature featureName' props, shiftRange (-1) range) rangeP :: Parser Range-rangeP = try spanP - <|> try betweenP +rangeP = try spanP+ <|> try betweenP <|> try pointP <|> try joinP <|> complementP@@ -141,8 +144,8 @@ _ <- string ".." upperBorderType <- option Precise (try $ char '>' *> pure Exceeded) upperBorderLocation <- decimal- pure $ Span (RangeBorder lowerBorderType lowerBorderLocation) (RangeBorder upperBorderType upperBorderLocation) - + pure $ Span (RangeBorder lowerBorderType lowerBorderLocation) (RangeBorder upperBorderType upperBorderLocation)+ betweenP :: Parser Range betweenP = do before <- decimal@@ -152,14 +155,14 @@ pointP :: Parser Range pointP = fmap Point decimal- + joinP :: Parser Range joinP = string "join(" *> fmap Join (rangeP `sepBy1` char ',') <* char ')' complementP :: Parser Range complementP = fmap Complement $ string "complement(" *> rangeP <* char ')'- + propsP :: Parser (Text, Text) propsP = do _ <- string featureIndent2@@ -178,17 +181,17 @@ indLine = do _ <- string featureIndent2 notFollowedBy (char '/')- text <- textWithSpacesP + text <- textWithSpacesP eolSpaceP pure text multiLineProp :: Parser Text multiLineProp = do- fstText <- textWithSpacesP <* eolSpaceP + fstText <- textWithSpacesP <* eolSpaceP rest <- many (try indLine)- pure $ T.concat (fstText : rest) + pure $ T.concat (fstText : rest) - + -- | First level of identation in FEATURES table file. --
src/Bio/MMTF/Decode/MessagePack.hs view
@@ -43,7 +43,11 @@ asStr m _ = fail $ T.unpack m <> ": not a string data" asChar :: MonadFail m => Text -> Object -> m Char-asChar m = (head . T.unpack <$>) . asStr m+asChar txt obj = do+ str <- asStr txt obj+ case T.unpack str of+ [] -> return ' '+ (c : _) -> return c asInt :: (MonadFail m, Integral a) => Text -> Object -> m a asInt _ (ObjectInt i) = pure (fromIntegral i)
src/Bio/PDB.hs view
@@ -72,15 +72,13 @@ mkResidue :: Map Text (Vector (Bond LocalID)) -> [PDB.Atom] -> Residue mkResidue _ [] = error "Cound not make residue from empty list"- mkResidue localBondsMap atoms' = Residue (T.strip $ PDB.atomResName firstResidueAtom)- (PDB.atomResSeq firstResidueAtom)- (PDB.atomICode firstResidueAtom)+ mkResidue localBondsMap atoms'@(firstAtom : _) = Residue (T.strip $ PDB.atomResName firstAtom)+ (PDB.atomResSeq firstAtom)+ (PDB.atomICode firstAtom) (V.fromList $ mkAtom <$> atoms')- (localBondsMap M.!?! residueID firstResidueAtom)+ (localBondsMap M.!?! residueID firstAtom) Undefined -- now we do not read secondary structure "" -- chemical component type?!- where- firstResidueAtom = head atoms' mkAtom :: PDB.Atom -> Atom mkAtom atom@PDB.Atom{..} = Atom (GlobalID $ atomToNilBasedIndex M.!?! atom)
src/Bio/PDB/BondRestoring.hs view
@@ -42,25 +42,28 @@ residueIDToLocalBonds = do (residueAtoms, residueBonds) <- zip chainAtomsGroupedByResidue intraResidueGlobalBonds let localBonds = V.fromList $ convertGlobalsToLocals residueAtoms residueBonds- let _residueID = residueID $ head residueAtoms+ let _residueID =+ case residueAtoms of+ [] -> ""+ (atom : _) -> residueID atom pure (_residueID, localBonds)- + intraResidueGlobalBonds :: [[Bond PDB.Atom]] intraResidueGlobalBonds = fmap restoreIntraResidueBonds chainAtomsGroupedByResidue- + chainAtomsGroupedByResidue :: [[PDB.Atom]] chainAtomsGroupedByResidue = groupChainByResidue chainAtoms- + convertGlobalsToLocals :: [PDB.Atom] -> [Bond PDB.Atom] -> [Bond LocalID] convertGlobalsToLocals residueAtoms = map convertGlobalToLocal where convertGlobalToLocal :: Bond PDB.Atom -> Bond LocalID- convertGlobalToLocal (Bond from to order) = + convertGlobalToLocal (Bond from to order) = Bond (LocalID $ atomToLocalIdMap ! from) (LocalID $ atomToLocalIdMap ! to) order- + atomToLocalIdMap :: Map PDB.Atom Int atomToLocalIdMap = M.fromList $ zip sortedAtoms [0..]- + sortedAtoms :: [PDB.Atom] sortedAtoms = sort residueAtoms @@ -70,19 +73,19 @@ where convertToGlobalIDs :: Map PDB.Atom Int -> Vector (Bond PDB.Atom) -> Vector (Bond GlobalID) convertToGlobalIDs mapping = reindexBonds (\atom -> GlobalID $ mapping ! atom)- + reindexBonds :: (a -> b) -> Vector (Bond a) -> Vector (Bond b) reindexBonds convertID = fmap (\(Bond from to order) -> Bond (convertID from) (convertID to) order) chainAtomsGroupedByResidue :: Vector [[PDB.Atom]] chainAtomsGroupedByResidue = fmap groupChainByResidue chains- + _intraResidueBonds :: [Bond PDB.Atom] _intraResidueBonds = concatMap restoreChainIntraResidueBonds chainAtomsGroupedByResidue- + peptideBonds :: [Bond PDB.Atom] peptideBonds = concatMap restoreChainPeptideBonds chainAtomsGroupedByResidue- + disulfideBonds :: [Bond PDB.Atom] disulfideBonds = restoreDisulfideBonds . concat $ V.toList chainAtomsGroupedByResidue @@ -116,7 +119,7 @@ restoreChainPeptideBonds' :: [[PDB.Atom]] -> [Maybe (Bond PDB.Atom)] -> [Maybe (Bond PDB.Atom)] restoreChainPeptideBonds' [] acc = acc restoreChainPeptideBonds' [_] acc = acc- restoreChainPeptideBonds' (residue1:residue2:residues) acc = + restoreChainPeptideBonds' (residue1:residue2:residues) acc = restoreChainPeptideBonds' (residue2:residues) (constructBond residue1 residue2 : acc) constructBond :: [PDB.Atom] -> [PDB.Atom] -> Maybe (Bond PDB.Atom)@@ -129,7 +132,7 @@ guard $ distance (coords carbonAtom1) (coords nitrogenAtom2) < peptideBondMaxLength pure $ Bond carbonAtom1 nitrogenAtom2 1- + getAtomByName :: [PDB.Atom] -> Text -> Maybe PDB.Atom getAtomByName atoms atomNameToFind = find ((atomNameToFind ==) . T.strip . PDB.atomName) atoms @@ -137,20 +140,21 @@ restoreChainIntraResidueBonds = concatMap restoreIntraResidueBonds restoreIntraResidueBonds :: [PDB.Atom] -> [Bond PDB.Atom]-restoreIntraResidueBonds residueAtoms = catMaybes $ constructBond <$> residueBonds+restoreIntraResidueBonds [] = []+restoreIntraResidueBonds residueAtoms@(firstAtom : _) = catMaybes $ constructBond <$> residueBonds where -- TODO: support bond order somehow constructBond :: (Text, Text) -> Maybe (Bond PDB.Atom) constructBond (fromAtomName, toAtomName) = Bond <$> constructAtom fromAtomName <*> constructAtom toAtomName <*> Just 1- + constructAtom :: Text -> Maybe PDB.Atom constructAtom atomName = atomNameToAtom !? atomName- + atomNameToAtom :: Map Text PDB.Atom atomNameToAtom = M.fromList $ (\atom@PDB.Atom{..} -> (T.strip atomName, atom)) <$> residueAtoms- + residueBonds :: [(Text, Text)]- residueBonds = intraResidueBonds . T.strip . PDB.atomResName $ head residueAtoms+ residueBonds = intraResidueBonds . T.strip . PDB.atomResName $ firstAtom intraResidueBonds :: Text -> [(Text, Text)] intraResidueBonds "NMA" = [("CA", "N")]
src/Bio/PDB/Functions.hs view
@@ -7,20 +7,21 @@ import Data.Map.Strict (Map) import qualified Data.Map.Strict as M (fromList)-import Data.List (groupBy, +import Data.List (groupBy, sortOn) import Data.Vector (Vector) import qualified Data.Vector as V (toList) import Data.Char (toUpper) groupChainByResidue :: Vector PDB.Atom -> [[PDB.Atom]]-groupChainByResidue = sortOn (sortOnResidue . head) . groupBy atomsFromSameResidue . V.toList- where +groupChainByResidue = sortOn sortOnResidue . groupBy atomsFromSameResidue . V.toList+ where atomsFromSameResidue :: PDB.Atom -> PDB.Atom -> Bool atomsFromSameResidue atom1 atom2 = PDB.atomResSeq atom1 == PDB.atomResSeq atom2 && PDB.atomICode atom1 == PDB.atomICode atom2- - sortOnResidue :: PDB.Atom -> Int- sortOnResidue PDB.Atom{..} = atomSerial * 100 + (insertionCodeSortingCorrections M.!?! toUpper atomICode)- ++ sortOnResidue :: [PDB.Atom] -> Int+ sortOnResidue [] = -1000000+ sortOnResidue (PDB.Atom{..} : _) = atomSerial * 100 + (insertionCodeSortingCorrections M.!?! toUpper atomICode)+ insertionCodeSortingCorrections :: Map Char Int insertionCodeSortingCorrections = M.fromList $ zip (' ':['A'..'Z']) [0..]
src/Bio/PDB/Reader.hs view
@@ -48,7 +48,7 @@ checkRow :: [Int] -> Bool checkRow [] = True-checkRow xs = last xs - head xs + 1 == L.length xs+checkRow row@(x : _) = last row - x + 1 == L.length row checkMdlLines :: ([PDBWarnings], Text) -> Bool checkMdlLines warnings'n'text = checkRow mdlLineNumbers
src/Bio/Sequence/Functions/Marking.hs view
@@ -16,7 +16,7 @@ import Data.List.NonEmpty (NonEmpty (..)) import Data.Text (Text) import qualified Data.Vector as V (toList)-import Prelude hiding (drop, head, length, null, reverse, tail, take, (!!))+import Prelude hiding (length) import Bio.NucleicAcid.Nucleotide (Complementary (..)) import Bio.Sequence.Class (ContainsMarking, IsBareSequence, IsMarkedSequence,
src/Bio/Sequence/Functions/Weight.hs view
@@ -25,9 +25,7 @@ import Data.Vector (Vector) import qualified Data.Vector as V (drop, length, take, toList, (!))-import Prelude hiding (drop, head, length,- null, reverse, tail, take,- (!!))+import Prelude hiding (drop, length, take, (!!)) -- | Range of form [a, b]. --
src/Bio/Uniprot/Parser.hs view
@@ -8,7 +8,7 @@ module Bio.Uniprot.Parser where import Prelude hiding (null)-import qualified Prelude as P (concat, init, last, null, tail)+import qualified Prelude as P (concat, init, last) #if MIN_VERSION_base(4, 18, 0) import Control.Applicative ((<|>))@@ -127,7 +127,9 @@ string "=" pure () result <- pack . P.init <$> many1 (satisfy (not . isEndOfLine))- pure . head $ " {ECO" `splitOn` result+ case " {ECO" `splitOn` result of+ [] -> pure ""+ (txt : _) -> pure txt -- Parses internal DE entities parseInternal :: Text -> Parser DE@@ -235,9 +237,11 @@ taxId <- pack <$> many1 (notChar ';') char ';' hostName' <- many' (satisfy $ not . isEndOfLine)- let hostName = pack $ if P.null hostName'- then ""- else P.tail . P.init $ hostName'+ let hostName = pack $+ case hostName' of+ [] -> ""+ [x] -> ""+ (x : xs) -> init xs pure OH{..} -- | Parses RN, RP, RC, RX, RG, RA, RT and RL lines of UniProt-KB text file.@@ -300,7 +304,11 @@ topic <- pack <$> many1 (notChar ':') char ':' (char ' ' $> ()) <|> (endOfLine >> string "CC" >> count 7 space $> ())- comment <- head . (" {ECO" `splitOn`) . pack <$> parseMultiLineComment "CC" 7+ splitedComments <- (" {ECO" `splitOn`) . pack <$> parseMultiLineComment "CC" 7+ let comment =+ case splitedComments of+ [] -> ""+ (x : _) -> x pure CC{..} -- | UniProt-KB copyright comment@@ -494,7 +502,10 @@ parseDefItem :: Text -> Parser Text parseDefItem name = do string name >> char '='- head . (" {" `splitOn`) . pack <$> parseTillChar ';'+ txt <- (" {" `splitOn`) . pack <$> parseTillChar ';'+ case txt of+ [] -> return ""+ (x : _) -> return x -- | Parses line till specific char (e.g. semicolon or dot) before space/endOfLine/endOfInput. parseTillChar :: Char -> Parser String@@ -524,8 +535,8 @@ hyphenConcat (x:y:ys) = x ++ hyphenConcat (sy:ys) where sy :: String- sy | last x == '-' = tail y- | isAA (last x) && isAA (y !! 1) = tail y+ sy | last x == '-' = drop 1 y+ | isAA (last x) && isAA (y !! 1) = drop 1 y | otherwise = y isAA :: Char -> Bool
test/GB/pIntA-TRBV.gb view
@@ -1,6 +1,6 @@-LOCUS P2-32_pIntA-TRBV5-1_J1-1-Fc-lama-knob-EPEA 5960 bp circular 27-NOV-2020-SOURCE - ORGANISM +LOCUS P2-32_pIntA-TRBV5-1_J1-1-Fc-lama-knob-EPEA 5960 bp circular 27-NOV-2020+SOURCE+ ORGANISM COMMENT This file is created by Vector NTI http://www.invitrogen.com/ COMMENT ORIGDB|GenBank@@ -9,7 +9,7 @@ COMMENT LSOWNER| COMMENT VNTNAME|pIntA-mIgK-GFP-stuffer-KpnI-EPEA| COMMENT VNTAUTHORNAME|Demo User|-BASE COUNT 1711 a 1577 c 1543 g 1830 t +BASE COUNT 1711 a 1577 c 1543 g 1830 t EMBL_ID P1-79_pIntA-mIgK-GFP-stuffer-KpnI-EPEA 5945 bp circular 14-OCT-2020 EMBL_ID P1-79_pIntA-mIgK-GFP-stuffer-KpnI-EPEA 6661 bp circular 29-JAN-2020 EMBL_ID pIntA-mIgK-GFP-s 6661 bp DNA circular 4-OCT-2019
+ test/GB/spaces_in_locus.gb view
@@ -0,0 +1,20 @@+LOCUS BLABLA BLABLA BLABLA 100 bp DNA circular SYN 11-SEP-2024 +DEFINITION synthetic circular DNA. +ACCESSION . +VERSION . +KEYWORDS . +SOURCE synthetic DNA construct + ORGANISM synthetic DNA construct +REFERENCE 1 (bases 1 to 100) + AUTHORS hhh + TITLE Direct Submission + JOURNAL Exported Sep 12, 2024 from SnapGene 6.1.0 + https://www.snapgene.com +FEATURES Location/Qualifiers + source 1..100 + /mol_type="other DNA" + /organism="plasmid" +ORIGIN + 1 cctacagcgt cctacagcgt cctacagcgt cctacagcgt cctacagcgt cctacagcgt + 61 cctacagcgt cctacagcgt cctacagcgt cctacagcgt +//
test/GBParserSpec.hs view
@@ -20,50 +20,51 @@ dottedMetaSpecP "test/GB/pAAV-GFP-CellBioLab-dots.gb" unknownFieldsSpecP "test/GB/pIntA-TRBV.gb" baseCountWithSophisticatedRangesAndMultilineFeatures "test/GB/fromYanaWithLove.gb"+ spacesInLocusName "test/GB/spaces_in_locus.gb" rangeTests :: Spec rangeTests = describe "Range parser" $ do- it "correctly parses a simple span" $ + it "correctly parses a simple span" $ greedyRangeP "69..420" `shouldBe` successful (Span (RangeBorder Precise 69) (RangeBorder Precise 420)) it "correctly parses a span with the lower border exceeded" $ greedyRangeP "<69..420" `shouldBe` successful (Span (RangeBorder Exceeded 69) (RangeBorder Precise 420)) it "correctly parses a span with the upper border exceeded" $ greedyRangeP "69..>420" `shouldBe` successful (Span (RangeBorder Precise 69) (RangeBorder Exceeded 420))- it "correctly parses a span with both border exceeded" $ + it "correctly parses a span with both border exceeded" $ greedyRangeP "<69..>420" `shouldBe` successful (Span (RangeBorder Exceeded 69) (RangeBorder Exceeded 420))- it "does not parse a span with the lower border exceeded incorrectly" $ + it "does not parse a span with the lower border exceeded incorrectly" $ greedyRangeP ">69..420" `shouldSatisfy` isFail- it "does not parse a span with the upper border exceeded incorrectly" $ + it "does not parse a span with the upper border exceeded incorrectly" $ greedyRangeP "69..<420" `shouldSatisfy` isFail - it "correctly parses a 'between' statement" $ + it "correctly parses a 'between' statement" $ greedyRangeP "41^42" `shouldBe` successful (Between 41 42)- it "does not parse a 'between' statement witn border excession marks" $ + it "does not parse a 'between' statement witn border excession marks" $ greedyRangeP "<41^42" `shouldSatisfy` isFail - it "correctly parses a single point feature" $ + it "correctly parses a single point feature" $ greedyRangeP "42" `shouldBe` successful (Point 42)- it "does not parse a single point feature with border excession marks" $ + it "does not parse a single point feature with border excession marks" $ greedyRangeP "<3" `shouldSatisfy` isFail - it "correctly parses a join() statement" $ + it "correctly parses a join() statement" $ greedyRangeP "join(2,12..56)" `shouldBe` successful (Join [Point 2, Span (RangeBorder Precise 12) (RangeBorder Precise 56)])- it "correctly parses a sophisticated join() statement" $ + it "correctly parses a sophisticated join() statement" $ greedyRangeP "join(2^3,<5..10,15,20..>28)" `shouldBe` successful (Join [Between 2 3, Span (RangeBorder Exceeded 5) (RangeBorder Precise 10), Point 15, Span (RangeBorder Precise 20) (RangeBorder Exceeded 28)]) - it "correctly parses a complement() statement" $ + it "correctly parses a complement() statement" $ greedyRangeP "complement(69..>420)" `shouldBe` successful (Complement (Span (RangeBorder Precise 69) (RangeBorder Exceeded 420)))- it "correctly parses a join() incorporated into a complement()" $ + it "correctly parses a join() incorporated into a complement()" $ greedyRangeP "complement(join(2^3,<5..10,15,20..>28))" `shouldBe` successful (Complement (Join [Between 2 3, Span (RangeBorder Exceeded 5) (RangeBorder Precise 10), Point 15, Span (RangeBorder Precise 20) (RangeBorder Exceeded 28)])) where greedyRangeP :: Text -> Either String Range greedyRangeP = over _Left errorBundlePretty . parse (rangeP <* eof) ""- + successful :: a -> Either String a successful = Right isFail :: Either String a -> Bool- isFail = null + isFail = null pAAVGFPSpecP :: FilePath -> Spec pAAVGFPSpecP path = describe "pAAVGFP" $ do@@ -101,7 +102,7 @@ baseCountWithSophisticatedRangesAndMultilineFeatures path = describe "" $ do it "correctly parses the 'BASE COUNT' line and features with sophisticated ranges" $ do gbS <- gbSeq <$> fromFile path- gbS `shouldBe` unsafeMarkedSequence sophisticatedFeaturesSeq sophisticatedFeatures + gbS `shouldBe` unsafeMarkedSequence sophisticatedFeaturesSeq sophisticatedFeatures compPreciseSpan :: (Int, Int) -> Range compPreciseSpan = Complement . preciseSpan@@ -218,20 +219,20 @@ sophisticatedFeaturesSeq = "cctacagcgtgagctatgagaaagcgccacgcttcccgaagggagaaaggcggacaggtatccggtaagcggcagggtcggaacaggagagcgcacgagggagcttccagggggaaacgcctggtatctttatagtcctgtcgggtttcgccacctctgacttgagcgtcgatttttgtgatgctcgtcaggggggcggagcctatggaaaaacgccagcaacgcggcctttttacggttcctggccttttgctggccttttgctcacatgttctttcctgcgttatcccctgattctgtggataaccgtattaccgcctttgagtgagctgataccgctcgccgcagccgaacgaccgagcgcagcgagtcagtgagcgaggaagcgtacatttatattggctcatgtccaatatgaccgccatgttgacattgattattgactagaccgcgttacataacttacggtaaatggcccgcctggctgaccgcccaacgacccccgcccattgacgtcaataatgacgtatgttcccatagtaacgccaatagggactttccattgacgtcaatgggtggagtatttacggtaaactgcccacttggcagtacatcaagtgtatcatatgccaagtacgccccctattgacgtcaatgacggtaaatggcccgcctggcattatgcccagtacatgaccttatgggactttcctacttggcagtacatctacgtattagtcatcgctattaccatggtgatgcggttttggcagtacatcaatgggcgtggatagcggtttgactcacggggatttccaagtctccaccccattgacgtcaatgggagtttgttttggcaccaaaatcaacgggactttccaaaatgtcgtaacaactccgccccattgacgcaaatgggcggtaggcgtgtacggtgggaggtctatataagcagagctcgtttagtgaaccgtcagatcgcctggagacgccatccacgctgttttgacctccatagaagacaccgggaccgatccagcctccgcggccgggaacggtgcattggaacgcggattccccgtgccaagagtgacgtaagtaccgcctatagagtctataggcccacccccttggcttcttatgcatgctatactgtttttggcttggggtctatacacccccgcttcctcatgttataggtgatggtatagcttagcctataggtgtgggttattgaccattattgaccactcccctattggtgacgatactttccattactaatccataacatggctctttgccacaactctctttattggctatatgccaatacactgtccttcagagactgacacggactctgtatttttacaggatggggtctcatttattatttacaaattcacatatacaacaccaccgtccccagtgcccgcagtttttattaaacataacgtgggatctccacgcgaatctcgggtacgtgttccggacatgggctcatctccggtagcggcggagcttctacatccgagccctgctcccatgcctccagcgactcatggtcgctcggcagctccttgctcctaacagtggaggccagacttaggcacagcacgatgcccaccaccaccagtgtgccgcacaaggccgtggcggtagggtatgtgtctgaaaatgagctcggggagcgggcttgcaccgctgacgcatttggaagacttaaggcagcggcagaagaagatgcaggcagctgagttgttgtgttctgataagagtcagaggtaactcccgttgcggtgctgttaacggtggagggcagtgtagtctgagcagtactcgttgctgccgcgcgcgccaccagacataatagctgacagactaacagactgttcctttccatgggtcttttctgcagtcaccgtccttgacacgaagcttgccgccaccatggagaccgacaccctgctgctgtgggtgctgctgctgtgggtgcccgggtcgacgaagagctcatgagcggatacatatttgaatgtatttagaaaaataaacaaataggggtcagtgttacaaccaattaaccaattctgaacattatcgcgagcccatttatacctgaatatggctcataacaccccttgtttgcctggcggcagtagcgcggtggtcccacctgaccccatgccgaactcagaagtgaaacgccgtagcgccgatggtagtgtggggactccccatgcgagagtagggaactgccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgcccgggctaattatggggtgtcgcccttggggtgagaccctcgagtgtacagaattcttactgatacgtgtccagatcaaccgctttcacgacctctaccagacacatgtgatcacggcgctcgtcgcggtctttgctcagtttggtgtggtaggtaatgtgatgataacgcgggatatgcactgccgcggagcccgccaacggacgattcatttggctgcatttggtaaccagtttttcggtcacaccttcaatatcgtacgcctggttgaactcaacgcggatgccattgttaacggtgtcaggcagaatatacagaatgcttggcgggcattggaatgcaacgttcttacgcagaatgtgaccgtctttcttaaagttctcaccagtcagcgtgacacgattgtagatagaaccgcgttcgtaggtaaccatagcacgcgtcttgtacacgccgtcgccttcgaagctgatggtacgctcttgggtataaccttccggcatggcgctcttaaagaaatccttgatgtggctcgggtacttgcgaaacactgaacaccgtagctcagggtgctcaccagggttgcccacgggacccggcaggtcgcccgtagtgcagatgtatttcgctttaatggtacccgtggtcgcgtcacccggtaccctcgcctttaatgataaatttcataccttcgacgtcgccttccagttcggtgatatacgggatctctttctcaaacagttttgcaccttccgtcaatgccgtcatatgtttacctcctaaggtctcgaaaagttaaacaaaattatttctaaagggaaaccgttgtggaattgtgagcgctcacaattccacatattataattgttatccgctcacaaagcaaataaatttttcatgatttcactgtgcatgaagctcgtaattgttatccgctcacaattaagggcgacacaaaatttattctaaatgataataaatactgataacatcttatagtttgtattatattttgtattatcgttgacatgtataattttgatatcaaaaactgattttccctttattattttcgagatttattttcttaattctctttaacaaactagaaatattgtatatacaaaaaatcataaataatagatgaatagtttaattataggtgttcatcaatcgaaaaagcaacgtatcttatttaaagtgcgttgcttttttctcatttataaggttaaataattctcatatatcaagcaaagtgacaggcgcccttaaatattctgacaaatgctctttccctaaactccccccataaaaaaacccgccgaagcgggtttttacgttatttgcggattaacgattactcgttatcagaaccgcccagggggcccgagcttaagactggccgtcgttttacaacacaagctcttccgtacggtggctgcaccatctgtcttcatcttcccgccatctgatgagcagttgaaatctggaactgcctctgttgtgtgcctgctgaataacttctatcccagagaggccaaagtacagtggaaggtggataacgccctccaatcgggtaactcccaggagagtgtcacagagcaggacagcaaggacagcacctacagcctcagcagcaccctgacgctgagcaaagcagactacgagaaacacaaagtctacgcctgcgaagtcacccatcagggcctgagctcgcccgtcacaaagagcttcaacaggggagagtgttaatagtctagacctaggtgatcataatcagccataccacatttgtagaggttttacttgctttaaaaaacctcccacacctccccctgaacctgaaacataaaatgaatgcaattgttgttgttaacttgtttattgcagcttataatggttacaaataaagcaatagcatcacaaatttcacaaataaagcatttttttcactgcattctagttgtggtttgtccaaactcatcaatgtatcttatcatgtctggagatctctagctagaggatcgatccccgccccggacgaactaaacctgactacgacatctctgccccttcttcgcggggcagtgcatgtaatcccttcagttggttggtacaacttgccaactgaaccctaaacgggtagcatatgcttcccgggtagtagtatatactatccagactaaccctaattcaatagcatatgttacccaacgggaagcatatgctatcgaattagggttagtaaaagggtcctaaggaacagcgatgtaggtgggcgggccaagataggggcgcgattgctgcgatctggaggacaaattacacacacttgcgcctgagcgccaagcacagggttgttggtcctcatattcacgaggtcgctgagagcacggtgggctaatgttgccatgggtagcatatactacccaaatatctggatagcatatgctatcctaatctatatctgggtagcataggctatcctaatctatatctgggtagcatatgctatcctaatctatatctgggtagtatatgctatcctaatttatatctgggtagcataggctatcctaatctatatctgggtagcatatgctatcctaatctatatctgggtagtatatgctatcctaatctgtatccgggtagcatatgctatcctaatagagattagggtagtatatgctatcctaatttatatctgggtagcatatactacccaaatatctggatagcatatgctatcctaatctatatctgggtagcatatgctatcctaatctatatctgggtagcataggctatcctaatctatatctgggtagcatatgctatcctaatctatatctgggtagtatatgctatcctaatttatatctgggtagcataggctatcctaatctatatctgggtagcatatgctatcctaatctatatctgggtagtatatgctatcctaatctgtatccgggtagcatatgctatcctcatgataagctgtcaaacatgagaattaattcttgaagacgaaagggcctcgtgatacgcctatttttataggttaatgtcatgataataatggtttcttagacgtcaggtggcacttttcggggaaatgtgcgcggaacccctatttgtttatttttctaaatacattcaaatatgtatccgctcatgagacaataaccctgataaatgcttcaataatattgaaaaaggaagagtatgagtattcaacatttccgtgtcgcccttattcccttttttgcggcattttgccttcctgtttttgctcacccagaaacgctggtgaaagtaaaagatgctgaagatcagttgggtgcacgagtgggttacatcgaactggatctcaacagcggtaagatccttgagagttttcgccccgaagaacgttttccaatgatgagcacttttaaagttctgctatgtggcgcggtattatcccgtgttgacgccgggcaagagcaactcggtcgccgcatacactattctcagaatgacttggttgagtactcaccagtcacagaaaagcatcttacggatggcatgacagtaagagaattatgcagtgctgccataaccatgagtgataacactgcggccaacttacttctgacaacgatcggaggaccgaaggagctaaccgcttttttgcacaacatgggggatcatgtaactcgccttgatcgttgggaaccggagctgaatgaagccataccaaacgacgagcgtgacaccacgatgcctgcagcaatggcaacaacgttgcgcaaactattaactggcgaactacttactctagcttcccggcaacaattaatagactggatggaggcggataaagttgcaggaccacttctgcgctcggcccttccggctggctggtttattgctgataaatctggagccggtgagcgtgggtctcgcggtatcattgcagcactggggccagatggtaagccctcccgtatcgtagttatctacacgacggggagtcaggcaactatggatgaacgaaatagacagatcgctgagataggtgcctcactgattaagcattggtaactgtcagaccaagtttactcatatatactttagattgatttaaaacttcatttttaatttaaaaggatctaggtgaagatcctttttgataatctcatgaccaaaatcccttaacgtgagttttcgttccactgagcgtcagaccccgtagaaaagatcaaaggatcttcttgagatcctttttttctgcgcgtaatctgctgcttgcaaacaaaaaaaccaccgctaccagcggtggtttgtttgccggatcaagagctaccaactctttttccgaaggtaactggcttcagcagagcgcagataccaaatactgttcttctagtgtagccgtagttaggccaccacttcaagaactctgtagcaccgcctacatacctcgctctgctaatcctgttaccagtggctgctgccagtggcgataagtcgtgtcttaccgggttggactcaagacgatagttaccggataaggcgcagcggtcgggctgaacggggggttcgtgcacacagcccagcttggagcgaacgacctacaccgaactgagata" sophisticatedFeatures :: [(Feature, Range)]-sophisticatedFeatures = - [ (Feature "source" +sophisticatedFeatures =+ [ (Feature "source" [ ("organism", "synthetic DNA construct") , ("mol_type", "other DNA") ] , preciseSpan (0, 6950)) - , (Feature "rep_origin" + , (Feature "rep_origin" [ ("label", "pUCorigin and also a multiline property") , ("note", "/vntifkey=33") ] , Join [Point 0, preciseSpan (6550, 6950)]) - , (Feature "enhancer" + , (Feature "enhancer" [ ("label", "cmv enhanser") , ("label", "cmv\\enhanser") , ("note", "/vntifkey=9")@@ -251,7 +252,7 @@ ] , preciseSpan (1011, 1918)) - , (Feature "primer_bind" + , (Feature "primer_bind" [ ("label", "inv olig1") ] , preciseSpan (1501, 1521)) @@ -269,7 +270,7 @@ ] , preciseSpan (1953, 2009)) - , (Feature "misc_feature" + , (Feature "misc_feature" [ ("label", "START") , ("note", "START") , ("note", "/ugene_name=START")@@ -277,7 +278,7 @@ ] , preciseSpan (1953, 1955)) - , (Feature "misc_feature" + , (Feature "misc_feature" [ ("label", "GFP stuffer") , ("note", "GFP stuffer") , ("note", "/ugene_name=GFP\\ stuffer")@@ -285,7 +286,7 @@ ] , preciseSpan (2010, 3738)) - , (Feature "misc_feature" + , (Feature "misc_feature" [ ("label", "CK") , ("note", "CK") , ("note", "/ugene_name=CK")@@ -293,7 +294,7 @@ ] , preciseSpan (3739, 4059)) - , (Feature "misc_feature" + , (Feature "misc_feature" [ ("label", "STOP") , ("note", "STOP") , ("note", "/ugene_name=STOP")@@ -301,7 +302,7 @@ ] , preciseSpan (4060, 4065)) - , (Feature "misc_feature" + , (Feature "misc_feature" [ ("gene", "SV40_PA term") , ("label", "SV40_PA term") , ("label", "SV40_PA\\term")@@ -309,18 +310,18 @@ ] , preciseSpan (4078, 4316)) - , (Feature "primer_bind" + , (Feature "primer_bind" [ ("label", "pEE_Clab") ] , preciseSpan (4349, 4369)) - , (Feature "rep_origin" + , (Feature "rep_origin" [ ("label", "EBV ori") , ("label", "EBV\\ori") , ("note", "/vntifkey=33") ] , preciseSpan (4581, 4974)) - , (Feature "CDS" + , (Feature "CDS" [ ("codon_start", "1") , ("label", "AmpR") , ("note", "/vntifkey=4")@@ -328,3 +329,10 @@ ] , preciseSpan (5542, 6402)) ]++spacesInLocusName :: FilePath -> Spec+spacesInLocusName path =+ describe "should correct parse gb with spaces in plasmid name in locus" $+ it "" $ do+ mt <- meta <$> fromFile path+ name (locus mt) `shouldBe` "BLABLA BLABLA BLABLA"