cobot-io 0.1.3.11 → 0.1.3.12
raw patch · 6 files changed
+64/−27 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- ChangeLog.md +5/−0
- cobot-io.cabal +2/−2
- src/Bio/PDB/BondRestoring.hs +9/−3
- src/Bio/PDB/Parser.hs +24/−22
- test/PDBParserSpec.hs +23/−0
- test/Spec.hs +1/−0
ChangeLog.md view
@@ -2,6 +2,11 @@ ## [Unreleased] +## [0.1.3.12] - 2020-11-11+### Fixed+- PDB parser error: it didn't account for segment identifier field.+- Bond restoring in PDB for non-standard residue names.+ ## [0.1.3.11] - 2020-11-08 ### Changed - Allow `linear-0.21`.
cobot-io.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 4a6f3015c17c537b110962a77c5d6d5da84a9a9a01620acfb07850485afca69a+-- hash: aad94ebea31bcb6b5c480d834d36fb486ea7a71241c328be223d6a91c736be66 name: cobot-io-version: 0.1.3.11+version: 0.1.3.12 synopsis: Biological data file formats and IO description: Please see the README on GitHub at <https://github.com/biocad/cobot-io#readme> category: Bio
src/Bio/PDB/BondRestoring.hs view
@@ -170,12 +170,18 @@ sideChainBonds "ALA" = bwhMany [("CB", ["HB1", "HB2", "HB3"])] sideChainBonds "ARG" = [("CB", "CG"), ("CG", "CD"), ("CD", "NE"), ("NE", "CZ"), ("CZ", "NH2"), ("CZ", "NH1")] ++ bwhMany[("CB", ["HB3", "HB2"]), ("CG", ["HG3", "HG2"]), ("CD", ["HD3", "HD2"]), ("NE", ["HE"]), ("NH1", ["HH12", "HH11"]), ("NH2", ["HH22", "HH21"])] sideChainBonds "ASN" = [("CB", "CG"), ("CG", "OD1"), ("CG", "ND2")] ++ bwhMany [("CB", ["HB3", "HB2"]), ("ND2", ["HD22", "HD21"])]-sideChainBonds "ASP" = [("CB", "CG"), ("CG", "OD1"), ("CG", "OD2")] ++ bwhMany [("CB", ["HB3", "HB2"]), ("OD2", ["HD2"])]+sideChainBonds "ASP" = [("CB", "CG"), ("CG", "OD1"), ("CG", "OD2")] ++ bwhMany [("CB", ["HB3", "HB2"]), ("OD2", ["HD2"])] -- in fact, these are bonds for ASH, but sometimes ASH called just ASP...+sideChainBonds "ASH" = [("CB", "CG"), ("CG", "OD1"), ("CG", "OD2")] ++ bwhMany [("CB", ["HB3", "HB2"]), ("OD2", ["HD2"])] sideChainBonds "CYS" = [("CB", "SG")] ++ bwhMany [("CB", ["HB3", "HB2"]), ("SG", ["HG"])]+sideChainBonds "CYX" = [("CB", "SG")] ++ bwhMany [("CB", ["HB3", "HB2"]), ("SG", ["HG"])] sideChainBonds "GLN" = [("CB", "CG"), ("CG", "CD"), ("CD", "OE1"), ("CD", "NE2")] ++ bwhMany [("CB", ["HB3", "HB2"]), ("CG", ["HG3", "HG2"]), ("NE2", ["HE22", "HE21"])]-sideChainBonds "GLU" = [("CB", "CG"), ("CG", "CD"), ("CD", "OE1"), ("CD", "OE2")] ++ bwhMany [("CB", ["HB1", "HB2", "HB3"]), ("CG", ["HG3", "HG2"]), ("OE2", ["HE2"])]+sideChainBonds "GLU" = [("CB", "CG"), ("CG", "CD"), ("CD", "OE1"), ("CD", "OE2")] ++ bwhMany [("CB", ["HB1", "HB2", "HB3"]), ("CG", ["HG3", "HG2"]), ("OE2", ["HE2"])] -- in fact, these are bonds for GLH, but sometimes GLH called just GLU...+sideChainBonds "GLH" = [("CB", "CG"), ("CG", "CD"), ("CD", "OE1"), ("CD", "OE2")] ++ bwhMany [("CB", ["HB1", "HB2", "HB3"]), ("CG", ["HG3", "HG2"]), ("OE2", ["HE2"])] sideChainBonds "GLY" = [] -- nothing-sideChainBonds "HIS" = [("CB", "CG"), ("CG", "ND1"), ("ND1", "CE1"), ("CE1", "NE2"), ("NE2", "CD2"), ("CD2", "CG")] ++ bwhMany [("CB", ["HB3", "HB2"]), ("ND1", ["HD1"]), ("CE1", ["HE1"]), ("NE2", ["HE2"]), ("CD2", ["HD2"])]+sideChainBonds "HID" = [("CB", "CG"), ("CG", "ND1"), ("ND1", "CE1"), ("CE1", "NE2"), ("NE2", "CD2"), ("CD2", "CG")] ++ bwhMany [("CB", ["HB3", "HB2"]), ("ND1", ["HD1"]), ("CE1", ["HE1"]), ("CD2", ["HD2"]), ("CD2", ["HD2"])] -- in fact, these are bonds for HIP, but residue names in PDB is a mess...+sideChainBonds "HIE" = [("CB", "CG"), ("CG", "ND1"), ("ND1", "CE1"), ("CE1", "NE2"), ("NE2", "CD2"), ("CD2", "CG")] ++ bwhMany [("CB", ["HB3", "HB2"]), ("CE1", ["HE1"]), ("NE2", ["HE2"]), ("CD2", ["HD2"]), ("CD2", ["HD2"])] -- in fact, these are bonds for HIP, but residue names in PDB is a mess...+sideChainBonds "HIP" = [("CB", "CG"), ("CG", "ND1"), ("ND1", "CE1"), ("CE1", "NE2"), ("NE2", "CD2"), ("CD2", "CG")] ++ bwhMany [("CB", ["HB3", "HB2"]), ("ND1", ["HD1"]), ("CE1", ["HE1"]), ("NE2", ["HE2"]), ("CD2", ["HD2"])] -- in fact, these are bonds for HIP, but residue names in PDB is a mess...+sideChainBonds "HIS" = [("CB", "CG"), ("CG", "ND1"), ("ND1", "CE1"), ("CE1", "NE2"), ("NE2", "CD2"), ("CD2", "CG")] ++ bwhMany [("CB", ["HB3", "HB2"]), ("ND1", ["HD1"]), ("CE1", ["HE1"]), ("NE2", ["HE2"]), ("CD2", ["HD2"])] -- this covers all possible histidines with 'HIS' name sideChainBonds "ILE" = [("CB", "CG1"), ("CB", "CG2"), ("CG1", "CD1")] ++ bwhMany [("CB", ["HB", "HB2", "HB3"]), ("CG1", ["HG13", "HG12"]), ("CG2", ["HG21", "HG22", "HG23"]), ("CD1", ["HD11", "HD12", "HD13"])] sideChainBonds "LEU" = [("CB", "CG"), ("CG", "CD1"), ("CG", "CD2")] ++ bwhMany [("CB", ["HB3", "HB2"]), ("CG", ["HG", "HG2"]), ("CD1", ["HD11", "HD12", "HD13"]), ("CD2", ["HD21", "HD22", "HD23"])] sideChainBonds "LYS" = [("CB", "CG"), ("CG", "CD"), ("CD", "CE"), ("CE", "NZ")] ++ bwhMany [("CB", ["HB1", "HB2", "HB3"]), ("CG", ["HG1", "HG2", "HG3"]), ("CD", ["HD3", "HD2"]), ("CE", ["HE3", "HE2"]), ("NZ", ["HZ1", "HZ2", "HZ3"])]
src/Bio/PDB/Parser.hs view
@@ -12,10 +12,12 @@ import Control.DeepSeq () import Data.Attoparsec.Text (Parser, choice, count, endOfInput, endOfLine, isEndOfLine, satisfy,- skipWhile, space, string, takeWhile)+ skipWhile, space, string, takeWhile,+ anyChar) import qualified Data.List as L (groupBy) import Data.Map.Strict (Map, fromListWithKey) import Data.Maybe (catMaybes)+import Data.Function (on) import Data.Text as T (Text, concat, pack, stripEnd) import qualified Data.Vector as V (Vector, concat, fromList, singleton) import GHC.Generics ()@@ -64,32 +66,32 @@ atomP :: Parser CoordLike atomP = let atom = Atom <$> (- (string "ATOM " *> -- (1 - 5) ATOM -- we extended atomSerial length to the left for one symbol- (read <$> count 6 notEndLineChar)) -- (6 - 11) atomSerial- <|> -- or- (string "HETATM" *> -- (1 - 6) HETATM- (read <$> count 5 notEndLineChar)) -- (7 - 11) atomSerial+ (string "ATOM " *> -- (1 - 5) ATOM -- we extended atomSerial length to the left for one symbol+ (read <$> count 6 notEndLineChar)) -- (6 - 11) atomSerial+ <|> -- or+ (string "HETATM" *> -- (1 - 6) HETATM+ (read <$> count 5 notEndLineChar)) -- (7 - 11) atomSerial ) <* space- <*> (T.pack <$> count 4 notEndLineChar) -- (13 - 16) atomName- <*> notEndLineChar -- (17) atomAltLoc- <*> (T.pack <$> count 3 notEndLineChar) <* space -- (18 - 20) atomResName- <*> notEndLineChar -- (22) atomChainID- <*> (read <$> count 4 notEndLineChar) -- (23 - 26) atomResSeq- <*> notEndLineChar <* count 3 space -- (27) atomICode- <*> (read <$> count 8 notEndLineChar) -- (31 - 38) atomX- <*> (read <$> count 8 notEndLineChar) -- (39 - 46) atomY- <*> (read <$> count 8 notEndLineChar) -- (47 - 54) atomZ- <*> (read <$> count 6 notEndLineChar) -- (55 - 60) atomOccupancy- <*> (read <$> count 6 notEndLineChar) <* count 10 space -- (61 - 66) atomTempFactor- <*> (T.pack <$> count 2 notEndLineChar) -- (77 - 78) atomElement- <*> (T.pack <$> count 2 notEndLineChar) -- (79 - 80) atomCharge+ <*> (T.pack <$> count 4 notEndLineChar) -- (13 - 16) atomName+ <*> notEndLineChar -- (17) atomAltLoc+ <*> (T.pack <$> count 3 notEndLineChar) <* space -- (18 - 20) atomResName+ <*> notEndLineChar -- (22) atomChainID+ <*> (read <$> count 4 notEndLineChar) -- (23 - 26) atomResSeq+ <*> notEndLineChar <* count 3 space -- (27) atomICode+ <*> (read <$> count 8 notEndLineChar) -- (31 - 38) atomX+ <*> (read <$> count 8 notEndLineChar) -- (39 - 46) atomY+ <*> (read <$> count 8 notEndLineChar) -- (47 - 54) atomZ+ <*> (read <$> count 6 notEndLineChar) -- (55 - 60) atomOccupancy+ <*> (read <$> count 6 notEndLineChar) <* count 10 anyChar -- (61 - 66) atomTempFactor+ <*> (T.pack <$> count 2 notEndLineChar) -- (77 - 78) atomElement+ <*> (T.pack <$> count 2 notEndLineChar) -- (79 - 80) atomCharge <* (endOfLine <|> endOfInput) in AtomLine <$> atom coordNotAtomP :: Parser CoordLike coordNotAtomP = do- _ <- string "TER " <|> string "ANISOU" <|> string "CONECT"+ _ <- string "TER" <|> string "ANISOU" <|> string "CONECT" skipWhile $ not . isEndOfLine endOfLine return CoordNotAtomLine@@ -112,7 +114,7 @@ AtomLine x -> Just x _ -> Nothing groupByChains :: [Atom]-> [[Atom]]- groupByChains = L.groupBy (\x y -> atomChainID x == atomChainID y)+ groupByChains = L.groupBy ((==) `on` atomChainID) modelP :: Parser Model modelP = do@@ -159,4 +161,4 @@ (fieldType :: Maybe FieldType) <- readMaybe <$> count 6 notEndLineChar fieldTypeText <- takeText endOfLine <|> endOfInput- return $ OtherFieldData (fieldType, T.stripEnd fieldTypeText)+ return $ OtherFieldData (fieldType, T.stripEnd fieldTypeText)
test/PDBParserSpec.hs view
@@ -429,6 +429,29 @@ (MASTER,V.fromList[" 1 2 3 4 5 6 7 8"])] } +withSegmentIdentifierModelSpecP :: Spec+withSegmentIdentifierModelSpecP = describe "PDB with segment identifier field." $+ it "correctly parses PDB with segment identifier field" $ do+ let mt = fromTextPDB . lenghtenLines $ T.pack ( + "ATOM 1 N VAL H 1 12.009 -20.902 2.468 0.00 0.00 H N \n" +++ "ATOM 2 CA VAL H 1 12.654 -20.252 1.326 0.00 0.00 H C \n" +++ "END\n"+ )+ mt `shouldBe` Right ([], withSegmentIdentifierModel)++withSegmentIdentifierModel :: PDB+withSegmentIdentifierModel = PDB { title = ""+ , remarks = Data.Map.Strict.empty+ , models = V.singleton $ V.fromList [ + V.fromList [+ Atom {atomSerial = 1, atomName = " N ", atomAltLoc = ' ', atomResName = "VAL", atomChainID = 'H', atomResSeq = 1, atomICode = ' ',+ atomX = 12.009, atomY = -20.902, atomZ = 2.468, atomOccupancy = 0.0, atomTempFactor = 0.0, atomElement = " N", atomCharge = " "},+ Atom {atomSerial = 2, atomName = " CA ", atomAltLoc = ' ', atomResName = "VAL", atomChainID = 'H', atomResSeq = 1, atomICode = ' ', + atomX = 12.654, atomY = -20.252, atomZ = 1.326, atomOccupancy = 0.0, atomTempFactor = 0.0, atomElement = " C", atomCharge = " "}+ ]] + , otherFields = Data.Map.Strict.empty+ }+ lenghtenLines :: Text -> Text lenghtenLines text = longLinedText where
test/Spec.hs view
@@ -58,6 +58,7 @@ rawPDBToModelConversionSingleChainSpec bondsRestoringTripeptideSpec bondsRestoringBiggerMoleculesSpec+ withSegmentIdentifierModelSpecP pdbWriterSpec -- Structure structureSpec