2 {-# LANGUAGE FlexibleInstances #-}
3 {-# LANGUAGE ForeignFunctionInterface #-}
19 import Prelude hiding (min, max)
21 import Numeric.LinearAlgebra
22 import Foreign ( ForeignPtr
28 import Foreign.C (CInt(..), CDouble(..), CSize(..), CString,
29 peekCString, withCString)
30 import Foreign.Storable
32 import Numeric.Units.Dimensional.Prelude ( meter, nano
35 import qualified Data.Vector.Storable as V
36 import qualified Data.Vector.Storable.Mutable as MV
45 data Factory = K6c | Uhv | MedH | MedV | SoleilSiriusKappa
47 instance Show Factory where
52 show SoleilSiriusKappa = "SOLEIL SIRIUS KAPPA"
54 factoryFromString :: String -> Factory
60 | s == "SOLEIL SIRIUS KAPPA" = SoleilSiriusKappa
61 | otherwise = error $ "unknown diffractometer type:" ++ s
65 data Geometry = Geometry
66 Factory -- ^ the type of diffractometer
68 (Vector Double) -- ^ axes position
69 (Maybe [Parameter]) -- ^ axes configuration
80 #if __GLASGOW_HASKELL__ <= 710
81 #let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
86 newFactory :: Factory -> IO (Ptr HklFactory)
87 newFactory f = withCString (show f) $ \cname -> c_hkl_factory_get_by_name cname nullPtr
89 foreign import ccall unsafe "hkl.h hkl_factory_get_by_name"
90 c_hkl_factory_get_by_name :: CString -- ^ name
91 -> Ptr () -- ^ GError (null for now)
92 -> IO (Ptr HklFactory)
95 peekSource :: Ptr Geometry -> IO (Source)
97 (CDouble w) <- c_hkl_geometry_wavelength_get ptr unit
98 return (Source (w *~ nano meter))
100 foreign import ccall unsafe "hkl.h hkl_geometry_wavelength_set"
101 c_hkl_geometry_wavelength_set :: Ptr Geometry -- geometry
102 -> CDouble -- wavelength
105 -> IO () -- IO CInt but for now do not deal with the errors
107 pokeSource :: Ptr Geometry -> Source -> IO ()
108 pokeSource ptr (Source lw) = do
109 let wavelength = CDouble (lw /~ nano meter)
110 c_hkl_geometry_wavelength_set ptr wavelength unit nullPtr
112 foreign import ccall unsafe "hkl.h hkl_geometry_wavelength_get"
113 c_hkl_geometry_wavelength_get :: Ptr Geometry -- geometry
115 -> IO CDouble -- wavelength
117 peekAxis :: Ptr Geometry -> CString -> IO Parameter
118 peekAxis ptr s = c_hkl_geometry_axis_get ptr s nullPtr >>= peek
120 instance Storable Geometry where
121 alignment _ = #{alignment int}
123 sizeOf _ = #{size int}
126 f_name <- c_hkl_geometry_name_get ptr >>= peekCString
127 let factory = factoryFromString f_name
129 source <- peekSource ptr
131 (DArray n axis_names) <- peek =<< c_hkl_geometry_axis_names_get ptr
132 v <- MV.new (fromEnum n)
133 MV.unsafeWith v $ \values ->
134 c_hkl_geometry_axis_values_get ptr values n unit
137 ps <- mapM (peekAxis ptr) axis_names
139 return $ Geometry factory source vs (Just ps)
141 poke ptr (Geometry _ s vs _) = do
143 (DArray n _) <- peek =<< c_hkl_geometry_axis_names_get ptr
144 V.unsafeWith vs $ \values ->
145 c_hkl_geometry_axis_values_set ptr values n unit nullPtr
147 foreign import ccall unsafe "hkl.h hkl_geometry_axis_values_get"
148 c_hkl_geometry_axis_values_get :: Ptr Geometry -- geometry
149 -> Ptr Double -- axis values
150 -> CSize -- size of axis values
152 -> IO () -- IO CInt but for now do not deal with the errors
154 foreign import ccall unsafe "hkl.h hkl_geometry_axis_names_get"
155 c_hkl_geometry_axis_names_get :: Ptr Geometry -- goemetry
156 -> IO (Ptr (DArray CString)) -- darray_string
158 foreign import ccall unsafe "hkl.h hkl_geometry_axis_get"
159 c_hkl_geometry_axis_get :: Ptr Geometry -- geometry
160 -> CString -- axis name
162 -> IO (Ptr Parameter) -- parameter or nullPtr
164 foreign import ccall unsafe "hkl.h hkl_geometry_name_get"
165 c_hkl_geometry_name_get :: Ptr Geometry -> IO CString
167 foreign import ccall unsafe "hkl.h hkl_geometry_axis_values_set"
168 c_hkl_geometry_axis_values_set :: Ptr Geometry -- geometry
169 -> Ptr Double -- axis values
170 -> CSize -- size of axis values
173 -> IO () -- IO CInt but for now do not deal with the errors
175 withGeometry :: Geometry -> (Ptr Geometry -> IO b) -> IO b
176 withGeometry g fun = do
177 fptr <- newGeometry g
178 withForeignPtr fptr fun
180 newGeometry :: Geometry -> IO (ForeignPtr Geometry)
181 newGeometry g@(Geometry f _ _ _) = do
182 ptr <- c_hkl_factory_create_new_geometry =<< newFactory f
184 newForeignPtr c_hkl_geometry_free ptr
186 foreign import ccall unsafe "hkl.h hkl_factory_create_new_geometry"
187 c_hkl_factory_create_new_geometry :: Ptr HklFactory -> IO (Ptr Geometry)
189 foreign import ccall unsafe "hkl.h &hkl_geometry_free"
190 c_hkl_geometry_free :: FunPtr (Ptr Geometry -> IO ())