{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TupleSections #-}

module Bio.PDB.BondRestoring
  ( restoreModelGlobalBonds
  , restoreModelLocalBonds
  , restoreChainLocalBonds
  , residueID
  ) where

import qualified Bio.PDB.Type as PDB  (Atom(..))
import           Bio.PDB.Functions    (groupChainByResidue)
import           Bio.Structure        (Bond (..), GlobalID (..), LocalID (..))

import           Data.Vector          (Vector)
import qualified Data.Vector as V     (fromList, toList)
import           Data.List            (find, sort)
import           Data.Text            (Text)
import qualified Data.Text as T       (strip, pack, unpack)
import           Data.Map.Strict      (Map, (!?), (!))
import qualified Data.Map.Strict as M (fromList)
import           Data.Maybe           (catMaybes)

import           Linear.Metric        (distance)
import           Linear.V3            (V3(..))

import           Control.Monad        (guard)

residueID :: PDB.Atom -> Text
residueID :: Atom -> Text
residueID PDB.Atom{Char
Float
Int
Text
atomCharge :: Atom -> Text
atomElement :: Atom -> Text
atomTempFactor :: Atom -> Float
atomOccupancy :: Atom -> Float
atomZ :: Atom -> Float
atomY :: Atom -> Float
atomX :: Atom -> Float
atomICode :: Atom -> Char
atomResSeq :: Atom -> Int
atomChainID :: Atom -> Char
atomResName :: Atom -> Text
atomAltLoc :: Atom -> Char
atomName :: Atom -> Text
atomSerial :: Atom -> Int
atomCharge :: Text
atomElement :: Text
atomTempFactor :: Float
atomOccupancy :: Float
atomZ :: Float
atomY :: Float
atomX :: Float
atomICode :: Char
atomResSeq :: Int
atomChainID :: Char
atomResName :: Text
atomAltLoc :: Char
atomName :: Text
atomSerial :: Int
..} = String -> Text
T.pack (forall a. Show a => a -> String
show Char
atomChainID) forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (forall a. Show a => a -> String
show Int
atomResSeq) forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (forall a. Show a => a -> String
show Char
atomICode)

restoreModelLocalBonds :: Vector (Vector PDB.Atom) -> Map Text (Vector (Bond LocalID))
restoreModelLocalBonds :: Vector (Vector Atom) -> Map Text (Vector (Bond LocalID))
restoreModelLocalBonds = forall k a. Ord k => [(k, a)] -> Map k a
M.fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Vector Atom -> [(Text, Vector (Bond LocalID))]
restoreChainLocalBonds'

restoreChainLocalBonds :: Vector PDB.Atom -> Map Text (Vector (Bond LocalID))
restoreChainLocalBonds :: Vector Atom -> Map Text (Vector (Bond LocalID))
restoreChainLocalBonds = forall k a. Ord k => [(k, a)] -> Map k a
M.fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Atom -> [(Text, Vector (Bond LocalID))]
restoreChainLocalBonds'

restoreChainLocalBonds' :: Vector PDB.Atom -> [(Text, Vector (Bond LocalID))]
restoreChainLocalBonds' :: Vector Atom -> [(Text, Vector (Bond LocalID))]
restoreChainLocalBonds' Vector Atom
chainAtoms = [(Text, Vector (Bond LocalID))]
residueIDToLocalBonds
  where
    residueIDToLocalBonds :: [(Text, Vector (Bond LocalID))]
    residueIDToLocalBonds :: [(Text, Vector (Bond LocalID))]
residueIDToLocalBonds = do
      ([Atom]
residueAtoms, [Bond Atom]
residueBonds) <- forall a b. [a] -> [b] -> [(a, b)]
zip [[Atom]]
chainAtomsGroupedByResidue [[Bond Atom]]
intraResidueGlobalBonds
      let localBonds :: Vector (Bond LocalID)
localBonds = forall a. [a] -> Vector a
V.fromList forall a b. (a -> b) -> a -> b
$ [Atom] -> [Bond Atom] -> [Bond LocalID]
convertGlobalsToLocals [Atom]
residueAtoms [Bond Atom]
residueBonds
      let _residueID :: Text
_residueID = Atom -> Text
residueID forall a b. (a -> b) -> a -> b
$ forall a. [a] -> a
head [Atom]
residueAtoms
      forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text
_residueID, Vector (Bond LocalID)
localBonds)
    
    intraResidueGlobalBonds :: [[Bond PDB.Atom]]
    intraResidueGlobalBonds :: [[Bond Atom]]
intraResidueGlobalBonds = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Atom] -> [Bond Atom]
restoreIntraResidueBonds [[Atom]]
chainAtomsGroupedByResidue
    
    chainAtomsGroupedByResidue :: [[PDB.Atom]]
    chainAtomsGroupedByResidue :: [[Atom]]
chainAtomsGroupedByResidue = Vector Atom -> [[Atom]]
groupChainByResidue Vector Atom
chainAtoms
    
    convertGlobalsToLocals :: [PDB.Atom] -> [Bond PDB.Atom] -> [Bond LocalID]
    convertGlobalsToLocals :: [Atom] -> [Bond Atom] -> [Bond LocalID]
convertGlobalsToLocals [Atom]
residueAtoms = forall a b. (a -> b) -> [a] -> [b]
map Bond Atom -> Bond LocalID
convertGlobalToLocal
      where
        convertGlobalToLocal :: Bond PDB.Atom -> Bond LocalID
        convertGlobalToLocal :: Bond Atom -> Bond LocalID
convertGlobalToLocal (Bond Atom
from Atom
to Int
order) = 
          forall m. m -> m -> Int -> Bond m
Bond (Int -> LocalID
LocalID forall a b. (a -> b) -> a -> b
$ Map Atom Int
atomToLocalIdMap forall k a. Ord k => Map k a -> k -> a
! Atom
from) (Int -> LocalID
LocalID forall a b. (a -> b) -> a -> b
$ Map Atom Int
atomToLocalIdMap forall k a. Ord k => Map k a -> k -> a
! Atom
to) Int
order
        
        atomToLocalIdMap :: Map PDB.Atom Int
        atomToLocalIdMap :: Map Atom Int
atomToLocalIdMap = forall k a. Ord k => [(k, a)] -> Map k a
M.fromList forall a b. (a -> b) -> a -> b
$ forall a b. [a] -> [b] -> [(a, b)]
zip [Atom]
sortedAtoms [Int
0..]
        
        sortedAtoms :: [PDB.Atom]
        sortedAtoms :: [Atom]
sortedAtoms = forall a. Ord a => [a] -> [a]
sort [Atom]
residueAtoms


restoreModelGlobalBonds :: Map PDB.Atom Int -> Vector (Vector PDB.Atom) -> Vector (Bond GlobalID)
restoreModelGlobalBonds :: Map Atom Int -> Vector (Vector Atom) -> Vector (Bond GlobalID)
restoreModelGlobalBonds Map Atom Int
atomToNilBasedIndex Vector (Vector Atom)
chains = Map Atom Int -> Vector (Bond Atom) -> Vector (Bond GlobalID)
convertToGlobalIDs Map Atom Int
atomToNilBasedIndex forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> Vector a
V.fromList forall a b. (a -> b) -> a -> b
$ [Bond Atom]
_intraResidueBonds forall a. [a] -> [a] -> [a]
++ [Bond Atom]
peptideBonds forall a. [a] -> [a] -> [a]
++ [Bond Atom]
disulfideBonds
  where
    convertToGlobalIDs :: Map PDB.Atom Int -> Vector (Bond PDB.Atom) -> Vector (Bond GlobalID)
    convertToGlobalIDs :: Map Atom Int -> Vector (Bond Atom) -> Vector (Bond GlobalID)
convertToGlobalIDs Map Atom Int
mapping = forall a b. (a -> b) -> Vector (Bond a) -> Vector (Bond b)
reindexBonds (\Atom
atom -> Int -> GlobalID
GlobalID forall a b. (a -> b) -> a -> b
$ Map Atom Int
mapping forall k a. Ord k => Map k a -> k -> a
! Atom
atom)
    
    reindexBonds :: (a -> b) -> Vector (Bond a) -> Vector (Bond b)
    reindexBonds :: forall a b. (a -> b) -> Vector (Bond a) -> Vector (Bond b)
reindexBonds a -> b
convertID = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Bond a
from a
to Int
order) -> forall m. m -> m -> Int -> Bond m
Bond (a -> b
convertID a
from) (a -> b
convertID a
to) Int
order)

    chainAtomsGroupedByResidue :: Vector [[PDB.Atom]]
    chainAtomsGroupedByResidue :: Vector [[Atom]]
chainAtomsGroupedByResidue = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Vector Atom -> [[Atom]]
groupChainByResidue Vector (Vector Atom)
chains
    
    _intraResidueBonds :: [Bond PDB.Atom]
    _intraResidueBonds :: [Bond Atom]
_intraResidueBonds = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap [[Atom]] -> [Bond Atom]
restoreChainIntraResidueBonds Vector [[Atom]]
chainAtomsGroupedByResidue
    
    peptideBonds :: [Bond PDB.Atom]
    peptideBonds :: [Bond Atom]
peptideBonds = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap [[Atom]] -> [Bond Atom]
restoreChainPeptideBonds Vector [[Atom]]
chainAtomsGroupedByResidue
    
    disulfideBonds :: [Bond PDB.Atom]
    disulfideBonds :: [Bond Atom]
disulfideBonds = [[Atom]] -> [Bond Atom]
restoreDisulfideBonds forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat forall a b. (a -> b) -> a -> b
$ forall a. Vector a -> [a]
V.toList Vector [[Atom]]
chainAtomsGroupedByResidue

restoreDisulfideBonds :: [[PDB.Atom]] -> [Bond PDB.Atom]
restoreDisulfideBonds :: [[Atom]] -> [Bond Atom]
restoreDisulfideBonds [[Atom]]
atomsGroupedByResidue = do
  Atom
atom1 <- [Atom]
cystineSulfur
  Atom
atom2 <- [Atom]
cystineSulfur
  forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Atom -> Int
PDB.atomSerial Atom
atom1 forall a. Ord a => a -> a -> Bool
< Atom -> Int
PDB.atomSerial Atom
atom2)
  forall (f :: * -> *). Alternative f => Bool -> f ()
guard forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. (Metric f, Floating a) => f a -> f a -> a
distance (Atom -> V3 Float
coords Atom
atom1) (Atom -> V3 Float
coords Atom
atom2) forall a. Ord a => a -> a -> Bool
< Float
sulfidicBondMaxLength
  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall m. m -> m -> Int -> Bond m
Bond Atom
atom1 Atom
atom2 Int
1
    where
      cystineSulfur :: [PDB.Atom]
      cystineSulfur :: [Atom]
cystineSulfur = forall a. (a -> Bool) -> [a] -> [a]
filter ((Text
"SG" forall a. Eq a => a -> a -> Bool
==) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.strip forall b c a. (b -> c) -> (a -> b) -> a -> c
. Atom -> Text
PDB.atomName) forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Atom]]
cystines
      cystines :: [[PDB.Atom]]
      cystines :: [[Atom]]
cystines = forall a. (a -> Bool) -> [a] -> [a]
filter [Atom] -> Bool
cystinePredicate [[Atom]]
atomsGroupedByResidue
      cystinePredicate :: [PDB.Atom] -> Bool
      cystinePredicate :: [Atom] -> Bool
cystinePredicate [Atom]
residue = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ((Text
"SG" forall a. Eq a => a -> a -> Bool
==) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.strip forall b c a. (b -> c) -> (a -> b) -> a -> c
. Atom -> Text
PDB.atomName) [Atom]
residue Bool -> Bool -> Bool
&& forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all ((Text
"HG" forall a. Eq a => a -> a -> Bool
/=) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.strip forall b c a. (b -> c) -> (a -> b) -> a -> c
. Atom -> Text
PDB.atomName) [Atom]
residue

coords :: PDB.Atom -> V3 Float
coords :: Atom -> V3 Float
coords PDB.Atom{Char
Float
Int
Text
atomCharge :: Text
atomElement :: Text
atomTempFactor :: Float
atomOccupancy :: Float
atomZ :: Float
atomY :: Float
atomX :: Float
atomICode :: Char
atomResSeq :: Int
atomChainID :: Char
atomResName :: Text
atomAltLoc :: Char
atomName :: Text
atomSerial :: Int
atomCharge :: Atom -> Text
atomElement :: Atom -> Text
atomTempFactor :: Atom -> Float
atomOccupancy :: Atom -> Float
atomZ :: Atom -> Float
atomY :: Atom -> Float
atomX :: Atom -> Float
atomICode :: Atom -> Char
atomResSeq :: Atom -> Int
atomChainID :: Atom -> Char
atomResName :: Atom -> Text
atomAltLoc :: Atom -> Char
atomName :: Atom -> Text
atomSerial :: Atom -> Int
..} = forall a. a -> a -> a -> V3 a
V3 Float
atomX Float
atomY Float
atomZ

sulfidicBondMaxLength :: Float
sulfidicBondMaxLength :: Float
sulfidicBondMaxLength = Float
2.56

peptideBondMaxLength :: Float
peptideBondMaxLength :: Float
peptideBondMaxLength = Float
1.5

restoreChainPeptideBonds :: [[PDB.Atom]] -> [Bond PDB.Atom]
restoreChainPeptideBonds :: [[Atom]] -> [Bond Atom]
restoreChainPeptideBonds [[Atom]]
atomsGroupedByResidue = forall a. [Maybe a] -> [a]
catMaybes forall a b. (a -> b) -> a -> b
$ [[Atom]] -> [Maybe (Bond Atom)] -> [Maybe (Bond Atom)]
restoreChainPeptideBonds' [[Atom]]
atomsGroupedByResidue forall a. Monoid a => a
mempty
  where
    restoreChainPeptideBonds' :: [[PDB.Atom]] -> [Maybe (Bond PDB.Atom)] -> [Maybe (Bond PDB.Atom)]
    restoreChainPeptideBonds' :: [[Atom]] -> [Maybe (Bond Atom)] -> [Maybe (Bond Atom)]
restoreChainPeptideBonds' [] [Maybe (Bond Atom)]
acc = [Maybe (Bond Atom)]
acc
    restoreChainPeptideBonds' [[Atom]
_] [Maybe (Bond Atom)]
acc = [Maybe (Bond Atom)]
acc
    restoreChainPeptideBonds' ([Atom]
residue1:[Atom]
residue2:[[Atom]]
residues) [Maybe (Bond Atom)]
acc = 
      [[Atom]] -> [Maybe (Bond Atom)] -> [Maybe (Bond Atom)]
restoreChainPeptideBonds' ([Atom]
residue2forall a. a -> [a] -> [a]
:[[Atom]]
residues) ([Atom] -> [Atom] -> Maybe (Bond Atom)
constructBond [Atom]
residue1 [Atom]
residue2 forall a. a -> [a] -> [a]
: [Maybe (Bond Atom)]
acc)

    constructBond :: [PDB.Atom] -> [PDB.Atom] -> Maybe (Bond PDB.Atom)
    constructBond :: [Atom] -> [Atom] -> Maybe (Bond Atom)
constructBond [Atom]
residue1 [Atom]
residue2 = do
        Atom
carbonAtom1   <- [Atom] -> Text -> Maybe Atom
getAtomByName [Atom]
residue1 Text
"C"
        Atom
nitrogenAtom2 <- [Atom] -> Text -> Maybe Atom
getAtomByName [Atom]
residue2 Text
"N"

        -- check if the atoms are close enough
        -- in order not to restore a wrong peptide bond in case of absent residues (gaps)
        forall (f :: * -> *). Alternative f => Bool -> f ()
guard forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. (Metric f, Floating a) => f a -> f a -> a
distance (Atom -> V3 Float
coords Atom
carbonAtom1) (Atom -> V3 Float
coords Atom
nitrogenAtom2) forall a. Ord a => a -> a -> Bool
< Float
peptideBondMaxLength

        forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall m. m -> m -> Int -> Bond m
Bond Atom
carbonAtom1 Atom
nitrogenAtom2 Int
1
    
    getAtomByName :: [PDB.Atom] -> Text -> Maybe PDB.Atom
    getAtomByName :: [Atom] -> Text -> Maybe Atom
getAtomByName [Atom]
atoms Text
atomNameToFind = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((Text
atomNameToFind forall a. Eq a => a -> a -> Bool
==) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.strip forall b c a. (b -> c) -> (a -> b) -> a -> c
. Atom -> Text
PDB.atomName) [Atom]
atoms

restoreChainIntraResidueBonds :: [[PDB.Atom]] -> [Bond PDB.Atom]
restoreChainIntraResidueBonds :: [[Atom]] -> [Bond Atom]
restoreChainIntraResidueBonds = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap [Atom] -> [Bond Atom]
restoreIntraResidueBonds

restoreIntraResidueBonds :: [PDB.Atom] -> [Bond PDB.Atom]
restoreIntraResidueBonds :: [Atom] -> [Bond Atom]
restoreIntraResidueBonds [Atom]
residueAtoms = forall a. [Maybe a] -> [a]
catMaybes forall a b. (a -> b) -> a -> b
$ (Text, Text) -> Maybe (Bond Atom)
constructBond forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(Text, Text)]
residueBonds
  where
    -- TODO: support bond order somehow
    constructBond :: (Text, Text) -> Maybe (Bond PDB.Atom)
    constructBond :: (Text, Text) -> Maybe (Bond Atom)
constructBond (Text
fromAtomName, Text
toAtomName) = forall m. m -> m -> Int -> Bond m
Bond forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Maybe Atom
constructAtom Text
fromAtomName forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Maybe Atom
constructAtom Text
toAtomName forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. a -> Maybe a
Just Int
1
    
    constructAtom :: Text -> Maybe PDB.Atom
    constructAtom :: Text -> Maybe Atom
constructAtom Text
atomName = Map Text Atom
atomNameToAtom forall k a. Ord k => Map k a -> k -> Maybe a
!? Text
atomName
    
    atomNameToAtom :: Map Text PDB.Atom
    atomNameToAtom :: Map Text Atom
atomNameToAtom = forall k a. Ord k => [(k, a)] -> Map k a
M.fromList forall a b. (a -> b) -> a -> b
$ (\atom :: Atom
atom@PDB.Atom{Char
Float
Int
Text
atomCharge :: Text
atomElement :: Text
atomTempFactor :: Float
atomOccupancy :: Float
atomZ :: Float
atomY :: Float
atomX :: Float
atomICode :: Char
atomResSeq :: Int
atomChainID :: Char
atomResName :: Text
atomAltLoc :: Char
atomName :: Text
atomSerial :: Int
atomCharge :: Atom -> Text
atomElement :: Atom -> Text
atomTempFactor :: Atom -> Float
atomOccupancy :: Atom -> Float
atomZ :: Atom -> Float
atomY :: Atom -> Float
atomX :: Atom -> Float
atomICode :: Atom -> Char
atomResSeq :: Atom -> Int
atomChainID :: Atom -> Char
atomResName :: Atom -> Text
atomAltLoc :: Atom -> Char
atomName :: Atom -> Text
atomSerial :: Atom -> Int
..} -> (Text -> Text
T.strip Text
atomName, Atom
atom)) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Atom]
residueAtoms
    
    residueBonds :: [(Text, Text)]
    residueBonds :: [(Text, Text)]
residueBonds = Text -> [(Text, Text)]
intraResidueBonds forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.strip forall b c a. (b -> c) -> (a -> b) -> a -> c
. Atom -> Text
PDB.atomResName forall a b. (a -> b) -> a -> b
$ forall a. [a] -> a
head [Atom]
residueAtoms

intraResidueBonds :: Text -> [(Text, Text)]
intraResidueBonds :: Text -> [(Text, Text)]
intraResidueBonds Text
"NMA" = [(Text
"CA", Text
"N")]
intraResidueBonds Text
"ACE" = [(Text
"C", Text
"O"), (Text
"C", Text
"CH3")]
intraResidueBonds Text
residueName = [(Text, Text)]
backboneBonds forall a. [a] -> [a] -> [a]
++ Text -> [(Text, Text)]
caCbBonds Text
residueName forall a. [a] -> [a] -> [a]
++ Text -> [(Text, Text)]
sideChainBonds Text
residueName

backboneBonds :: [(Text, Text)]
backboneBonds :: [(Text, Text)]
backboneBonds = [(Text
"N", Text
"CA"), (Text
"CA", Text
"C"), (Text
"C", Text
"O"), (Text
"N", Text
"H")] forall a. [a] -> [a] -> [a]
++ [(Text
"C",Text
"OXT"), (Text
"C",Text
"HXT")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"N", [Text
"H1", Text
"H2", Text
"H3"])]

caCbBonds :: Text -> [(Text, Text)]
caCbBonds :: Text -> [(Text, Text)]
caCbBonds Text
aminoacid = case Text
aminoacid of
  Text
"GLY" -> [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CA", [Text
"HA1", Text
"HA2", Text
"HA3"])]
  Text
_     -> [(Text
"CA", Text
"CB"), (Text
"CA", Text
"HA"), (Text
"CA", Text
"HA1"), (Text
"CA", Text
"HA2"), (Text
"CA", Text
"HA3")]

sideChainBonds :: Text -> [(Text, Text)]
sideChainBonds :: Text -> [(Text, Text)]
sideChainBonds Text
"ALA" = [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB1", Text
"HB2", Text
"HB3"])]
sideChainBonds Text
"ARG" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"CD"), (Text
"CD", Text
"NE"), (Text
"NE", Text
"CZ"), (Text
"CZ", Text
"NH2"), (Text
"CZ", Text
"NH1")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany[(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"CG", [Text
"HG3", Text
"HG2"]), (Text
"CD", [Text
"HD3", Text
"HD2"]), (Text
"NE", [Text
"HE"]), (Text
"NH1", [Text
"HH12", Text
"HH11"]), (Text
"NH2", [Text
"HH22", Text
"HH21"])]
sideChainBonds Text
"ASN" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"OD1"), (Text
"CG", Text
"ND2")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"ND2", [Text
"HD22", Text
"HD21"]), (Text
"ND2", [Text
"HD2", Text
"HD1"])]
sideChainBonds Text
"ASP" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"OD1"), (Text
"CG", Text
"OD2")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"OD2", [Text
"HD2"])] -- in fact, these are bonds for ASH, but sometimes ASH called just ASP...
sideChainBonds Text
"ASH" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"OD1"), (Text
"CG", Text
"OD2")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"OD2", [Text
"HD2"])]
sideChainBonds Text
"CYS" = [(Text
"CB", Text
"SG")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"SG", [Text
"HG"])]
sideChainBonds Text
"CYX" = [(Text
"CB", Text
"SG")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"SG", [Text
"HG"])]
sideChainBonds Text
"GLN" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"CD"), (Text
"CD", Text
"OE1"), (Text
"CD", Text
"NE2")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"CG", [Text
"HG3", Text
"HG2"]), (Text
"NE2", [Text
"HE22", Text
"HE21"])]
sideChainBonds Text
"GLU" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"CD"), (Text
"CD", Text
"OE1"), (Text
"CD", Text
"OE2")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB1", Text
"HB2", Text
"HB3"]), (Text
"CG", [Text
"HG3", Text
"HG2"]), (Text
"OE2", [Text
"HE2"])] -- in fact, these are bonds for GLH, but sometimes GLH called just GLU...
sideChainBonds Text
"GLH" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"CD"), (Text
"CD", Text
"OE1"), (Text
"CD", Text
"OE2")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB1", Text
"HB2", Text
"HB3"]), (Text
"CG", [Text
"HG3", Text
"HG2"]), (Text
"OE2", [Text
"HE2"])]
sideChainBonds Text
"GLY" = [] -- nothing
sideChainBonds Text
"HID" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"ND1"), (Text
"ND1", Text
"CE1"), (Text
"CE1", Text
"NE2"), (Text
"NE2", Text
"CD2"), (Text
"CD2", Text
"CG")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"ND1", [Text
"HD1"]), (Text
"CE1", [Text
"HE1"]), (Text
"CD2", [Text
"HD2"]), (Text
"CD2", [Text
"HD2"])] -- in fact, these are bonds for HIP, but residue names in PDB is a mess...
sideChainBonds Text
"HIE" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"ND1"), (Text
"ND1", Text
"CE1"), (Text
"CE1", Text
"NE2"), (Text
"NE2", Text
"CD2"), (Text
"CD2", Text
"CG")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"CE1", [Text
"HE1"]), (Text
"NE2", [Text
"HE2"]), (Text
"CD2", [Text
"HD2"]), (Text
"CD2", [Text
"HD2"])] -- in fact, these are bonds for HIP, but residue names in PDB is a mess...
sideChainBonds Text
"HIP" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"ND1"), (Text
"ND1", Text
"CE1"), (Text
"CE1", Text
"NE2"), (Text
"NE2", Text
"CD2"), (Text
"CD2", Text
"CG")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"ND1", [Text
"HD1"]), (Text
"CE1", [Text
"HE1"]), (Text
"NE2", [Text
"HE2"]), (Text
"CD2", [Text
"HD2"])] -- in fact, these are bonds for HIP, but residue names in PDB is a mess...
sideChainBonds Text
"HIS" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"ND1"), (Text
"ND1", Text
"CE1"), (Text
"CE1", Text
"NE2"), (Text
"NE2", Text
"CD2"), (Text
"CD2", Text
"CG")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"ND1", [Text
"HD1"]), (Text
"CE1", [Text
"HE1"]), (Text
"NE2", [Text
"HE2"]), (Text
"CD2", [Text
"HD2"])] -- this covers all possible histidines with 'HIS' name
sideChainBonds Text
"ILE" = [(Text
"CB", Text
"CG1"), (Text
"CB", Text
"CG2"), (Text
"CG1", Text
"CD1")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB", Text
"HB2", Text
"HB3"]), (Text
"CG1", [Text
"HG13", Text
"HG12"]), (Text
"CG2", [Text
"HG21", Text
"HG22", Text
"HG23"]), (Text
"CD1", [Text
"HD11", Text
"HD12", Text
"HD13"])]
sideChainBonds Text
"LEU" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"CD1"), (Text
"CG", Text
"CD2")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"CG", [Text
"HG", Text
"HG2"]), (Text
"CD1", [Text
"HD11", Text
"HD12", Text
"HD13"]), (Text
"CD2", [Text
"HD21", Text
"HD22", Text
"HD23"])]
sideChainBonds Text
"LYS" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"CD"), (Text
"CD", Text
"CE"), (Text
"CE", Text
"NZ")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB1", Text
"HB2", Text
"HB3"]), (Text
"CG", [Text
"HG1", Text
"HG2", Text
"HG3"]), (Text
"CD", [Text
"HD3", Text
"HD2"]), (Text
"CE", [Text
"HE3", Text
"HE2"]), (Text
"NZ", [Text
"HZ1", Text
"HZ2", Text
"HZ3"])]
sideChainBonds Text
"MET" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"SD"), (Text
"SD", Text
"CE")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"CG", [Text
"HG3", Text
"HG2"]), (Text
"CE", [Text
"HE1", Text
"HE2", Text
"HE3"])]
sideChainBonds Text
"PHE" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"CD1"), (Text
"CD1", Text
"CE1"), (Text
"CE1", Text
"CZ"), (Text
"CZ", Text
"CE2"), (Text
"CE2", Text
"CD2"), (Text
"CD2", Text
"CG")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"CD1", [Text
"HD1"]), (Text
"CE1", [Text
"HE1"]), (Text
"CZ", [Text
"HZ"]), (Text
"CE2", [Text
"HE2"]), (Text
"CD2", [Text
"HD2"])]
sideChainBonds Text
"PRO" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"CD"), (Text
"CD", Text
"N")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB1", Text
"HB2", Text
"HB3"]), (Text
"CG", [Text
"HG3", Text
"HG2"]), (Text
"CD", [Text
"HD2", Text
"HD3"])]
sideChainBonds Text
"SER" = [(Text
"CB", Text
"OG")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2", Text
"HB1"]), (Text
"OG", [Text
"HG"])]
sideChainBonds Text
"THR" = [(Text
"CB", Text
"OG1"), (Text
"CB", Text
"CG2")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB", Text
"HB3"]), (Text
"OG1", [Text
"HG1"]), (Text
"CG2", [Text
"HG21", Text
"HG22", Text
"HG23"])]
sideChainBonds Text
"TRP" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"CD1"), (Text
"CD1", Text
"NE1"), (Text
"NE1", Text
"CE2"), (Text
"CE2", Text
"CD2"), (Text
"CD2", Text
"CG"), (Text
"CD2", Text
"CE3"), (Text
"CE3", Text
"CZ3"), (Text
"CZ3", Text
"CH2"), (Text
"CH2", Text
"CZ2"), (Text
"CZ2", Text
"CE2")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"CD1", [Text
"HD1"]), (Text
"NE1", [Text
"HE1"]), (Text
"CE3", [Text
"HE3"]), (Text
"CZ3", [Text
"HZ3"]), (Text
"CH2", [Text
"HH2"]), (Text
"CZ2", [Text
"HZ2"])]
sideChainBonds Text
"TYR" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"CD1"), (Text
"CD1", Text
"CE1"), (Text
"CE1", Text
"CZ"), (Text
"CZ", Text
"CE2"), (Text
"CE2", Text
"CD2"), (Text
"CD2", Text
"CG"), (Text
"CZ", Text
"OH")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"CD1", [Text
"HD1"]), (Text
"CE1", [Text
"HE1"]), (Text
"CE2", [Text
"HE2"]), (Text
"CD2", [Text
"HD2"]), (Text
"OH", [Text
"HH"])]
sideChainBonds Text
"VAL" = [(Text
"CB", Text
"CG1"), (Text
"CB", Text
"CG2")] forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB", Text
"HB3"]), (Text
"CG1", [Text
"HG11", Text
"HG12", Text
"HG13"]), (Text
"CG2", [Text
"HG21", Text
"HG22", Text
"HG23"])]
sideChainBonds Text
unknownResidue = forall a. HasCallStack => String -> a
error forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack forall a b. (a -> b) -> a -> b
$ Text
"cobot-io: we don't know what to do with residue " forall a. Semigroup a => a -> a -> a
<> Text
unknownResidue

bwhMany :: [(Text, [Text])] -> [(Text, Text)]
bwhMany :: [(Text, [Text])] -> [(Text, Text)]
bwhMany = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Text, [Text]) -> [(Text, Text)]
bwh

bwh :: (Text, [Text]) -> [(Text, Text)]
bwh :: (Text, [Text]) -> [(Text, Text)]
bwh = (Text, [Text]) -> [(Text, Text)]
heavyAtomBondsWithHydrogens

heavyAtomBondsWithHydrogens :: (Text, [Text]) -> [(Text, Text)]
heavyAtomBondsWithHydrogens :: (Text, [Text]) -> [(Text, Text)]
heavyAtomBondsWithHydrogens (Text
heavyAtomName, [Text]
hydrogenNames) = (Text
heavyAtomName,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Text]
hydrogenNames