hnetcdf 0.1.0.0 → 0.2.0.0
raw patch · 17 files changed
+628/−350 lines, 17 filesdep +hmatrixdep ~repadep ~transformers
Dependencies added: hmatrix
Dependency ranges changed: repa, transformers
Files
- CHANGELOG.markdown +4/−0
- Data/NetCDF.hs +145/−38
- Data/NetCDF/HMatrix.hs +40/−0
- Data/NetCDF/Metadata.hs +135/−27
- Data/NetCDF/PutGet.hs +0/−3
- Data/NetCDF/Raw.hs +2/−2
- Data/NetCDF/Raw/NetCDF4.chs +0/−151
- Data/NetCDF/Repa.hs +16/−0
- Data/NetCDF/Storable.hs +0/−49
- Data/NetCDF/Store.hs +0/−19
- Data/NetCDF/Types.hs +8/−19
- Data/NetCDF/Utils.hs +5/−0
- Data/NetCDF/Vector.hs +13/−0
- README.markdown +46/−0
- hnetcdf.cabal +28/−10
- test/test-get.hs +153/−32
- test/test-put.hs +33/−0
+ CHANGELOG.markdown view
@@ -0,0 +1,4 @@+0.2.0.0+-------+* Add partial output API+
Data/NetCDF.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE ScopedTypeVariables #-} -- | Bindings to the Unidata NetCDF data access library. -- -- As well as conventional low-level FFI bindings to the functions@@ -16,7 +17,7 @@ -- > ... -- > type SVRet = IO (Either NcError (SV.Vector a)) -- > ...--- > enc <- openFile "tst.nc" ReadMode+-- > enc <- openFile "tst.nc" -- > case enc of -- > Right nc -> do -- > eval <- get nc "varname" :: SVRet CDouble@@ -34,7 +35,7 @@ -- > ... -- > type RepaRet3 a = IO (Either NcError (R.Array F R.DIM3 a)) -- > ...--- > enc <- openFile "tst.nc" ReadMode+-- > enc <- openFile "tst.nc" -- > case enc of -- > Right nc -> do -- > eval <- get nc "varname" :: RepaRet3 CDouble@@ -45,8 +46,11 @@ , module Data.NetCDF.Metadata , NcStorable (..) , IOMode (..)- , openFile, closeFile, withFile- , get1, get, getA, getS ) where+ , openFile, createFile, closeFile+ , withReadFile, withCreateFile+ , get1, get, getA, getS+ , put1, put, putA, putS+ , coardsScale ) where import Data.NetCDF.Raw import Data.NetCDF.Types@@ -56,52 +60,73 @@ import Data.NetCDF.Store import Data.NetCDF.Utils -import Control.Applicative ((<$>)) import Control.Exception (bracket)-import Control.Monad (forM, void)-import Control.Monad.IO.Class-import Control.Monad.Trans.Reader+import Control.Monad (forM, forM_, void) import Control.Error-import Data.List import qualified Data.Map as M import Foreign.C import System.IO (IOMode (..)) --- | Open a NetCDF file and read all metadata.-openFile :: FilePath -> IOMode -> NcIO NcInfo-openFile p mode = runAccess "openFile" p $ do- ncid <- chk $ nc_open p (ncIOMode mode)+-- | Open an existing NetCDF file for read-only access and read all+-- metadata: the returned 'NcInfo' value contains all the information+-- about dimensions, variables and attributes in the file.+openFile :: FilePath -> NcIO (NcInfo NcRead)+openFile p = runAccess "openFile" p $ do+ ncid <- chk $ nc_open p (ncIOMode ReadMode) (ndims, nvars, nattrs, unlim) <- chk $ nc_inq ncid dims <- forM [0..ndims-1] (read1Dim ncid unlim) attrs <- forM [0..nattrs-1] (read1Attr ncid ncGlobal) vars <- forM [0..nvars-1] (read1Var ncid dims) let mkMap nf = foldl (\m v -> M.insert (nf v) v m) M.empty dimmap = mkMap ncDimName dims- attmap = mkMap ncAttrName attrs+ attmap = M.fromList attrs varmap = mkMap ncVarName vars varidmap = M.fromList $ zip (map ncVarName vars) [0..] return $ NcInfo p dimmap varmap attmap ncid varidmap +-- | Create a new NetCDF file, ready for write-only access. The+-- 'NcInfo' parameter contains all the information about dimensions,+-- variables and attributes in the file.+createFile :: NcInfo NcWrite -> NcIO (NcInfo NcWrite)+createFile (NcInfo n ds vs as _ _) = runAccess "createFile" n $ do+ ncid <- chk $ nc_create n (ncIOMode WriteMode)+ newds <- forM (M.toList ds) (write1Dim ncid . snd)+ let dimids = M.fromList $ zip (M.keys ds) newds+ forM_ (M.toList as) (write1Attr ncid ncGlobal)+ newvs <- forM (M.toList vs) (write1Var ncid dimids . snd)+ let varids = M.fromList $ zip (M.keys vs) newvs+ chk $ nc_enddef ncid+ return $ NcInfo n ds vs as ncid varids+ -- | Close a NetCDF file.-closeFile :: NcInfo -> IO ()+closeFile :: NcInfo a -> IO () closeFile (NcInfo _ _ _ _ ncid _) = void $ nc_close ncid --- | Bracket file use: a little different from the standard 'withFile'--- function because of error handling.-withFile :: FilePath -> IOMode- -> (NcInfo -> IO r) -> (NcError -> IO r) -> IO r-withFile p m ok err = bracket- (openFile p m)+-- | Bracket read-only file use: a little different from the standard+-- 'withFile' function because of error handling.+withReadFile :: FilePath+ -> (NcInfo NcRead -> IO r) -> (NcError -> IO r) -> IO r+withReadFile p ok e = bracket+ (openFile p) (either (const $ return ()) closeFile)- (either err ok)+ (either e ok) +-- | Bracket write-only file use: a little different from the standard+-- 'withFile' function because of error handling.+withCreateFile :: NcInfo NcWrite+ -> (NcInfo NcWrite -> IO r) -> (NcError -> IO r) -> IO r+withCreateFile nc ok e = bracket+ (createFile nc)+ (either (const $ return ()) closeFile)+ (either e ok)+ -- | Read a single value from an open NetCDF file.-get1 :: NcStorable a => NcInfo -> NcVar -> [Int] -> NcIO a+get1 :: NcStorable a => NcInfo NcRead -> NcVar -> [Int] -> NcIO a get1 nc var idxs = runAccess "get1" (ncName nc) $ chk $ get_var1 (ncId nc) ((ncVarIds nc) M.! (ncVarName var)) idxs -- | Read a whole variable from an open NetCDF file.-get :: (NcStorable a, NcStore s) => NcInfo -> NcVar -> NcIO (s a)+get :: (NcStorable a, NcStore s) => NcInfo NcRead -> NcVar -> NcIO (s a) get nc var = runAccess "get" (ncName nc) $ do let ncid = ncId nc varid = (ncVarIds nc) M.! (ncVarName var)@@ -110,7 +135,7 @@ -- | Read a slice of a variable from an open NetCDF file. getA :: (NcStorable a, NcStore s)- => NcInfo -> NcVar -> [Int] -> [Int] -> NcIO (s a)+ => NcInfo NcRead -> NcVar -> [Int] -> [Int] -> NcIO (s a) getA nc var start count = runAccess "getA" (ncName nc) $ do let ncid = ncId nc varid = (ncVarIds nc) M.! (ncVarName var)@@ -118,49 +143,131 @@ -- | Read a strided slice of a variable from an open NetCDF file. getS :: (NcStorable a, NcStore s)- => NcInfo -> NcVar -> [Int] -> [Int] -> [Int] -> NcIO (s a)+ => NcInfo NcRead -> NcVar -> [Int] -> [Int] -> [Int] -> NcIO (s a) getS nc var start count stride = runAccess "getS" (ncName nc) $ do let ncid = ncId nc varid = (ncVarIds nc) M.! (ncVarName var) chk $ get_vars ncid varid start count stride +-- | Write a single value to an open NetCDF file.+put1 :: NcStorable a => NcInfo NcWrite -> NcVar -> [Int] -> a -> NcIO ()+put1 nc var idxs val = runAccess "put1" (ncName nc) $+ chk $ put_var1 (ncId nc) ((ncVarIds nc) M.! (ncVarName var)) idxs val++-- | Write a whole variable to an open NetCDF file.+put :: (NcStorable a, NcStore s) => NcInfo NcWrite -> NcVar -> s a -> NcIO ()+put nc var val = runAccess "put" (ncName nc) $ do+ let ncid = ncId nc+ varid = (ncVarIds nc) M.! (ncVarName var)+ chk $ put_var ncid varid val++-- | Write a slice of a variable to an open NetCDF file.+putA :: (NcStorable a, NcStore s)+ => NcInfo NcWrite -> NcVar -> [Int] -> [Int] -> s a -> NcIO ()+putA nc var start count val = runAccess "putA" (ncName nc) $ do+ let ncid = ncId nc+ varid = (ncVarIds nc) M.! (ncVarName var)+ chk $ put_vara ncid varid start count val++-- | Write a strided slice of a variable to an open NetCDF file.+putS :: (NcStorable a, NcStore s)+ => NcInfo NcWrite -> NcVar -> [Int] -> [Int] -> [Int] -> s a -> NcIO ()+putS nc var start count stride val = runAccess "putS" (ncName nc) $ do+ let ncid = ncId nc+ varid = (ncVarIds nc) M.! (ncVarName var)+ chk $ put_vars ncid varid start count stride val++ -- | Helper function to read a single NC dimension. read1Dim :: Int -> Int -> Int -> Access NcDim read1Dim ncid unlim dimid = do (name, len) <- chk $ nc_inq_dim ncid dimid return $ NcDim name len (dimid == unlim) +-- | Helper function to write a single NC dimension.+write1Dim :: Int -> NcDim -> Access Int+write1Dim ncid (NcDim name len unlim) = do+ chk $ nc_def_dim ncid name (if unlim then ncUnlimitedLength else len)+ -- | Helper function to read a single NC attribute.-read1Attr :: Int -> Int -> Int -> Access NcAttr+read1Attr :: Int -> Int -> Int -> Access (Name, NcAttr) read1Attr ncid varid attid = do n <- chk $ nc_inq_attname ncid varid attid (itype, len) <- chk $ nc_inq_att ncid varid n a <- readAttr ncid varid n (toEnum itype) len- return a+ return (n, a) +-- | Helper function to write a single NC attribute.+write1Attr :: Int -> Int -> (Name, NcAttr) -> Access ()+write1Attr ncid varid (n, a) = writeAttr ncid varid n a+ -- | Helper function to read metadata for a single NC variable. read1Var :: Int -> [NcDim] -> Int -> Access NcVar read1Var ncid dims varid = do (n, itype, nvdims, vdimids, nvatts) <- chk $ nc_inq_var ncid varid let vdims = map (dims !!) $ take nvdims vdimids vattrs <- forM [0..nvatts-1] (read1Attr ncid varid)- let vattmap = foldl (\m a -> M.insert (ncAttrName a) a m) M.empty vattrs+ let vattmap = foldl (\m (nm, a) -> M.insert nm a m) M.empty vattrs return $ NcVar n (toEnum itype) vdims vattmap +-- | Helper function to write metadata for a single NC variable.+write1Var :: Int -> M.Map Name Int -> NcVar -> Access Int+write1Var ncid dimidmap (NcVar n t dims as) = do+ let dimids = map ((dimidmap M.!) . ncDimName) dims+ varid <- chk $ nc_def_var ncid n (fromEnum t) (length dims) dimids+ forM_ (M.toList as) (write1Attr ncid varid)+ return varid+ -- | Read an attribute from a NetCDF variable with error handling. readAttr :: Int -> Int -> String -> NcType -> Int -> Access NcAttr-readAttr nc var n NcChar l = readAttr' nc var n l nc_get_att_text-readAttr nc var n NcShort l = readAttr' nc var n l nc_get_att_short-readAttr nc var n NcInt l = readAttr' nc var n l nc_get_att_int-readAttr nc var n NcFloat l = readAttr' nc var n l nc_get_att_float-readAttr nc var n NcDouble l = readAttr' nc var n l nc_get_att_double-readAttr nc var n NcUInt l = readAttr' nc var n l nc_get_att_uint-readAttr _ _ n _ _ = return $ NcAttr n ([0] :: [CInt])+readAttr nc var n NcByte l =+ readAttr' nc var n l (NcAttrByte . map fromIntegral) nc_get_att_uchar+readAttr nc var n NcChar l = readAttr' nc var n l NcAttrChar nc_get_att_text+readAttr nc var n NcShort l = readAttr' nc var n l NcAttrShort nc_get_att_short+readAttr nc var n NcInt l = readAttr' nc var n l NcAttrInt nc_get_att_int+readAttr nc var n NcFloat l = readAttr' nc var n l NcAttrFloat nc_get_att_float+readAttr nc var n NcDouble l =+ readAttr' nc var n l NcAttrDouble nc_get_att_double -- | Helper function for attribute reading.-readAttr' :: Show a => Int -> Int -> String -> Int+readAttr' :: Show a => Int -> Int -> String -> Int -> ([a] -> NcAttr) -> (Int -> Int -> String -> Int -> IO (Int, [a])) -> Access NcAttr-readAttr' nc var n l rf = NcAttr n <$> (chk $ rf nc var n l)+readAttr' nc var n l w rf = chk $ do+ tmp <- rf nc var n l+ return $ (fst tmp, w $ snd tmp) +-- | Write an attribute to a NetCDF variable with error handling.+writeAttr :: Int -> Int -> String -> NcAttr -> Access ()+writeAttr nc var n (NcAttrByte v) = writeAttr' nc var n id v nc_put_att_uchar+writeAttr nc var n (NcAttrChar v) = writeAttr' nc var n id v nc_put_att_text+writeAttr nc var n (NcAttrShort v) =+ writeAttr' nc var n fromIntegral v nc_put_att_short+writeAttr nc var n (NcAttrInt v) =+ writeAttr' nc var n fromIntegral v nc_put_att_int+writeAttr nc var n (NcAttrFloat v) =+ writeAttr' nc var n realToFrac v nc_put_att_float+writeAttr nc var n (NcAttrDouble v) =+ writeAttr' nc var n realToFrac v nc_put_att_double +-- | Helper function for attribute writeing.+writeAttr' :: Int -> Int -> String -> (a -> b) -> [a]+ -> (Int -> Int -> String -> Int -> [b] -> IO Int) -> Access ()+writeAttr' nc var n conv vs wf = chk $ wf nc var n (length vs) (map conv vs)+++-- | Apply COARDS value scaling.+coardsScale :: forall a b s. (NcStorable a, NcStorable b, FromNcAttr a,+ NcStore s, Real a, Fractional b)+ => NcVar -> s a -> s b+coardsScale v din = smap xform din+ where offset = fromMaybe 0.0 $+ ncVarAttr v "add_offset" >>= fromAttr :: CDouble+ scale = fromMaybe 1.0 $+ ncVarAttr v "scale_factor" >>= fromAttr :: CDouble+ fill = ncVarAttr v "_FillValue" >>= fromAttr :: Maybe a+ xform x = case fill of+ Nothing -> realToFrac $ realToFrac x * scale + offset+ Just f -> if x == f+ then realToFrac f+ else realToFrac $ realToFrac x * scale + offset
+ Data/NetCDF/HMatrix.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- | NetCDF store instance for HMatrix vectors and matrices.+module Data.NetCDF.HMatrix+ ( HVector (..)+ , HRowMajorMatrix (..)+ , HColumnMajorMatrix (..)+ ) where++import Data.NetCDF.Store++import qualified Numeric.Container as C+import Data.Packed.Foreign+import Data.Packed.Development++newtype HVector a = HVector (C.Vector a)+ deriving (Eq, Show)++instance NcStore HVector where+ toForeignPtr (HVector v) = (\(x, _, _) -> x) $ unsafeToForeignPtr v+ fromForeignPtr p s = HVector $ unsafeFromForeignPtr p 0 (Prelude.product s)+ smap f (HVector v) = HVector $ C.mapVector f v++newtype HRowMajorMatrix a = HRowMajorMatrix (C.Matrix a)++instance NcStore HRowMajorMatrix where+ toForeignPtr (HRowMajorMatrix m) = fst $ unsafeMatrixToForeignPtr m+ fromForeignPtr p s = HRowMajorMatrix $+ matrixFromVector RowMajor (last s) $+ unsafeFromForeignPtr p 0 (Prelude.product s)+ smap f (HRowMajorMatrix m) = HRowMajorMatrix $ C.mapMatrix f m++newtype HColumnMajorMatrix a = HColumnMajorMatrix (C.Matrix a)++instance NcStore HColumnMajorMatrix where+ toForeignPtr (HColumnMajorMatrix m) = fst $ unsafeMatrixToForeignPtr m+ fromForeignPtr p s = HColumnMajorMatrix $+ matrixFromVector ColumnMajor (last s) $+ unsafeFromForeignPtr p 0 (Prelude.product s)+ smap f (HColumnMajorMatrix m) = HColumnMajorMatrix $ C.mapMatrix f m
Data/NetCDF/Metadata.hs view
@@ -1,69 +1,177 @@-{-# LANGUAGE ExistentialQuantification, StandaloneDeriving #-}+{-# LANGUAGE FlexibleInstances, UndecidableInstances, EmptyDataDecls #-} -- | NetCDF file metadata handling: when a NetCDF file is opened, -- metadata defining the dimensions, variables and attributes in the -- file are read all at once to create a value of type `NcInfo`. module Data.NetCDF.Metadata- ( NcDim (..)- , NcAttr (..)+ ( Name+ , NcDim (..)+ , NcAttr (..), ToNcAttr (..), FromNcAttr (..) , NcVar (..)- , NcInfo (..)+ , NcInfo (..), NcRead, NcWrite , ncDim, ncAttr, ncVar, ncVarAttr+ , emptyNcInfo+ , addNcDim, addNcVar, addNcAttr, addNcVarAttr, (#) ) where import Data.NetCDF.Types import qualified Data.Map as M+import Data.Word+import Foreign.C +-- | Names for dimensions, variables, attributes.+type Name = String -- | Information about a dimension: name, number of entries and -- whether unlimited.-data NcDim = NcDim { ncDimName :: String+data NcDim = NcDim { ncDimName :: Name , ncDimLength :: Int , ncDimUnlimited :: Bool } deriving Show -- | Attribute value.-data NcAttr = forall a. Show a => NcAttr { ncAttrName :: String- , ncAttrVals :: [a] }+data NcAttr = NcAttrByte [Word8]+ | NcAttrChar [Char]+ | NcAttrShort [CShort]+ | NcAttrInt [CInt]+ | NcAttrFloat [CFloat]+ | NcAttrDouble [CDouble]+ deriving (Eq, Show) -deriving instance Show NcAttr+-- | Conversion from Haskell types to attribute values.+class ToNcAttrHelp a where+ toAttrHelp :: [a] -> NcAttr +instance ToNcAttrHelp Word8 where toAttrHelp = NcAttrByte+instance ToNcAttrHelp Char where toAttrHelp = NcAttrChar+instance ToNcAttrHelp CShort where toAttrHelp = NcAttrShort+instance ToNcAttrHelp CInt where toAttrHelp = NcAttrInt+instance ToNcAttrHelp CFloat where toAttrHelp = NcAttrFloat+instance ToNcAttrHelp CDouble where toAttrHelp = NcAttrDouble++class ToNcAttr a where+ toAttr :: a -> NcAttr++instance ToNcAttrHelp a => ToNcAttr a where+ toAttr x = toAttrHelp [x]+instance ToNcAttrHelp a => ToNcAttr [a] where+ toAttr xs = toAttrHelp xs++-- | Conversion from attribute values to Haskell types.+class FromNcAttr a where+ fromAttr :: NcAttr -> Maybe a++instance FromNcAttr Word8 where+ fromAttr (NcAttrByte [x]) = Just x+ fromAttr _ = Nothing+instance FromNcAttr [Word8] where+ fromAttr (NcAttrByte xs) = Just xs+ fromAttr _ = Nothing+instance FromNcAttr Char where+ fromAttr (NcAttrChar [x]) = Just x+ fromAttr _ = Nothing+instance FromNcAttr [Char] where+ fromAttr (NcAttrChar xs) = Just xs+ fromAttr _ = Nothing+instance FromNcAttr CShort where+ fromAttr (NcAttrShort [x]) = Just x+ fromAttr _ = Nothing+instance FromNcAttr [CShort] where+ fromAttr (NcAttrShort xs) = Just xs+ fromAttr _ = Nothing+instance FromNcAttr CInt where+ fromAttr (NcAttrInt [x]) = Just x+ fromAttr _ = Nothing+instance FromNcAttr [CInt] where+ fromAttr (NcAttrInt xs) = Just xs+ fromAttr _ = Nothing+instance FromNcAttr CFloat where+ fromAttr (NcAttrFloat [x]) = Just x+ fromAttr _ = Nothing+instance FromNcAttr [CFloat] where+ fromAttr (NcAttrFloat xs) = Just xs+ fromAttr _ = Nothing+instance FromNcAttr CDouble where+ fromAttr (NcAttrDouble [x]) = Just x+ fromAttr _ = Nothing+instance FromNcAttr [CDouble] where+ fromAttr (NcAttrDouble xs) = Just xs+ fromAttr _ = Nothing++ -- | Information about a variable: name, type, dimensions and -- attributes.-data NcVar = NcVar { ncVarName :: String+data NcVar = NcVar { ncVarName :: Name , ncVarType :: NcType , ncVarDims :: [NcDim]- , ncVarAttrs :: M.Map String NcAttr+ , ncVarAttrs :: M.Map Name NcAttr } deriving Show +-- | Type tags for NcInfo values.+data NcRead+data NcWrite+ -- | Metadata information for a whole NetCDF file.-data NcInfo = NcInfo { ncName :: FilePath- -- ^ File name.- , ncDims :: M.Map String NcDim- -- ^ Dimensions defined in file.- , ncVars :: M.Map String NcVar- -- ^ Variables defined in file.- , ncAttrs :: M.Map String NcAttr- -- ^ Global attributes defined in file.- , ncId :: NcId- -- ^ Low-level file access ID.- , ncVarIds :: M.Map String NcId- -- ^ Low-level IDs for variables.- } deriving Show+data NcInfo a = NcInfo { ncName :: FilePath+ -- ^ File name.+ , ncDims :: M.Map Name NcDim+ -- ^ Dimensions defined in file.+ , ncVars :: M.Map Name NcVar+ -- ^ Variables defined in file.+ , ncAttrs :: M.Map Name NcAttr+ -- ^ Global attributes defined in file.+ , ncId :: NcId+ -- ^ Low-level file access ID.+ , ncVarIds :: M.Map Name NcId+ -- ^ Low-level IDs for variables.+ } deriving Show -- | Extract dimension metadata by name.-ncDim :: NcInfo -> String -> Maybe NcDim+ncDim :: NcInfo a -> Name -> Maybe NcDim ncDim nc n = M.lookup n $ ncDims nc -- | Extract a global attribute by name.-ncAttr :: NcInfo -> String -> Maybe NcAttr+ncAttr :: NcInfo a -> Name -> Maybe NcAttr ncAttr nc n = M.lookup n $ ncAttrs nc -- | Extract variable metadata by name.-ncVar :: NcInfo -> String -> Maybe NcVar+ncVar :: NcInfo a -> Name -> Maybe NcVar ncVar nc n = M.lookup n $ ncVars nc -- | Extract an attribute for a given variable by name.-ncVarAttr :: NcVar -> String -> Maybe NcAttr+ncVarAttr :: NcVar -> Name -> Maybe NcAttr ncVarAttr v n = M.lookup n $ ncVarAttrs v+++-- | Empty NcInfo value to build on.+emptyNcInfo :: FilePath -> NcInfo NcWrite+emptyNcInfo n = NcInfo n M.empty M.empty M.empty ncInvalidId M.empty++-- | Add a new dimension to an NcInfo value.+addNcDim :: NcDim -> NcInfo NcWrite -> NcInfo NcWrite+addNcDim dim@(NcDim name _ _) (NcInfo n ds vs as fid vids) =+ NcInfo n (M.insert name chkdim ds) vs as fid vids+ where chkdim = dim { ncDimUnlimited =+ ncDimUnlimited dim &&+ (not . or . (map ncDimUnlimited) . M.elems $ ds) }++-- | Add a new variable to an NcInfo value.+addNcVar :: NcVar -> NcInfo NcWrite -> NcInfo NcWrite+addNcVar var@(NcVar name _ _ _) (NcInfo n ds vs as fid vids) =+ NcInfo n ds (M.insert name var vs) as fid vids++-- | Add a new global attribute to an NcInfo value.+addNcAttr :: Name -> NcAttr -> NcInfo NcWrite -> NcInfo NcWrite+addNcAttr name att (NcInfo n ds vs as fid vids) =+ NcInfo n ds vs (M.insert name att as) fid vids++-- | Add a new attribute to an NcVar value.+addNcVarAttr :: Name -> NcAttr -> NcVar -> NcVar+addNcVarAttr name att (NcVar n t ds as) = NcVar n t ds (M.insert name att as)++infixl 8 #++-- | Handy postfix function application.+(#) :: a -> (a -> b) -> b+(#) = flip ($)
Data/NetCDF/PutGet.hs view
@@ -14,12 +14,9 @@ import Foreign.Marshal.Alloc import Control.Applicative ((<$>)) import Control.Monad (liftM)-import Data.Word -import Data.NetCDF.Types import Data.NetCDF.Storable import Data.NetCDF.Store-import Data.NetCDF.Raw.PutGet put_var1 :: NcStorable a => Int -> Int -> [Int] -> a -> IO Int put_var1 nc var idxs v = do
Data/NetCDF/Raw.hs view
@@ -4,10 +4,10 @@ ( module Data.NetCDF.Raw.Base , module Data.NetCDF.Raw.PutGet , module Data.NetCDF.Raw.Attributes- , module Data.NetCDF.Raw.NetCDF4+-- , module Data.NetCDF.Raw.NetCDF4 ) where import Data.NetCDF.Raw.Base import Data.NetCDF.Raw.PutGet import Data.NetCDF.Raw.Attributes-import Data.NetCDF.Raw.NetCDF4+--import Data.NetCDF.Raw.NetCDF4
− Data/NetCDF/Raw/NetCDF4.chs
@@ -1,151 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface #-}---- | Raw bindings for NetCDF4 features (not implemented).--module Data.NetCDF.Raw.NetCDF4 where--#include <netcdf.h>---------------------------------------------------------------------------------------- UNSUPPORTED FEATURES (NetCDF-4)---------------------------------------------------------------------------------------- USER DEFINED TYPES------ int nc_def_compound(int ncid, size_t size,--- const char *name, nc_type *typeidp);--- int nc_insert_compound(int ncid, nc_type xtype, const char *name,--- size_t offset, nc_type field_typeid);--- int nc_insert_array_compound(int ncid, nc_type xtype, const char *name,--- size_t offset, nc_type field_typeid,--- int ndims, const int *dim_sizes);--- int nc_inq_type(int ncid, nc_type xtype, char *name, size_t *size);--- int nc_inq_compound(int ncid, nc_type xtype, char *name, size_t *sizep,--- size_t *nfieldsp);--- int nc_inq_compound_name(int ncid, nc_type xtype, char *name);--- int nc_inq_compound_size(int ncid, nc_type xtype, size_t *sizep);--- int nc_inq_compound_nfields(int ncid, nc_type xtype, size_t *nfieldsp);--- int nc_inq_compound_fieldname(int ncid, nc_type xtype, int fieldid,--- char *name);--- int nc_inq_compound_fieldindex(int ncid, nc_type xtype, const char *name,--- int *fieldidp);--- int nc_inq_compound_fieldoffset(int ncid, nc_type xtype, int fieldid,--- size_t *offsetp);--- int nc_inq_compound_fieldtype(int ncid, nc_type xtype, int fieldid,--- nc_type *field_typeidp);--- int nc_inq_compound_fieldndims(int ncid, nc_type xtype, int fieldid,--- int *ndimsp);--- int nc_inq_compound_fielddim_sizes(int ncid, nc_type xtype, int fieldid,--- int *dim_sizes);--- typedef struct {--- size_t len; /**< Length of VL data (in base type units) */--- void *p; /**< Pointer to VL data */--- } nc_vlen_t;--- int nc_def_vlen(int ncid, const char *name,--- nc_type base_typeid, nc_type *xtypep);--- int nc_inq_vlen(int ncid, nc_type xtype, char *name, size_t *datum_sizep,--- nc_type *base_nc_typep);--- int nc_free_vlen(nc_vlen_t *vl);--- int nc_put_vlen_element(int ncid, int typeid1, void *vlen_element,--- size_t len, const void *data);--- int nc_get_vlen_element(int ncid, int typeid1, const void *vlen_element,--- size_t *len, void *data);--- int nc_free_string(size_t len, char **data);--- int nc_inq_user_type(int ncid, nc_type xtype, char *name, size_t *size,--- nc_type *base_nc_typep, size_t *nfieldsp, int *classp);--- int nc_def_enum(int ncid, nc_type base_typeid, const char *name,--- nc_type *typeidp);--- int nc_insert_enum(int ncid, nc_type xtype, const char *name,--- const void *value);--- int nc_inq_enum_member(int ncid, nc_type xtype, int idx, char *name,--- void *value);--- int nc_inq_enum_ident(int ncid, nc_type xtype, long long value,--- char *identifier);--- int nc_def_opaque(int ncid, size_t size, const char *name, nc_type *xtypep);--- int nc_inq_opaque(int ncid, nc_type xtype, char *name, size_t *sizep);--- int nc_inq_typeid(int ncid, const char *name, nc_type *typeidp);--- int nc_inq_compound_field(int ncid, nc_type xtype, int fieldid, char *name,--- size_t *offsetp, nc_type *field_typeidp,--- int *ndimsp, int *dim_sizesp);--- int nc_free_vlens(size_t len, nc_vlen_t vlens[]);--- int nc_inq_enum(int ncid, nc_type xtype, char *name, nc_type *base_nc_typep,--- size_t *base_sizep, size_t *num_membersp);---- GROUPS------ int nc_inq_ncid(int ncid, const char *name, int *grp_ncid);--- int nc_inq_grps(int ncid, int *numgrps, int *ncids);--- int nc_inq_grpname(int ncid, char *name);--- int nc_inq_grpname_full(int ncid, size_t *lenp, char *full_name);--- int nc_inq_grpname_len(int ncid, size_t *lenp);--- int nc_inq_grp_parent(int ncid, int *parent_ncid);--- int nc_inq_grp_ncid(int ncid, const char *grp_name, int *grp_ncid);--- int nc_inq_grp_full_ncid(int ncid, const char *full_name, int *grp_ncid);--- int nc_inq_varids(int ncid, int *nvars, int *varids);--- int nc_inq_dimids(int ncid, int *ndims, int *dimids, int include_parents);--- int nc_inq_typeids(int ncid, int *ntypes, int *typeids);--- int nc_def_grp(int parent_ncid, const char *name, int *new_ncid);---- NETCDF-4 VARIABLES------ int nc_def_var_deflate(int ncid, int varid, int shuffle, int deflate,--- int deflate_level);--- int nc_inq_var_deflate(int ncid, int varid, int *shufflep,--- int *deflatep, int *deflate_levelp);--- int nc_def_var_fletcher32(int ncid, int varid, int fletcher32);--- int nc_inq_var_fletcher32(int ncid, int varid, int *fletcher32p);--- int nc_def_var_chunking(int ncid, int varid, int storage,--- const size_t *chunksizesp);--- int nc_inq_var_chunking(int ncid, int varid, int *storagep,--- size_t *chunksizesp);--- int nc_def_var_fill(int ncid, int varid, int no_fill,--- const void *fill_value);--- int nc_inq_var_fill(int ncid, int varid, int *no_fill, void *fill_valuep);--- int nc_def_var_endian(int ncid, int varid, int endian);--- int nc_inq_var_endian(int ncid, int varid, int *endianp);--- int nc_set_chunk_cache(size_t size, size_t nelems, float preemption);--- int nc_get_chunk_cache(size_t *sizep, size_t *nelemsp, float *preemptionp);--- int nc_set_var_chunk_cache(int ncid, int varid, size_t size, size_t nelems,--- float preemption);--- int nc_get_var_chunk_cache(int ncid, int varid, size_t *sizep,--- size_t *nelemsp, float *preemptionp);--- int nc_inq_var_szip(int ncid, int varid, int *options_maskp,--- int *pixels_per_blockp);---- Variable length strings are only supported in NetCDF-4 files, which--- we don't handle yet.------ int nc_put_var_string(int ncid, int varid, const char **op);--- int nc_get_var_string(int ncid, int varid, char **ip);--- int nc_put_var1_string(int ncid, int varid, const size_t *indexp,--- const char **op);--- int nc_get_var1_string(int ncid, int varid, const size_t *indexp,--- char **ip);--- int nc_put_vara_string(int ncid, int varid, const size_t *startp,--- const size_t *countp, const char **op);--- int nc_get_vara_string(int ncid, int varid, const size_t *startp,--- const size_t *countp, char **ip);--- int nc_put_vars_string(int ncid, int varid, const size_t *startp,--- const size_t *countp, const ptrdiff_t *stridep,--- const char **op);--- int nc_get_vars_string(int ncid, int varid, const size_t *startp,--- const size_t *countp, const ptrdiff_t *stridep,--- char **ip);--- int nc_put_varm_string(int ncid, int varid, const size_t *startp,--- const size_t *countp, const ptrdiff_t *stridep,--- const ptrdiff_t * imapp, const char **op);--- int nc_get_varm_string(int ncid, int varid, const size_t *startp,--- const size_t *countp, const ptrdiff_t *stridep,--- const ptrdiff_t * imapp, char **ip);--- int nc_put_att_string(int ncid, int varid, const char *name,--- size_t len, const char **op);--- int nc_get_att_string(int ncid, int varid, const char *name, char **ip);---- MISCELLANEOUS------ int nc_var_par_access(int ncid, int varid, int par_access);--- int nc_inq_type_equal(int ncid1, nc_type typeid1, int ncid2,--- nc_type typeid2, int *equal);--- int nc_set_default_format(int format, int *old_formatp);
+ Data/NetCDF/Repa.hs view
@@ -0,0 +1,16 @@+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- | NetCDF store instance for Repa arrays.+module Data.NetCDF.Repa where++import Data.NetCDF.Store++import Data.Array.Repa+import qualified Data.Array.Repa as R+import qualified Data.Array.Repa.Repr.ForeignPtr as RF+import Data.Array.Repa.Repr.ForeignPtr (F)++instance Shape sh => NcStore (Array F sh) where+ toForeignPtr = RF.toForeignPtr+ fromForeignPtr p s = RF.fromForeignPtr (shapeOfList $ reverse s) p+ smap f s = computeS $ R.map f s
Data/NetCDF/Storable.hs view
@@ -11,7 +11,6 @@ import Foreign.Storable import Data.NetCDF.Types-import Data.NetCDF.Store import Data.NetCDF.Raw.PutGet @@ -102,52 +101,4 @@ ffi_get_vara = nc_get_vara_double'_ ffi_put_vars = nc_put_vars_double'_ ffi_get_vars = nc_get_vars_double'_--instance NcStorable CUChar where- -- #define NC_UBYTE 7 /**< unsigned 1 byte int */- ncType _ = NcUByte- ffi_put_var1 = nc_put_var1_uchar'_- ffi_get_var1 = nc_get_var1_uchar'_- ffi_put_var = nc_put_var_uchar'_- ffi_get_var = nc_get_var_uchar'_- ffi_put_vara = nc_put_vara_uchar'_- ffi_get_vara = nc_get_vara_uchar'_- ffi_put_vars = nc_put_vars_uchar'_- ffi_get_vars = nc_get_vars_uchar'_--instance NcStorable CUShort where- -- #define NC_USHORT 8 /**< unsigned 2-byte int */- ncType _ = NcUShort- ffi_put_var1 = nc_put_var1_ushort'_- ffi_get_var1 = nc_get_var1_ushort'_- ffi_put_var = nc_put_var_ushort'_- ffi_get_var = nc_get_var_ushort'_- ffi_put_vara = nc_put_vara_ushort'_- ffi_get_vara = nc_get_vara_ushort'_- ffi_put_vars = nc_put_vars_ushort'_- ffi_get_vars = nc_get_vars_ushort'_--instance NcStorable CUInt where- -- #define NC_UINT 9 /**< unsigned 4-byte int */- ncType _ = NcUInt- ffi_put_var1 = nc_put_var1_uint'_- ffi_get_var1 = nc_get_var1_uint'_- ffi_put_var = nc_put_var_uint'_- ffi_get_var = nc_get_var_uint'_- ffi_put_vara = nc_put_vara_uint'_- ffi_get_vara = nc_get_vara_uint'_- ffi_put_vars = nc_put_vars_uint'_- ffi_get_vars = nc_get_vars_uint'_--instance NcStorable CLong where- -- #define NC_INT64 10 /**< signed 8-byte int */- ncType _ = NcInt64- ffi_put_var1 = nc_put_var1_long'_- ffi_get_var1 = nc_get_var1_long'_- ffi_put_var = nc_put_var_long'_- ffi_get_var = nc_get_var_long'_- ffi_put_vara = nc_put_vara_long'_- ffi_get_vara = nc_get_vara_long'_- ffi_put_vars = nc_put_vars_long'_- ffi_get_vars = nc_get_vars_long'_
Data/NetCDF/Store.hs view
@@ -5,19 +5,10 @@ module Data.NetCDF.Store where -import Data.List (reverse) import Foreign.Storable import Foreign.ForeignPtr -import Data.Vector.Storable hiding (reverse) -import Data.Array.Repa-import qualified Data.Array.Repa as R-import qualified Data.Array.Repa.Repr.ForeignPtr as RF-import Data.Array.Repa.Repr.ForeignPtr (F)--import Data.NetCDF.Types- -- | Class representing containers suitable for storing values read -- from NetCDF variables. Just has methods to convert back and forth -- between the store and a foreign pointer, and to perform simple@@ -26,13 +17,3 @@ toForeignPtr :: Storable e => s e -> ForeignPtr e fromForeignPtr :: Storable e => ForeignPtr e -> [Int] -> s e smap :: (Storable a, Storable b) => (a -> b) -> s a -> s b--instance NcStore Vector where- toForeignPtr = fst . unsafeToForeignPtr0- fromForeignPtr p s = unsafeFromForeignPtr0 p (Prelude.product s)- smap = Data.Vector.Storable.map--instance Shape sh => NcStore (Array F sh) where- toForeignPtr = RF.toForeignPtr- fromForeignPtr p s = RF.fromForeignPtr (shapeOfList $ reverse s) p- smap f s = computeS $ R.map f s
Data/NetCDF/Types.hs view
@@ -5,7 +5,6 @@ import Control.Exception import Data.Typeable-import System.FilePath import System.IO (IOMode (..)) -- | Representation for NetCDF external data types.@@ -16,12 +15,6 @@ | NcInt -- ^ Signed 4 byte integer | NcFloat -- ^ Single precision floating point | NcDouble -- ^ Double precision floating point- | NcUByte -- ^ Unsigned 1 byte int- | NcUShort -- ^ Unsigned 2-byte int- | NcUInt -- ^ Unsigned 4-byte int- | NcInt64 -- ^ Signed 8-byte int- | NcUInt64 -- ^ Unsigned 8-byte int- | NcString -- ^ String deriving (Eq, Show) instance Enum NcType where@@ -31,12 +24,6 @@ fromEnum NcInt = 4 fromEnum NcFloat = 5 fromEnum NcDouble = 6- fromEnum NcUByte = 7- fromEnum NcUShort = 8- fromEnum NcUInt = 9- fromEnum NcInt64 = 10- fromEnum NcUInt64 = 11- fromEnum NcString = 12 toEnum n = case n of 1 -> NcByte 2 -> NcChar@@ -44,12 +31,6 @@ 4 -> NcInt 5 -> NcFloat 6 -> NcDouble- 7 -> NcUByte- 8 -> NcUShort- 9 -> NcUInt- 10 -> NcInt64- 11 -> NcUInt64- 12 -> NcString _ -> throw (NcInvalidType n) -- | Internal representation of NetCDF IDs.@@ -73,3 +54,11 @@ -- | Fake variable identifier for global attributes. ncGlobal :: Int ncGlobal = -1++-- | Fake length value for defining unlimited dimensions.+ncUnlimitedLength :: Int+ncUnlimitedLength = 0++-- | Fake file identifier for unopened files.+ncInvalidId :: NcId+ncInvalidId = -1
Data/NetCDF/Utils.hs view
@@ -26,6 +26,11 @@ status :: a -> Int proj :: a -> OutType a +instance Checkable Int where+ type OutType Int = ()+ status s = s+ proj _ = ()+ instance Checkable (Int, a) where type OutType (Int, a) = a status (s, _) = s
+ Data/NetCDF/Vector.hs view
@@ -0,0 +1,13 @@+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- | NetCDF store instance for Storable Vectors.+module Data.NetCDF.Vector where++import Data.NetCDF.Store++import qualified Data.Vector.Storable as SV++instance NcStore SV.Vector where+ toForeignPtr = fst . SV.unsafeToForeignPtr0+ fromForeignPtr p s = SV.unsafeFromForeignPtr0 p (Prelude.product s)+ smap = SV.map
+ README.markdown view
@@ -0,0 +1,46 @@+hnetcdf+=======++Haskell NetCDF library: as well as conventional low-level FFI bindings+to the functions in the NetCDF library (in the `Data.NetCDF.Raw`+modules), `hnetcdf` provides a higher-level Haskell interface+(currently only for reading data). This higher-level interface aims+to provide a "container polymorphic" view of NetCDF data allowing+NetCDF variables to be read into `Storable` `Vectors` and Repa arrays+easily.++For example:++``` haskell+import Data.NetCDF+import Foreign.C+import qualified Data.Vector.Storable as SV+...+type SVRet = IO (Either NcError (SV.Vector a))+...+ enc <- openFile "tst.nc" ReadMode+ case enc of+ Right nc -> do+ eval <- get nc "varname" :: SVRet CDouble+ ...+```++gets the full contents of a NetCDF variable as a `Storable` `Vector`,+while the following code reads the same variable (assumed to be+three-dimensional) into a Repa array:++``` haskell+import Data.NetCDF+import Foreign.C+import qualified Data.Array.Repa as R+import qualified Data.Array.Repa.Eval as RE+import Data.Array.Repa.Repr.ForeignPtr (F)+...+type RepaRet3 a = IO (Either NcError (R.Array F R.DIM3 a))+...+ enc <- openFile "tst.nc" ReadMode+ case enc of+ Right nc -> do+ eval <- get nc "varname" :: RepaRet3 CDouble+ ...+```
hnetcdf.cabal view
@@ -1,5 +1,5 @@ name: hnetcdf-version: 0.1.0.0+version: 0.2.0.0 synopsis: Haskell NetCDF library description: Bindings to the Unidata NetCDF library, along with a higher-level@@ -12,6 +12,7 @@ copyright: Copyright (2013) Ian Ross category: Data build-type: Simple+extra-source-files: README.markdown CHANGELOG.markdown cabal-version: >=1.8 homepage: https://github.com/ian-ross/hnetcdf @@ -21,6 +22,9 @@ Library exposed-modules: Data.NetCDF+ Data.NetCDF.Vector+ Data.NetCDF.Repa+ Data.NetCDF.HMatrix Data.NetCDF.Metadata Data.NetCDF.PutGet Data.NetCDF.Storable@@ -31,18 +35,20 @@ Data.NetCDF.Raw.Base Data.NetCDF.Raw.PutGet Data.NetCDF.Raw.Attributes- Data.NetCDF.Raw.NetCDF4 Data.NetCDF.Raw.Utils+-- Data.NetCDF.Raw.NetCDF4 build-depends: base >= 4.3 && < 5, containers >= 0.4 && < 0.6,- filepath >= 1.3 && < 1.4,- transformers >= 0.2 && < 0.4, either >= 3.4.1 && < 3.5, errors >= 1.4.2 && < 1.5,- vector >= 0.9 && < 0.11,- repa >= 3.2 && < 3.3+ filepath >= 1.3 && < 1.4,+ hmatrix >= 0.15.2.0 && < 0.16,+ repa,+ transformers >= 0.2 && < 0.5,+ vector >= 0.9 && < 0.11 build-tools: c2hs extra-libraries: netcdf+ ghc-options: -Wall Test-Suite test-raw-metadata type: exitcode-stdio-1.0@@ -52,7 +58,7 @@ base >= 4.3 && < 5, containers >= 0.4 && < 0.6, vector >= 0.9 && < 0.11,- repa >= 3.2 && < 3.3,+ repa, test-framework >= 0.3, test-framework-hunit, test-framework-quickcheck2 >= 0.3,@@ -68,7 +74,7 @@ base >= 4.3 && < 5, containers >= 0.4 && < 0.6, vector >= 0.9 && < 0.11,- repa >= 3.2 && < 3.3,+ repa, directory >= 1.1 && < 1.3, test-framework >= 0.3, test-framework-hunit,@@ -85,7 +91,7 @@ base >= 4.3 && < 5, containers >= 0.4 && < 0.6, vector >= 0.9 && < 0.11,- repa >= 3.2 && < 3.3,+ repa, directory >= 1.1 && < 1.3, test-framework >= 0.3, test-framework-hunit,@@ -102,8 +108,9 @@ base >= 4.3 && < 5, containers >= 0.4 && < 0.6, errors >= 1.4.2 && < 1.5,+ hmatrix >= 0.15.2.0 && < 0.16,+ repa, vector >= 0.9 && < 0.11,- repa >= 3.2 && < 3.3, directory >= 1.1 && < 1.3, test-framework >= 0.3, test-framework-hunit,@@ -112,3 +119,14 @@ QuickCheck extra-libraries: netcdf +Test-Suite test-put+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: test-put.hs+ build-depends: hnetcdf,+ base >= 4.3 && < 5,+ containers >= 0.4 && < 0.6,+ errors >= 1.4.2 && < 1.5,+ vector >= 0.9 && < 0.11,+ directory >= 1.1 && < 1.3+ extra-libraries: netcdf
test/test-get.hs view
@@ -8,9 +8,13 @@ import Data.Array.Repa.Repr.ForeignPtr (F) import Control.Error import Control.Monad-+import Numeric.Container as C import Foreign.C+ import Data.NetCDF+import qualified Data.NetCDF.Vector as V+import qualified Data.NetCDF.Repa as R+import qualified Data.NetCDF.HMatrix as H main :: IO () main = defaultMain tests@@ -41,6 +45,9 @@ , testCase "Read (float, Repa)" (getVarRepa infile "vf" fwit) , testCase "Read (int, Repa)" (getVarRepa infile "vi" iwit) , testCase "Read (short, Repa)" (getVarRepa infile "vs" swit)+ , testCase "Read (float, hmatrix)" (getVarHMV infile "vf" fwit)+ , testCase "Read (int, hmatrix)" (getVarHMV infile "vi" iwit)+ , testCase "Read (short, hmatrix)" (getVarHMV infile "vs" swit) ], testGroup "Variable slice access functions" [ testCase "Read (float, SV)" (getVarASV infile "vf" fwit)@@ -49,6 +56,9 @@ , testCase "Read (float, Repa)" (getVarARepa infile "vf" fwit) , testCase "Read (int, Repa)" (getVarARepa infile "vi" iwit) , testCase "Read (short, Repa)" (getVarARepa infile "vs" swit)+ , testCase "Read (float, hmatrix)" (getVarAHMV infile "vf" fwit)+ , testCase "Read (int, hmatrix)" (getVarAHMV infile "vi" iwit)+ , testCase "Read (short, hmatrix)" (getVarAHMV infile "vs" swit) ], testGroup "Strided slice access functions" [ testCase "Read (float, SV)" (getVarSSV infile "vf" fwit)@@ -57,6 +67,9 @@ , testCase "Read (float, Repa)" (getVarSRepa infile "vf" fwit) , testCase "Read (int, Repa)" (getVarSRepa infile "vi" iwit) , testCase "Read (short, Repa)" (getVarSRepa infile "vs" swit)+ , testCase "Read (float, hmatrix)" (getVarSHMV infile "vf" fwit)+ , testCase "Read (int, hmatrix)" (getVarSHMV infile "vi" iwit)+ , testCase "Read (short, hmatrix)" (getVarSHMV infile "vs" swit) ] ] @@ -64,6 +77,8 @@ type SVRet a = IO (Either NcError (SV.Vector a)) type RepaRet3 a = IO (Either NcError (R.Array F R.DIM3 a)) type RepaRet1 a = IO (Either NcError (R.Array F R.DIM1 a))+type HMVRet a = IO (Either NcError (H.HVector a))+type HMMRet a = IO (Either NcError (H.HRowMajorMatrix a)) --------------------------------------------------------------------------------@@ -75,7 +90,7 @@ getVar1 :: forall a. (Eq a, Num a, Show a, NcStorable a) => FilePath -> String -> a -> Assertion getVar1 f v _ = do- enc <- openFile f ReadMode+ enc <- openFile f assertBool "failed to open file" $ isRight enc let Right nc = enc case ncVar nc v of@@ -95,31 +110,7 @@ (val == trueval) void $ closeFile nc --- getVar1 :: FilePath -> String -> Assertion--- getVar1 f v = do--- enc <- openFile f ReadMode--- assertBool "failed to open file" $ isRight enc--- let Right nc = enc--- case ncVar nc v of--- Nothing -> assertBool "missing variable" False--- Just var -> do--- let [nz, ny, nx] = map ncDimLength $ ncVarDims var--- typ = ncVarType var--- forM_ [1..nx] $ \ix -> do--- forM_ [1..ny] $ \iy -> do--- forM_ [1..nz] $ \iz -> do--- eval <- get1 nc var [iz-1, iy-1, ix-1] :: IO (Either NcError a)--- case eval of--- Left e -> assertBool ("read error: " ++ show e) False--- Right val -> do--- let trueval = fromIntegral $ ix + 10 * iy + 100 * iz--- assertBool ("value error: " ++ show val ++--- " instead of " ++ show trueval)--- (val == trueval)--- void $ closeFile nc -- -------------------------------------------------------------------------------- -- -- WHOLE VARIABLE READ@@ -129,7 +120,7 @@ getVarSV :: forall a. (Eq a, Num a, Show a, NcStorable a) => FilePath -> String -> a -> Assertion getVarSV f v _ = do- enc <- openFile f ReadMode+ enc <- openFile f assertBool "failed to open file" $ isRight enc let Right nc = enc case ncVar nc v of@@ -153,7 +144,7 @@ getVarRepa :: forall a. (Eq a, Num a, Show a, NcStorable a) => FilePath -> String -> a -> Assertion getVarRepa f v _ = do- enc <- openFile f ReadMode+ enc <- openFile f assertBool "failed to open file" $ isRight enc let Right nc = enc case ncVar nc v of@@ -174,8 +165,32 @@ (and $ zipWith (==) tstvals truevals) void $ closeFile nc +getVarHMV :: forall a. (Eq a, Num a, Show a, NcStorable a)+ => FilePath -> String -> a -> Assertion+getVarHMV f v _ = do+ enc <- openFile f+ assertBool "failed to open file" $ isRight enc+ let Right nc = enc+ case ncVar nc v of+ Nothing -> assertBool "missing variable" False+ Just var -> do+ eval <- get nc var :: HMVRet a+ case eval of+ Left e -> assertBool ("read error: " ++ show e) False+ Right (H.HVector val) -> do+ let [nz, ny, nx] = map ncDimLength $ ncVarDims var+ truevals = [fromIntegral $ ix + 10 * iy + 100 * iz |+ ix <- [1..nx], iy <- [1..ny], iz <- [1..nz]]+ idxs = [(iz - 1) * ny * nx + (iy - 1) * nx + (ix - 1) |+ ix <- [1..nx], iy <- [1..ny], iz <- [1..nz]]+ tstvals = [val C.@> i | i <- idxs]+ assertBool ("value error: " ++ show tstvals +++ " instead of " ++ show truevals)+ (and $ zipWith (==) tstvals truevals)+ void $ closeFile nc + -------------------------------------------------------------------------------- -- -- VARIABLE SLICE READ@@ -185,7 +200,7 @@ getVarASV :: forall a. (Num a, Show a, Eq a, NcStorable a) => FilePath -> String -> a -> Assertion getVarASV f v _ = do- enc <- openFile f ReadMode+ enc <- openFile f assertBool "failed to open file" $ isRight enc let Right nc = enc case ncVar nc v of@@ -232,7 +247,7 @@ getVarARepa :: forall a. (Num a, Show a, Eq a, NcStorable a) => FilePath -> String -> a -> Assertion getVarARepa f v _ = do- enc <- openFile f ReadMode+ enc <- openFile f assertBool "failed to open file" $ isRight enc let Right nc = enc case ncVar nc v of@@ -276,7 +291,54 @@ assertBool ("3: value error: " ++ show tstvals ++ " instead of " ++ show truevals) (tstvals == truevals) +getVarAHMV :: forall a. (Num a, Show a, Eq a, NcStorable a)+ => FilePath -> String -> a -> Assertion+getVarAHMV f v _ = do+ enc <- openFile f+ assertBool "failed to open file" $ isRight enc+ let Right nc = enc+ case ncVar nc v of+ Nothing -> assertBool "missing variable" False+ Just var -> do+ let [nz, ny, nx] = map ncDimLength $ ncVarDims var+ forM_ [1..nx] $ \ix -> do+ forM_ [1..ny] $ \iy -> do+ let start = [0, iy-1, ix-1]+ count = [nz, 1, 1]+ eval <- getA nc var start count :: HMVRet a+ case eval of+ Left e -> assertBool ("read error: " ++ show e) False+ Right vals -> do+ let truevals = H.HVector $ C.buildVector (fromIntegral nz)+ (\iz -> fromIntegral $ ix + 10 * iy + 100 * (iz+1))+ assertBool ("1: value error: " ++ show vals +++ " instead of " ++ show truevals) (vals == truevals)+ forM_ [1..nx] $ \ix -> do+ forM_ [1..nz] $ \iz -> do+ let start = [iz-1, 0, ix-1]+ count = [1, ny, 1]+ eval <- getA nc var start count :: HMVRet a+ case eval of+ Left e -> assertBool ("read error: " ++ show e) False+ Right vals -> do+ let truevals = H.HVector $ C.buildVector (fromIntegral ny)+ (\iy -> fromIntegral $ ix + 10 * (iy+1) + 100 * iz)+ assertBool ("2: value error: " ++ show vals +++ " instead of " ++ show truevals) (vals == truevals)+ forM_ [1..ny] $ \iy -> do+ forM_ [1..nz] $ \iz -> do+ let start = [iz-1, iy-1, 0]+ count = [1, 1, nx]+ eval <- getA nc var start count :: HMVRet a+ case eval of+ Left e -> assertBool ("read error: " ++ show e) False+ Right vals -> do+ let truevals = H.HVector $ C.buildVector (fromIntegral nx)+ (\ix -> fromIntegral $ (ix+1) + 10 * iy + 100 * iz)+ assertBool ("3: value error: " ++ show vals +++ " instead of " ++ show truevals) (vals == truevals) + -------------------------------------------------------------------------------- -- -- STRIDED SLICE READ@@ -286,7 +348,7 @@ getVarSSV :: forall a. (Num a, Show a, Eq a, NcStorable a) => FilePath -> String -> a -> Assertion getVarSSV f v _ = do- enc <- openFile f ReadMode+ enc <- openFile f assertBool "failed to open file" $ isRight enc let Right nc = enc case ncVar nc v of@@ -342,7 +404,7 @@ getVarSRepa :: forall a. (Num a, Show a, Eq a, NcStorable a) => FilePath -> String -> a -> Assertion getVarSRepa f v _ = do- enc <- openFile f ReadMode+ enc <- openFile f assertBool "failed to open file" $ isRight enc let Right nc = enc case ncVar nc v of@@ -403,3 +465,62 @@ assertBool ("3: value error: " ++ show tstvals ++ " instead of " ++ show truevals) (tstvals == truevals)++getVarSHMV :: forall a. (Num a, Show a, Eq a, NcStorable a)+ => FilePath -> String -> a -> Assertion+getVarSHMV f v _ = do+ enc <- openFile f+ assertBool "failed to open file" $ isRight enc+ let Right nc = enc+ case ncVar nc v of+ Nothing -> assertBool "missing variable" False+ Just var -> do+ let [nz, ny, nx] = map ncDimLength $ ncVarDims var+ forM_ [1..nx] $ \ix -> do+ forM_ [1..ny] $ \iy -> do+ forM_ [1..nz] $ \s -> do+ let start = [0, iy-1, ix-1]+ count = [(nz + s - 1) `div` s, 1, 1]+ stride = [s, 1, 1]+ eval <- getS nc var start count stride :: HMVRet a+ case eval of+ Left e -> assertBool ("read error: " ++ show e) False+ Right vals -> do+ let truevals = H.HVector $ C.buildVector+ (fromIntegral $ (nz + s - 1) `div` s)+ (\iz -> fromIntegral $+ ix + 10 * iy + 100 * (iz * s + 1))+ assertBool ("1: value error: " ++ show vals +++ " instead of " ++ show truevals) (vals == truevals)+ forM_ [1..nx] $ \ix -> do+ forM_ [1..nz] $ \iz -> do+ forM_ [1..ny] $ \s -> do+ let start = [iz-1, 0, ix-1]+ count = [1, (ny + s - 1) `div` s, 1]+ stride = [1, s, 1]+ eval <- getS nc var start count stride :: HMVRet a+ case eval of+ Left e -> assertBool ("read error: " ++ show e) False+ Right vals -> do+ let truevals = H.HVector $ C.buildVector+ (fromIntegral $ (ny + s - 1) `div` s)+ (\iy -> fromIntegral $+ ix + 10 * (iy * s + 1) + 100 * iz)+ assertBool ("2: value error: " ++ show vals +++ " instead of " ++ show truevals) (vals == truevals)+ forM_ [1..ny] $ \iy -> do+ forM_ [1..nz] $ \iz -> do+ forM_ [1..nx] $ \s -> do+ let start = [iz-1, iy-1, 0]+ count = [1, 1, (nx + s - 1) `div` s]+ stride = [1, 1, s]+ eval <- getS nc var start count stride :: HMVRet a+ case eval of+ Left e -> assertBool ("read error: " ++ show e) False+ Right vals -> do+ let truevals = H.HVector $ C.buildVector+ (fromIntegral $ (nx + s - 1) `div` s)+ (\ix -> fromIntegral $+ (ix * s + 1) + 10 * iy + 100 * iz)+ assertBool ("3: value error: " ++ show vals +++ " instead of " ++ show truevals) (vals == truevals)
+ test/test-put.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE ScopedTypeVariables #-}++import qualified Data.Map as M+import Data.Maybe+import qualified Data.Vector.Storable as SV+import Control.Error+import Control.Monad+import Foreign.C++import Data.NetCDF+import Data.NetCDF.Vector++main :: IO ()+main = do+ let xdim = NcDim "x" 10 False+ ydim = NcDim "y" 10 False+ nc = emptyNcInfo "tst-put.nc" #+ addNcDim xdim #+ addNcDim ydim #+ addNcVar (NcVar "x" NcDouble [xdim] M.empty) #+ addNcVar (NcVar "y" NcDouble [ydim] M.empty) #+ addNcVar (NcVar "z" NcDouble [xdim, ydim] M.empty)+ let write nc = do+ let xvar = fromJust $ ncVar nc "x"+ yvar = fromJust $ ncVar nc "y"+ zvar = fromJust $ ncVar nc "z"+ put nc xvar $ SV.fromList [1..10 :: CDouble]+ put nc yvar $ SV.fromList [1..10 :: CDouble]+ put nc zvar $ SV.fromList [ 100 * x + y |+ x <- [1..10 :: CDouble],+ y <- [1..10 :: CDouble] ]+ return ()+ withCreateFile nc write (putStrLn . ("ERROR: " ++) . show)