{-# 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 (Char -> String
forall a. Show a => a -> String
show Char
atomChainID) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
atomResSeq) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Char -> String
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 = [(Text, Vector (Bond LocalID))] -> Map Text (Vector (Bond LocalID))
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(Text, Vector (Bond LocalID))]
 -> Map Text (Vector (Bond LocalID)))
-> (Vector (Vector Atom) -> [(Text, Vector (Bond LocalID))])
-> Vector (Vector Atom)
-> Map Text (Vector (Bond LocalID))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Vector Atom -> [(Text, Vector (Bond LocalID))])
-> Vector (Vector Atom) -> [(Text, Vector (Bond LocalID))]
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 = [(Text, Vector (Bond LocalID))] -> Map Text (Vector (Bond LocalID))
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(Text, Vector (Bond LocalID))]
 -> Map Text (Vector (Bond LocalID)))
-> (Vector Atom -> [(Text, Vector (Bond LocalID))])
-> Vector Atom
-> Map Text (Vector (Bond LocalID))
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 GlobalID]
residueBonds) <- [[Atom]] -> [[Bond GlobalID]] -> [([Atom], [Bond GlobalID])]
forall a b. [a] -> [b] -> [(a, b)]
zip [[Atom]]
chainAtomsGroupedByResidue [[Bond GlobalID]]
intraResidueGlobalBonds
      let localBonds :: Vector (Bond LocalID)
localBonds = [Bond LocalID] -> Vector (Bond LocalID)
forall a. [a] -> Vector a
V.fromList ([Bond LocalID] -> Vector (Bond LocalID))
-> [Bond LocalID] -> Vector (Bond LocalID)
forall a b. (a -> b) -> a -> b
$ [Atom] -> [Bond GlobalID] -> [Bond LocalID]
convertGlobalsToLocals [Atom]
residueAtoms [Bond GlobalID]
residueBonds
      let _residueID :: Text
_residueID = Atom -> Text
residueID (Atom -> Text) -> Atom -> Text
forall a b. (a -> b) -> a -> b
$ [Atom] -> Atom
forall a. [a] -> a
head [Atom]
residueAtoms
      (Text, Vector (Bond LocalID)) -> [(Text, Vector (Bond LocalID))]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text
_residueID, Vector (Bond LocalID)
localBonds)
    
    intraResidueGlobalBonds :: [[Bond GlobalID]]
    intraResidueGlobalBonds :: [[Bond GlobalID]]
intraResidueGlobalBonds = ([Atom] -> [Bond GlobalID]) -> [[Atom]] -> [[Bond GlobalID]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Atom] -> [Bond GlobalID]
restoreIntraResidueBonds [[Atom]]
chainAtomsGroupedByResidue
    
    chainAtomsGroupedByResidue :: [[PDB.Atom]]
    chainAtomsGroupedByResidue :: [[Atom]]
chainAtomsGroupedByResidue = Vector Atom -> [[Atom]]
groupChainByResidue Vector Atom
chainAtoms
    
    convertGlobalsToLocals :: [PDB.Atom] -> [Bond GlobalID] -> [Bond LocalID]
    convertGlobalsToLocals :: [Atom] -> [Bond GlobalID] -> [Bond LocalID]
convertGlobalsToLocals [Atom]
residueAtoms = (Bond GlobalID -> Bond LocalID)
-> [Bond GlobalID] -> [Bond LocalID]
forall a b. (a -> b) -> [a] -> [b]
map Bond GlobalID -> Bond LocalID
convertGlobalToLocal
      where
        convertGlobalToLocal :: Bond GlobalID -> Bond LocalID
        convertGlobalToLocal :: Bond GlobalID -> Bond LocalID
convertGlobalToLocal (Bond (GlobalID Int
from) (GlobalID Int
to) Int
order) = 
          LocalID -> LocalID -> Int -> Bond LocalID
forall m. m -> m -> Int -> Bond m
Bond (Int -> LocalID
LocalID (Int -> LocalID) -> Int -> LocalID
forall a b. (a -> b) -> a -> b
$ Map Int Int
globalToLocalIdxMap Map Int Int -> Int -> Int
forall k a. Ord k => Map k a -> k -> a
! Int
from) (Int -> LocalID
LocalID (Int -> LocalID) -> Int -> LocalID
forall a b. (a -> b) -> a -> b
$ Map Int Int
globalToLocalIdxMap Map Int Int -> Int -> Int
forall k a. Ord k => Map k a -> k -> a
! Int
to) Int
order
        
        globalToLocalIdxMap :: Map Int Int
        globalToLocalIdxMap :: Map Int Int
globalToLocalIdxMap = [(Int, Int)] -> Map Int Int
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(Int, Int)] -> Map Int Int) -> [(Int, Int)] -> Map Int Int
forall a b. (a -> b) -> a -> b
$ [Int] -> [Int] -> [(Int, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int]
sortedGlobalIndices [Int
0..]
        
        sortedGlobalIndices :: [Int]
        sortedGlobalIndices :: [Int]
sortedGlobalIndices = (Atom -> Int) -> [Atom] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Atom -> Int
PDB.atomSerial ([Atom] -> [Int]) -> [Atom] -> [Int]
forall a b. (a -> b) -> a -> b
$ [Atom] -> [Atom]
forall a. Ord a => [a] -> [a]
sort [Atom]
residueAtoms


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

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

restoreDisulfideBonds :: [[PDB.Atom]] -> [Bond GlobalID]
restoreDisulfideBonds :: [[Atom]] -> [Bond GlobalID]
restoreDisulfideBonds [[Atom]]
atomsGroupedByResidue = do
  Atom
atom1 <- [Atom]
cystineSulfur
  Atom
atom2 <- [Atom]
cystineSulfur
  Bool -> [()]
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Atom -> Int
PDB.atomSerial Atom
atom1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Atom -> Int
PDB.atomSerial Atom
atom2)
  Bool -> [()]
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> [()]) -> Bool -> [()]
forall a b. (a -> b) -> a -> b
$ V3 Float -> V3 Float -> Float
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) Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
sulfidicBondMaxLength
  Bond GlobalID -> [Bond GlobalID]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bond GlobalID -> [Bond GlobalID])
-> Bond GlobalID -> [Bond GlobalID]
forall a b. (a -> b) -> a -> b
$ GlobalID -> GlobalID -> Int -> Bond GlobalID
forall m. m -> m -> Int -> Bond m
Bond (Int -> GlobalID
GlobalID (Int -> GlobalID) -> Int -> GlobalID
forall a b. (a -> b) -> a -> b
$ Atom -> Int
PDB.atomSerial Atom
atom1) (Int -> GlobalID
GlobalID (Int -> GlobalID) -> Int -> GlobalID
forall a b. (a -> b) -> a -> b
$ Atom -> Int
PDB.atomSerial Atom
atom2) Int
1
    where
      cystineSulfur :: [PDB.Atom]
      cystineSulfur :: [Atom]
cystineSulfur = (Atom -> Bool) -> [Atom] -> [Atom]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Text
"SG" Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
==) (Text -> Bool) -> (Atom -> Text) -> Atom -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.strip (Text -> Text) -> (Atom -> Text) -> Atom -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Atom -> Text
PDB.atomName) ([Atom] -> [Atom]) -> [Atom] -> [Atom]
forall a b. (a -> b) -> a -> b
$ [[Atom]] -> [Atom]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Atom]]
cystines
      cystines :: [[PDB.Atom]]
      cystines :: [[Atom]]
cystines = ([Atom] -> Bool) -> [[Atom]] -> [[Atom]]
forall a. (a -> Bool) -> [a] -> [a]
filter [Atom] -> Bool
cystinePredicate [[Atom]]
atomsGroupedByResidue
      cystinePredicate :: [PDB.Atom] -> Bool
      cystinePredicate :: [Atom] -> Bool
cystinePredicate [Atom]
residue = (Atom -> Bool) -> [Atom] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ((Text
"SG" Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
==) (Text -> Bool) -> (Atom -> Text) -> Atom -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.strip (Text -> Text) -> (Atom -> Text) -> Atom -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Atom -> Text
PDB.atomName) [Atom]
residue Bool -> Bool -> Bool
&& (Atom -> Bool) -> [Atom] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all ((Text
"HG" Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
/=) (Text -> Bool) -> (Atom -> Text) -> Atom -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.strip (Text -> Text) -> (Atom -> Text) -> Atom -> Text
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
..} = Float -> Float -> Float -> V3 Float
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 GlobalID]
restoreChainPeptideBonds :: [[Atom]] -> [Bond GlobalID]
restoreChainPeptideBonds [[Atom]]
atomsGroupedByResidue = [Maybe (Bond GlobalID)] -> [Bond GlobalID]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe (Bond GlobalID)] -> [Bond GlobalID])
-> [Maybe (Bond GlobalID)] -> [Bond GlobalID]
forall a b. (a -> b) -> a -> b
$ [[Atom]] -> [Maybe (Bond GlobalID)] -> [Maybe (Bond GlobalID)]
restoreChainPeptideBonds' [[Atom]]
atomsGroupedByResidue [Maybe (Bond GlobalID)]
forall a. Monoid a => a
mempty
  where
    restoreChainPeptideBonds' :: [[PDB.Atom]] -> [Maybe (Bond GlobalID)] -> [Maybe (Bond GlobalID)]
    restoreChainPeptideBonds' :: [[Atom]] -> [Maybe (Bond GlobalID)] -> [Maybe (Bond GlobalID)]
restoreChainPeptideBonds' [] [Maybe (Bond GlobalID)]
acc = [Maybe (Bond GlobalID)]
acc
    restoreChainPeptideBonds' [[Atom]
_] [Maybe (Bond GlobalID)]
acc = [Maybe (Bond GlobalID)]
acc
    restoreChainPeptideBonds' ([Atom]
residue1:[Atom]
residue2:[[Atom]]
residues) [Maybe (Bond GlobalID)]
acc = 
      [[Atom]] -> [Maybe (Bond GlobalID)] -> [Maybe (Bond GlobalID)]
restoreChainPeptideBonds' ([Atom]
residue2[Atom] -> [[Atom]] -> [[Atom]]
forall a. a -> [a] -> [a]
:[[Atom]]
residues) ([Atom] -> [Atom] -> Maybe (Bond GlobalID)
constructBond [Atom]
residue1 [Atom]
residue2 Maybe (Bond GlobalID)
-> [Maybe (Bond GlobalID)] -> [Maybe (Bond GlobalID)]
forall a. a -> [a] -> [a]
: [Maybe (Bond GlobalID)]
acc)

    constructBond :: [PDB.Atom] -> [PDB.Atom] -> Maybe (Bond GlobalID)
    constructBond :: [Atom] -> [Atom] -> Maybe (Bond GlobalID)
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)
        Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> Bool -> Maybe ()
forall a b. (a -> b) -> a -> b
$ V3 Float -> V3 Float -> Float
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) Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
peptideBondMaxLength

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


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

restoreIntraResidueBonds :: [PDB.Atom] -> [Bond GlobalID]
restoreIntraResidueBonds :: [Atom] -> [Bond GlobalID]
restoreIntraResidueBonds [Atom]
residueAtoms = [Maybe (Bond GlobalID)] -> [Bond GlobalID]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe (Bond GlobalID)] -> [Bond GlobalID])
-> [Maybe (Bond GlobalID)] -> [Bond GlobalID]
forall a b. (a -> b) -> a -> b
$ (Text, Text) -> Maybe (Bond GlobalID)
constructBond ((Text, Text) -> Maybe (Bond GlobalID))
-> [(Text, Text)] -> [Maybe (Bond GlobalID)]
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 GlobalID)
    constructBond :: (Text, Text) -> Maybe (Bond GlobalID)
constructBond (Text
fromAtomName, Text
toAtomName) = GlobalID -> GlobalID -> Int -> Bond GlobalID
forall m. m -> m -> Int -> Bond m
Bond (GlobalID -> GlobalID -> Int -> Bond GlobalID)
-> Maybe GlobalID -> Maybe (GlobalID -> Int -> Bond GlobalID)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Maybe GlobalID
constructGlobalID Text
fromAtomName Maybe (GlobalID -> Int -> Bond GlobalID)
-> Maybe GlobalID -> Maybe (Int -> Bond GlobalID)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Maybe GlobalID
constructGlobalID  Text
toAtomName Maybe (Int -> Bond GlobalID) -> Maybe Int -> Maybe (Bond GlobalID)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1
    
    constructGlobalID :: Text -> Maybe GlobalID
    constructGlobalID :: Text -> Maybe GlobalID
constructGlobalID Text
atomName = Int -> GlobalID
GlobalID (Int -> GlobalID) -> Maybe Int -> Maybe GlobalID
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Map Text Int
atomNameToIndex Map Text Int -> Text -> Maybe Int
forall k a. Ord k => Map k a -> k -> Maybe a
!? Text
atomName
    
    atomNameToIndex :: Map Text Int
    atomNameToIndex :: Map Text Int
atomNameToIndex = [(Text, Int)] -> Map Text Int
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(Text, Int)] -> Map Text Int) -> [(Text, Int)] -> Map Text Int
forall a b. (a -> b) -> a -> b
$ (\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, Int
atomSerial)) (Atom -> (Text, Int)) -> [Atom] -> [(Text, Int)]
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 (Text -> [(Text, Text)])
-> (Atom -> Text) -> Atom -> [(Text, Text)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.strip (Text -> Text) -> (Atom -> Text) -> Atom -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Atom -> Text
PDB.atomResName (Atom -> [(Text, Text)]) -> Atom -> [(Text, Text)]
forall a b. (a -> b) -> a -> b
$ [Atom] -> Atom
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 [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
forall a. [a] -> [a] -> [a]
++ Text -> [(Text, Text)]
caCbBonds Text
residueName [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
forall a. [a] -> [a] -> [a]
++ [(Text
"C",Text
"OXT"), (Text
"C",Text
"HXT")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
forall a. [a] -> [a] -> [a]
++ [(Text, [Text])] -> [(Text, Text)]
bwhMany [(Text
"CB", [Text
"HB3", Text
"HB2"]), (Text
"ND2", [Text
"HD22", Text
"HD21"])]
sideChainBonds Text
"ASP" = [(Text
"CB", Text
"CG"), (Text
"CG", Text
"OD1"), (Text
"CG", Text
"OD2")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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")] [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
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 = String -> [(Text, Text)]
forall a. HasCallStack => String -> a
error (String -> [(Text, Text)])
-> (Text -> String) -> Text -> [(Text, Text)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack (Text -> [(Text, Text)]) -> Text -> [(Text, Text)]
forall a b. (a -> b) -> a -> b
$ Text
"cobot-io: we don't know what to do with residue " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
unknownResidue

bwhMany :: [(Text, [Text])] -> [(Text, Text)]
bwhMany :: [(Text, [Text])] -> [(Text, Text)]
bwhMany = ((Text, [Text]) -> [(Text, Text)])
-> [(Text, [Text])] -> [(Text, Text)]
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,) (Text -> (Text, Text)) -> [Text] -> [(Text, Text)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Text]
hydrogenNames