module Biobase.Types.Structure where
import Control.DeepSeq
import Control.Lens
import Control.Monad.Error.Class
import Control.Monad (foldM,unless)
import Data.ByteString (ByteString)
import Data.Data
import Data.Set (Set)
import GHC.Generics (Generic)
import qualified Data.ByteString.Char8 as BS8
import qualified Data.List as L
import qualified Data.Set as Set
newtype RNAss = RNAss { _rnass ∷ ByteString }
deriving (Eq,Ord,Show,Read,Data,Typeable,Generic,Monoid)
makeLenses ''RNAss
instance NFData RNAss
newtype RNAensembleStructure = RNAes { _rnaes ∷ ByteString }
deriving (Eq,Ord,Show,Read,Data,Typeable,Generic)
makeLenses ''RNAensembleStructure
instance NFData RNAensembleStructure
data RNAds = RNAds
{ _rnadsL ∷ !ByteString
, _rnadsR ∷ !ByteString
}
deriving (Eq,Ord,Show,Read,Data,Typeable,Generic)
makeLenses ''RNAds
instance NFData RNAds
rnads ∷ Prism' ByteString RNAds
rnads = prism (\(RNAds l r) → BS8.concat [l, "&", r])
(\s → case BS8.split '&' s of [l,r] → Right (RNAds l r) ; _ → Left s)
rnads2rnassPair ∷ Iso' RNAds (RNAss, RNAss)
rnads2rnassPair = iso (\(RNAds l r) → (RNAss l, RNAss r)) (\(RNAss l, RNAss r) → RNAds l r)
mkRNAds ∷ (Monad m, MonadError RNAStructureError m) ⇒ ByteString → m RNAds
mkRNAds q = BS8.split '&' q & \case
[l,r] → do
return $ RNAds
{ _rnadsL = l
, _rnadsR = r
}
_ → throwError $ RNAStructureError "mkRNAds: not a dimer" q
data RNAStructureError = RNAStructureError
{ _rnaStructureError ∷ String
, _rnaOffender ∷ ByteString
}
deriving (Show,Generic)
instance NFData RNAStructureError
verifyRNAss ∷ (Monad m, MonadError RNAStructureError m) ⇒ RNAss → m RNAss
verifyRNAss ss = do
return ss
newtype RNApset = RNApset { _rnapset ∷ Set (Int,Int) }
deriving (Read,Show,Eq,Ord,Generic)
makeLenses ''RNApset
instance NFData RNApset
rnassPairSet
∷ (MonadError String m)
⇒ RNAss
→ m RNApset
rnassPairSet (RNAss s2) = do
let go (set,ks ) (i,'(') = return (set,i:ks)
go (set,i:is) (j,')') = return (Set.insert (i,j) set, is)
go (set,[] ) (j,')') = throwError $ "unequal brackets in \"" ++ BS8.unpack s2 ++ "\" at position: " ++ show j
go (set,ks ) (_,'.') = return (set,ks)
(set,ss) ← foldM go (Set.empty,[]) . L.zip [0..] $ BS8.unpack s2
unless (null ss) $ throwError $ "unequal brackets in \"" ++ BS8.unpack s2 ++ "\" with opening bracket(s): " ++ show ss
return $ RNApset set
rnassPairSet' ∷ RNAss → RNApset
rnassPairSet' = either error id . rnassPairSet
pairDist ∷ RNApset → RNApset → Int
pairDist (RNApset p1) (RNApset p2) = Set.size z1 + Set.size z2
where i = Set.intersection p1 p2
z1 = p1 `Set.difference` i
z2 = p2 `Set.difference` i