packages feed

ViennaRNA-bindings-0.233.2.0: BioInf/ViennaRNA/Bindings/FFI/CoFold.chs

module BioInf.ViennaRNA.Bindings.FFI.CoFold
  ( ffiCoFold
  , ffiCoEnergyOfStructure
  , ffiCoPartitionFunction
  , ffiCoPartitionConstrained
  , CofoldF (..)
  ) where

import           Control.Applicative
import           Control.Monad
import           Data.ByteString.Char8 (ByteString, useAsCString, packCString)
import           Foreign.C.String
import           Foreign.C.Types
import           Foreign.Marshal.Alloc
import           Foreign.Marshal.Array
import           Foreign.Ptr
import           Foreign.Storable
import           GHC.Float
import qualified Data.Array.IArray as A
import qualified Data.ByteString.Char8 as BS
import           Unsafe.Coerce

import           BioInf.ViennaRNA.Bindings.FFI.Utils



#include "ViennaRNA/cofold.h"
#include "ViennaRNA/data_structures.h"
#include "ViennaRNA/fold.h"
#include "ViennaRNA/part_func_co.h"

{#pointer *cofoldF as CofoldFPtr -> CofoldF #}

data CofoldF = CofoldF
  { f0ab :: {-# UNPACK #-} !Double
  , fab  :: {-# UNPACK #-} !Double
  , fcab :: {-# UNPACK #-} !Double
  , fa   :: {-# UNPACK #-} !Double
  , fb   :: {-# UNPACK #-} !Double
  }
  deriving (Show)

instance Storable CofoldF where
  sizeOf _ = {#sizeof cofoldF#}
  alignment _ = sizeOf (undefined :: CDouble)
  peek p = CofoldF <$> liftM realToFrac ({# get cofoldF->F0AB #} p)
                   <*> liftM realToFrac ({# get cofoldF->FAB  #} p)
                   <*> liftM realToFrac ({# get cofoldF->FcAB #} p)
                   <*> liftM realToFrac ({# get cofoldF->FA   #} p)
                   <*> liftM realToFrac ({# get cofoldF->FB   #} p)

-- |

ffiCoFold :: Int -> ByteString -> IO (Double,ByteString)
ffiCoFold cp inp = useAsCString inp $ \cinp ->
                   useAsCString inp $ \struc -> do
  setCutPoint cp
  e <- {#call cofold #} cinp struc
  s <- packCString struc
  return (cf2d e, s)

-- |

ffiCoEnergyOfStructure :: Int -> ByteString -> ByteString -> Int -> IO Double
ffiCoEnergyOfStructure cp inp struc verb =
  useAsCString inp   $ \i ->
  useAsCString struc $ \s ->
    setCutPoint cp
    >>  {#call energy_of_structure #} i s (fromIntegral verb :: CInt)
    >>= (return . cf2d)

-- |

ffiCoPartitionFunction :: Int -> ByteString -> IO (CofoldF,ByteString,A.Array (Int,Int) Double)
ffiCoPartitionFunction cutpoint i =
  useAsCString i $ \ci ->
  useAsCString i $ \cs ->
  alloca         $ \ptr -> do
  setCutPoint cutpoint
  let n = BS.length i
  let z = n * (n+1) `div` 2 +1
  eF <- co_pf_fold_p ptr ci cs >> peek ptr
  s  <- packCString cs
  bp <- {#call export_co_bppm #}
  xs <- peekArray z (bp :: Ptr CDouble)
  let ar = A.accumArray (const id) 0 ((1,1),(n,n)) $ zip [ (ii,jj) | ii <- [n,n-1..1], jj <- [n,n-1..ii]] (drop 1 $ map unsafeCoerce xs)
  return (eF, s, ar)

-- | Constrained partition function

ffiCoPartitionConstrained :: Int -> ByteString -> ByteString -> IO (CofoldF,ByteString,A.Array (Int,Int) Double)
ffiCoPartitionConstrained cutpoint sq st =
  useAsCString sq $ \csq ->
  useAsCString st $ \cst ->
  alloca          $ \ptr -> do
  setCutPoint cutpoint
  let n = BS.length sq
  let z = n * (n+1) `div` 2 +1
  eF <- co_pf_fold_constrained_p ptr csq cst 1 >> peek ptr
  s  <- packCString cst
  bp <- {#call export_co_bppm #}
  xs <- peekArray z (bp :: Ptr CDouble)
  let ar = A.accumArray (const id) 0 ((1,1),(n,n)) $ zip [ (ii,jj) | ii <- [n,n-1..1], jj <- [n,n-1..ii]] (drop 1 $ map unsafeCoerce xs)
  return (eF, s, ar)



foreign import ccall "ffiwrap_co_pf_fold" co_pf_fold_p :: CofoldFPtr -> CString -> CString -> IO ()

foreign import ccall "ffiwrap_co_pf_fold_constrained" co_pf_fold_constrained_p :: CofoldFPtr -> CString -> CString -> Int -> IO ()