summaryrefslogtreecommitdiff
path: root/contrib/haskell/src/Hkl/C.hsc
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/haskell/src/Hkl/C.hsc')
-rw-r--r--contrib/haskell/src/Hkl/C.hsc160
1 files changed, 160 insertions, 0 deletions
diff --git a/contrib/haskell/src/Hkl/C.hsc b/contrib/haskell/src/Hkl/C.hsc
new file mode 100644
index 0000000..6066d51
--- /dev/null
+++ b/contrib/haskell/src/Hkl/C.hsc
@@ -0,0 +1,160 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE CPP #-}
+
+module Hkl.C
+ ( compute
+ , computePipe
+ , solve
+ , solveTraj
+ , solveTrajPipe
+ , module X
+ ) where
+
+import Prelude hiding (min, max)
+
+import Control.Monad (forever)
+import Control.Monad.Trans.State.Strict
+import Foreign ( ForeignPtr
+ , FunPtr
+ , Ptr
+ , nullPtr
+ , newForeignPtr
+ , withForeignPtr
+ , withArray)
+import Foreign.C ( CInt(..), CSize(..), CString
+ , withCString)
+
+import Pipes (Pipe, await, lift, yield)
+
+import Hkl.C.Detector
+import Hkl.C.Engine
+import Hkl.C.EngineList
+import Hkl.C.Geometry as X
+import Hkl.C.GeometryList as X
+import Hkl.C.Sample
+import Hkl.Detector
+import Hkl.Types
+
+#include "hkl.h"
+
+-- Engine
+
+solve' :: Ptr HklEngine -> Engine -> IO (ForeignPtr HklGeometryList)
+solve' engine (Engine _ ps _) = do
+ let positions = [v | (Parameter _ v _) <- ps]
+ let n = toEnum (length positions)
+ withArray positions $ \values ->
+ c_hkl_engine_pseudo_axis_values_set engine values n unit nullPtr
+ >>= newForeignPtr c_hkl_geometry_list_free
+
+solve :: Geometry -> Detector a -> Sample b -> Engine -> IO [Geometry]
+solve g@(Geometry f _ _ _) d s e@(Engine name _ _) = do
+ withSample s $ \sample ->
+ withDetector d $ \detector ->
+ withGeometry g $ \geometry ->
+ withEngineList f $ \engines ->
+ withCString name $ \cname -> do
+ c_hkl_engine_list_init engines geometry detector sample
+ engine <- c_hkl_engine_list_engine_get_by_name engines cname nullPtr
+ solve' engine e >>= peekHklGeometryList
+
+solveTraj :: Geometry -> Detector a -> Sample b -> [Engine] -> IO [Geometry]
+solveTraj g@(Geometry f _ _ _) d s es = do
+ let name = engineName (head es)
+ withSample s $ \sample ->
+ withDetector d $ \detector ->
+ withGeometry g $ \geometry ->
+ withEngineList f $ \engines ->
+ withCString name $ \cname -> do
+ c_hkl_engine_list_init engines geometry detector sample
+ engine <- c_hkl_engine_list_engine_get_by_name engines cname nullPtr
+ mapM (\e -> solve' engine e >>= getSolution0) es
+
+-- Pipe
+
+data Diffractometer = Diffractometer { difEngineList :: (ForeignPtr HklEngineList)
+ , difGeometry :: (ForeignPtr Geometry)
+ , difDetector :: (ForeignPtr HklDetector)
+ , difSample :: (ForeignPtr HklSample)
+ }
+ deriving (Show)
+
+withDiffractometer :: Diffractometer -> (Ptr HklEngineList -> IO b) -> IO b
+withDiffractometer d fun = do
+ let f_engines = difEngineList d
+ withForeignPtr f_engines fun
+
+newDiffractometer :: Geometry -> Detector a -> Sample b -> IO Diffractometer
+newDiffractometer g@(Geometry f _ _ _) d s = do
+ f_engines <- newEngineList f
+ f_geometry <- newGeometry g
+ f_detector <- newDetector d
+ f_sample <- newSample s
+ withForeignPtr f_sample $ \sample ->
+ withForeignPtr f_detector $ \detector ->
+ withForeignPtr f_geometry $ \geometry ->
+ withForeignPtr f_engines $ \engines -> do
+ c_hkl_engine_list_init engines geometry detector sample
+ return $ Diffractometer { difEngineList = f_engines
+ , difGeometry = f_geometry
+ , difDetector = f_detector
+ , difSample = f_sample
+ }
+
+computePipe :: Detector a -> Sample b -> Pipe Geometry [Engine] IO ()
+computePipe d s = forever $ do
+ g <- await
+ e <- lift $ compute g d s
+ yield e
+
+solveTrajPipe :: Geometry -> Detector a -> Sample b -> Pipe Engine Geometry IO ()
+solveTrajPipe g d s = do
+ dif <- lift $ newDiffractometer g d s
+ solveTrajPipe' dif
+
+solveTrajPipe' :: Diffractometer -> Pipe Engine Geometry IO ()
+solveTrajPipe' dif = flip evalStateT dif $ forever $ do
+ -- Inside here we are using `StateT Diffractometer (Pipe Engine Geometry IO ()) r`
+ e <- lift await
+ dif_ <- get
+ let name = engineName e
+ solutions <- lift . lift $ withDiffractometer dif_ $ \engines ->
+ withCString name $ \cname -> do
+ engine <- c_hkl_engine_list_engine_get_by_name engines cname nullPtr
+ solve' engine e >>= getSolution0
+ put dif_
+ lift $ yield solutions
+
+foreign import ccall unsafe "hkl.h hkl_engine_list_engine_get_by_name"
+ c_hkl_engine_list_engine_get_by_name :: Ptr HklEngineList --engine list
+ -> CString -- engine name
+ -> Ptr () -- gerror need to deal about this
+ -> IO (Ptr HklEngine) -- the returned HklEngine
+
+foreign import ccall unsafe "hkl.h hkl_engine_pseudo_axis_values_set"
+ c_hkl_engine_pseudo_axis_values_set :: Ptr HklEngine
+ -> Ptr Double --values
+ -> CSize -- n_values
+ -> CInt -- unit_type
+ -> Ptr () -- GError **error
+ -> IO (Ptr HklGeometryList)
+
+foreign import ccall unsafe "hkl.h &hkl_geometry_list_free"
+ c_hkl_geometry_list_free :: FunPtr (Ptr HklGeometryList -> IO ())
+
+compute :: Geometry -> Detector a -> Sample b -> IO [Engine]
+compute g@(Geometry f _ _ _) d s = do
+ withSample s $ \sample ->
+ withDetector d $ \detector ->
+ withGeometry g $ \geometry ->
+ withEngineList f $ \engines -> do
+ c_hkl_engine_list_init engines geometry detector sample
+ c_hkl_engine_list_get engines
+ engineListEnginesGet engines
+
+foreign import ccall unsafe "hkl.h hkl_engine_list_init"
+ c_hkl_engine_list_init:: Ptr HklEngineList -> Ptr Geometry -> Ptr HklDetector -> Ptr HklSample -> IO ()
+
+foreign import ccall unsafe "hkl.h hkl_engine_list_get"
+ c_hkl_engine_list_get:: Ptr HklEngineList -> IO ()