cobot-io-0.1.4.4: test/StructureSpec.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# OPTIONS_GHC -fno-warn-orphans -Wno-incomplete-uni-patterns #-}
module StructureSpec where
import Bio.MAE (fromFile)
import Bio.Structure (Atom (..), Bond (..), Chain (..),
LocalID (..), Model (..),
Residue (..), StructureModels (..))
import Bio.Structure.Functions (filterAtomsOfModel)
import Control.Monad (join)
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as M (fromList, (!))
import Data.Maybe (fromJust, isJust)
import Data.Set (Set)
import qualified Data.Set as S (fromList, member)
import Data.Vector (Vector)
import qualified Data.Vector as V (all, filter, find, fromList,
toList, zip)
import Test.Hspec
structureSpec :: Spec
structureSpec = describe "Structure spec." $ do
let mIO = fromFile "test/MAE/Capri.mae" >>= (\[x] -> pure x) . V.toList . modelsOf
beforeAll mIO $ do
it "atoms filtering works correctly. only N, CA, C" $ \m -> checkFiltering m $ (`elem` ["N", "CA", "C"]) . atomName
it "atoms filtering works correctly. only CA" $ \m -> checkFiltering m $ (== "CA") . atomName
it "atoms filtering works correctly. no atoms" $ \m -> checkFiltering m $ const False
it "atoms filtering works correctly. all atoms" $ \m -> checkFiltering m $ const True
where
checkFiltering :: Model -> (Atom -> Bool) -> Expectation
checkFiltering m p = do
checkAtoms
checkGlobalBonds
checkLocalBonds
where
m' = filterAtomsOfModel p m
checkAtoms :: Expectation
checkAtoms = V.all (V.all (V.all p . resAtoms) . chainResidues) (modelChains m') `shouldBe` True
checkGlobalBonds :: Expectation
checkGlobalBonds = all (\(Bond l r _) -> l `S.member` inds && r `S.member` inds) (modelBonds m') `shouldBe` True
where
filteredAtoms = join $ fmap (join . fmap (V.filter p . resAtoms) . chainResidues) $ modelChains m
inds = vecToSet $ fmap atomId filteredAtoms
checkLocalBonds :: Expectation
checkLocalBonds = all checkResiduePair pairsOfResidues `shouldBe` True
where
pairsOfResidues = zip (V.toList (join $ chainResidues <$> modelChains m))
(V.toList (join $ chainResidues <$> modelChains m'))
checkResiduePair :: (Residue, Residue) -> Bool
checkResiduePair (r, r') = vecToSet mappedBonds == vecToSet (resBonds r')
where
atInds = atomsWithIndices r
atInds' = atomsWithIndices r'
mappedBonds = fromJust <$> V.filter isJust (mapBond <$> resBonds r)
mapBond :: Bond LocalID -> Maybe (Bond LocalID)
mapBond (Bond l k t) = Bond <$> localMapping M.! l
<*> localMapping M.! k
<*> pure t
localMapping :: Map LocalID (Maybe LocalID)
localMapping = M.fromList $ V.toList forMap
where
forMap = fmap (\(a, i) -> (i, snd <$> V.find ((== atomId a) . atomId . fst) atInds')) atInds
atomsWithIndices :: Residue -> Vector (Atom, LocalID)
atomsWithIndices Residue{..} = V.zip resAtoms $ fmap LocalID $ V.fromList [0 ..]
vecToSet :: Ord a => Vector a -> Set a
vecToSet = S.fromList . V.toList