packages feed

zoom-cache 0.7.0.0 → 0.8.0.0

raw patch · 6 files changed

+409/−150 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Data.Iteratee.ZoomCache: StreamNull :: Stream
- Data.Iteratee.ZoomCache: instance NullPoint Stream
- Data.Iteratee.ZoomCache: instance Nullable Stream
- Data.Iteratee.ZoomCache: mapPackets :: (Functor m, MonadIO m) => [IdentifyCodec] -> (Packet -> m ()) -> Iteratee ByteString m ()
- Data.Iteratee.ZoomCache: mapStream :: (Functor m, MonadIO m) => [IdentifyCodec] -> (Stream -> m ()) -> Iteratee ByteString m ()
- Data.Iteratee.ZoomCache: mapSummaries :: (Functor m, MonadIO m) => [IdentifyCodec] -> (ZoomSummary -> m ()) -> Iteratee ByteString m ()
+ Data.Iteratee.ZoomCache: enumCTP :: (Functor m, MonadIO m) => Enumeratee [Stream] [(CacheFile, TrackNo, Packet)] m a
+ Data.Iteratee.ZoomCache: enumCTS :: (Functor m, MonadIO m) => Enumeratee [Stream] [(CacheFile, TrackNo, ZoomSummary)] m a
+ Data.Iteratee.ZoomCache: enumPackets :: (Functor m, MonadIO m) => Enumeratee [Stream] [Packet] m a
+ Data.Iteratee.ZoomCache: enumStreamTrackNo :: (Functor m, MonadIO m) => CacheFile -> TrackNo -> Enumeratee ByteString [Stream] m a
+ Data.Iteratee.ZoomCache: enumSummaries :: (Functor m, MonadIO m) => Enumeratee [Stream] [ZoomSummary] m a
+ Data.Iteratee.ZoomCache: enumSummaryLevel :: (Functor m, MonadIO m) => Int -> Enumeratee [Stream] [ZoomSummary] m a
+ Data.Iteratee.ZoomCache: filterTracks :: (Functor m, MonadIO m) => [TrackNo] -> Enumeratee [Stream] [Stream] m a
+ Data.Iteratee.ZoomCache: filterTracksByName :: (Functor m, MonadIO m) => CacheFile -> [ByteString] -> Enumeratee [Stream] [Stream] m a
+ Data.ZoomCache.Numeric: class (Ord a, Real a, ZoomReadable a, ZoomWritable a) => ZoomNum a
+ Data.ZoomCache.Numeric: enumDouble :: (Functor m, MonadIO m) => Enumeratee [Stream] [(TimeStamp, Double)] m a
+ Data.ZoomCache.Numeric: enumSummaryDouble :: (Functor m, MonadIO m) => Int -> Enumeratee [Stream] [Summary Double] m a
+ Data.ZoomCache.Numeric: numAvg :: ZoomNum a => SummaryData a -> Double
+ Data.ZoomCache.Numeric: numEntry :: ZoomNum a => SummaryData a -> a
+ Data.ZoomCache.Numeric: numExit :: ZoomNum a => SummaryData a -> a
+ Data.ZoomCache.Numeric: numMax :: ZoomNum a => SummaryData a -> a
+ Data.ZoomCache.Numeric: numMin :: ZoomNum a => SummaryData a -> a
+ Data.ZoomCache.Numeric: numRMS :: ZoomNum a => SummaryData a -> Double
+ Data.ZoomCache.Numeric: toSummaryDouble :: Typeable a => Summary a -> Maybe (Summary Double)
- Data.Iteratee.ZoomCache: enumCacheFile :: (Functor m, MonadIO m) => [IdentifyCodec] -> Enumeratee ByteString Stream m a
+ Data.Iteratee.ZoomCache: enumCacheFile :: (Functor m, MonadIO m) => [IdentifyCodec] -> Enumeratee ByteString [Stream] m a
- Data.Iteratee.ZoomCache: enumStream :: (Functor m, MonadIO m) => CacheFile -> Enumeratee ByteString Stream m a
+ Data.Iteratee.ZoomCache: enumStream :: (Functor m, MonadIO m) => CacheFile -> Enumeratee ByteString [Stream] m a
- Data.ZoomCache.Dump: zoomDumpSummaryLevel :: [IdentifyCodec] -> TrackNo -> Int -> FilePath -> IO ()
+ Data.ZoomCache.Dump: zoomDumpSummaryLevel :: Int -> [IdentifyCodec] -> TrackNo -> FilePath -> IO ()

Files

Data/Iteratee/ZoomCache.hs view
@@ -5,33 +5,57 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS -Wall #-} ------------------------------------------------------------------------- |--- Module      : Data.ZoomCache.Write--- Copyright   : Conrad Parker--- License     : BSD3-style (see LICENSE)------ Maintainer  : Conrad Parker <conrad@metadecks.org>--- Stability   : unstable--- Portability : unknown------ Iteratee reading of ZoomCache files.+{- |+   Module      : Data.Iteratee.ZoomCache+   Copyright   : Conrad Parker+   License     : BSD3-style (see LICENSE)++   Maintainer  : Conrad Parker <conrad@metadecks.org>+   Stability   : unstable+   Portability : unknown++   Iteratee reading of ZoomCache files.++   A typical usage, using the iteratee @iter@ to process the level 3 summaries+   from the track called \"rainfall\":++@+  I.fileDriverRandom (enumCacheFile standardIdentifiers .+      I.joinI . filterTracksByName [\"rainfall\"] .+      I.joinI . enumSummaryLevel 3 $ iter) filename+@++   Similarly, using the iteratee @rawIter@ to process the raw data from the+   track called \"rainfall\":++@+  I.fileDriverRandom (enumCacheFile standardIdentifiers .+      I.joinI . filterTracksByName [\"rainfall\"] .+      I.joinI . enumPackets $ rawIter) filename+@+-}+ ----------------------------------------------------------------------  module Data.Iteratee.ZoomCache (-    -- * Types-      Stream(..)+  -- * Types+    Stream(..) -    -- * Parsing iteratees-    , iterHeaders+  -- * Reading zoom-cache files and ByteStrings+  , enumCacheFile -    -- * Enumeratee-    , enumCacheFile-    , enumStream+  , iterHeaders+  , enumStream+  , enumStreamTrackNo -    -- * Iteratee maps-    , mapStream-    , mapPackets-    , mapSummaries+  -- * Stream enumeratees+  , enumPackets+  , enumSummaryLevel+  , enumSummaries+  , enumCTP+  , enumCTS+  , filterTracksByName+  , filterTracks ) where  import Control.Applicative@@ -68,47 +92,128 @@         , strmTrack   :: TrackNo         , strmSummary :: ZoomSummary         }-    | StreamNull -instance I.Nullable Stream where-    nullC StreamNull = True-    nullC _          = False+---------------------------------------------------------------------- -instance I.NullPoint Stream where-    empty = StreamNull+-- | Filter just the raw data+enumPackets :: (Functor m, MonadIO m)+            => I.Enumeratee [Stream] [Packet] m a+enumPackets = I.joinI . enumCTP . I.mapChunks (map (\(_,_,p) -> p)) -----------------------------------------------------------------------+-- | Filter summaries at a particular summary level+enumSummaryLevel :: (Functor m, MonadIO m)+                 => Int+                 -> I.Enumeratee [Stream] [ZoomSummary] m a+enumSummaryLevel level =+    I.joinI . enumSummaries .+    I.filter (\(ZoomSummary s) -> summaryLevel s == level) +-- | Filter summaries at all levels+enumSummaries :: (Functor m, MonadIO m)+              => I.Enumeratee [Stream] [ZoomSummary] m a+enumSummaries = I.joinI . enumCTS .  I.mapChunks (map (\(_,_,s) -> s))++-- | Filter raw data+enumCTP :: (Functor m, MonadIO m)+        => I.Enumeratee [Stream] [(CacheFile, TrackNo, Packet)] m a+enumCTP = I.mapChunks (catMaybes . map toCTP)+    where+        toCTP :: Stream -> Maybe (CacheFile, TrackNo, Packet)+        toCTP StreamPacket{..} = Just (strmFile, strmTrack, strmPacket)+        toCTP _                = Nothing++-- | Filter summaries+enumCTS :: (Functor m, MonadIO m)+        => I.Enumeratee [Stream] [(CacheFile, TrackNo, ZoomSummary)] m a+enumCTS = I.mapChunks (catMaybes . map toCTS)+    where+        toCTS :: Stream -> Maybe (CacheFile, TrackNo, ZoomSummary)+        toCTS StreamSummary{..} = Just (strmFile, strmTrack, strmSummary)+        toCTS _                 = Nothing++-- | Filter to a given list of track names+filterTracksByName :: (Functor m, MonadIO m)+                   => CacheFile+                   -> [ByteString]+                   -> I.Enumeratee [Stream] [Stream] m a+filterTracksByName CacheFile{..} names = filterTracks tracks+    where+        tracks :: [TrackNo]+        tracks = IM.keys (IM.filter f cfSpecs)+        f :: TrackSpec -> Bool+        f ts = specName ts `elem` names++-- | Filter to a given list of track numbers+filterTracks :: (Functor m, MonadIO m)+             => [TrackNo]+             -> I.Enumeratee [Stream] [Stream] m a+filterTracks tracks = I.filter fil+    where+        fil :: Stream -> Bool+        fil StreamPacket{..}  = strmTrack `elem` tracks+        fil StreamSummary{..} = strmTrack `elem` tracks+ -- | An enumeratee of a zoom-cache file, from the global header onwards. -- The global and track headers will be transparently read, and the  -- 'CacheFile' visible in the 'Stream' elements. enumCacheFile :: (Functor m, MonadIO m)               => [IdentifyCodec]-              -> I.Enumeratee ByteString Stream m a-enumCacheFile mappings iter = do-    fi <- iterHeaders mappings+              -> I.Enumeratee ByteString [Stream] m a+enumCacheFile identifiers iter = do+    fi <- iterHeaders identifiers     enumStream fi iter  -- | An enumeratee of zoom-cache data, after global and track headers -- have been read, or if the 'CacheFile' has been acquired elsewhere.+-- This version skips parsing of all tracks other than the specified 'TrackNo'.+--+-- This function should only be used in applications where only one track is+-- used from a file; if you need to process multiple tracks independently then+-- give each an iteratee filtered by filterTracks or filterTracksByName, and+-- run these in parallel on the output of 'enumCacheFile' or 'enumStream'.+-- Using this function multiple times in parallel will duplicate some parsing.+enumStreamTrackNo :: (Functor m, MonadIO m)+                  => CacheFile+                  -> TrackNo+                  -> I.Enumeratee ByteString [Stream] m a+enumStreamTrackNo cf0 trackNo = I.unfoldConvStream go cf0+    where+        go :: (Functor m, MonadIO m)+           => CacheFile+           -> Iteratee ByteString m (CacheFile, [Stream])+        go cf = do+            header <- I.joinI $ I.takeUpTo 8 I.stream2list+            case parseHeader (B.pack header) of+                Just PacketHeader -> do+                    (_, packet) <- readPacketTrackNo (cfSpecs cf) trackNo+                    let res = maybe [] (\p -> [StreamPacket cf trackNo p]) packet+                    return (cf, res)+                Just SummaryHeader -> do+                    (_, summary) <- readSummaryBlockTrackNo (cfSpecs cf) trackNo+                    let res = maybe [] (\s -> [StreamSummary cf trackNo s]) summary+                    return (cf, res)+                _ -> return (cf, [])++-- | An enumeratee of zoom-cache data, after global and track headers+-- have been read, or if the 'CacheFile' has been acquired elsewhere. enumStream :: (Functor m, MonadIO m)             => CacheFile-            -> I.Enumeratee ByteString Stream m a+            -> I.Enumeratee ByteString [Stream] m a enumStream = I.unfoldConvStream go     where         go :: (Functor m, MonadIO m)            => CacheFile-           -> Iteratee ByteString m (CacheFile, Stream)+           -> Iteratee ByteString m (CacheFile, [Stream])         go cf = do             header <- I.joinI $ I.takeUpTo 8 I.stream2list             case parseHeader (B.pack header) of                 Just PacketHeader -> do                     (trackNo, packet) <- readPacket (cfSpecs cf)-                    return (cf, StreamPacket cf trackNo (fromJust packet))+                    return (cf, [StreamPacket cf trackNo (fromJust packet)])                 Just SummaryHeader -> do                     (trackNo, summary) <- readSummaryBlock (cfSpecs cf)-                    return (cf, StreamSummary cf trackNo (fromJust summary))-                _ -> return (cf, StreamNull)+                    return (cf, [StreamSummary cf trackNo (fromJust summary)])+                _ -> return (cf, [])  ------------------------------------------------------------ @@ -130,7 +235,7 @@ iterHeaders :: (Functor m, Monad m)             => [IdentifyCodec]             -> I.Iteratee ByteString m CacheFile-iterHeaders mappings = iterGlobal >>= go+iterHeaders identifiers = iterGlobal >>= go     where         iterGlobal :: (Functor m, Monad m)                    => Iteratee ByteString m CacheFile@@ -147,7 +252,7 @@             header <- I.joinI $ I.takeUpTo 8 I.stream2list             case parseHeader (B.pack header) of                 Just TrackHeader -> do-                    (trackNo, spec) <- readTrackHeader mappings+                    (trackNo, spec) <- readTrackHeader identifiers                     let fi' = fi{cfSpecs = IM.insert trackNo spec (cfSpecs fi)}                     if (fiFull fi')                         then return fi'@@ -167,9 +272,9 @@ readTrackHeader :: (Functor m, Monad m)                 => [IdentifyCodec]                 -> Iteratee ByteString m (TrackNo, TrackSpec)-readTrackHeader mappings = do+readTrackHeader identifiers = do     trackNo <- readInt32be-    trackType <- readCodec mappings+    trackType <- readCodec identifiers     (drType, delta, zlib) <- readFlags     rate <- readRational64be     byteLength <- readInt32be@@ -183,20 +288,49 @@ enumInflateZlib :: (MonadIO m) => I.Enumeratee ByteString ByteString m a enumInflateZlib = enumInflate Zlib defaultDecompressParams -readPacket :: (Functor m, MonadIO m)-           => IntMap TrackSpec-           -> Iteratee ByteString m (TrackNo, Maybe Packet)-readPacket specs = do+readPacketPred :: (Functor m, MonadIO m)+               => IntMap TrackSpec+               -> ((TrackNo, TimeStamp, TimeStamp) -> Bool)+               -> Iteratee ByteString m (TrackNo, Maybe Packet)+readPacketPred specs p = do     trackNo <- readInt32be     entryTime <- TS <$> readInt64be     exitTime <- TS <$> readInt64be     count <- readInt32be     byteLength <- readInt32be-    packet <- case IM.lookup trackNo specs of+    packet <- if (p (trackNo, entryTime, exitTime))+        then do+            readPacketData specs trackNo entryTime exitTime count byteLength+        else do+            I.drop byteLength+            return Nothing+    return (trackNo, packet)++readPacketTrackNo :: (Functor m, MonadIO m)+                  => IntMap TrackSpec+                  -> TrackNo+                  -> Iteratee ByteString m (TrackNo, Maybe Packet)+readPacketTrackNo specs wantTrackNo =+    readPacketPred specs (\(trackNo, _, _) -> trackNo == wantTrackNo)++readPacket :: (Functor m, MonadIO m)+           => IntMap TrackSpec+           -> Iteratee ByteString m (TrackNo, Maybe Packet)+readPacket specs = readPacketPred specs (const True)++readPacketData :: (Functor m, MonadIO m)+               => IntMap TrackSpec+               -> TrackNo+               -> TimeStamp -> TimeStamp+               -> Int+               -> Int+               -> Iteratee ByteString m (Maybe Packet)+readPacketData specs trackNo entryTime exitTime count byteLength =+    case IM.lookup trackNo specs of         Just TrackSpec{..} -> do             let readDTS :: (Functor m, Monad m)                         => Iteratee ByteString m (ZoomRaw, [TimeStamp])-                readDTS = readDataTimeStamps specType specDeltaEncode specDRType count entryTime+                readDTS = readDataTimeStamps specType specDeltaEncode specDRType             (d, ts) <- if specZlibCompress                 then do                     z <- I.joinI $ enumInflateZlib I.stream2stream@@ -207,15 +341,14 @@         Nothing -> do             I.drop byteLength             return Nothing-    return (trackNo, packet)     where         runner1 :: Identity (I.Iteratee s Identity c) -> c         runner1 = runIdentity . I.run . runIdentity          readRawCodec :: (Functor m, Monad m)-                     => Codec -> Bool -> Int+                     => Codec -> Bool                      -> Iteratee ByteString m ZoomRaw-        readRawCodec (Codec a) delta count = ZoomRaw . f <$> replicateM count (readRawAs a)+        readRawCodec (Codec a) delta = ZoomRaw . f <$> replicateM count (readRawAs a)             where                 f | delta     = deltaDecodeRaw                   | otherwise = id@@ -225,45 +358,73 @@         readRawAs = const readRaw          readDataTimeStamps :: (Functor m, Monad m)-                           => Codec -> Bool -> DataRateType -> Int -> TimeStamp+                           => Codec -> Bool -> DataRateType                            -> Iteratee ByteString m (ZoomRaw, [TimeStamp])-        readDataTimeStamps codec delta drType count entry = do-            d <- readRawCodec codec delta count-            ts <- readTimeStamps drType count entry+        readDataTimeStamps codec delta drType = do+            d <- readRawCodec codec delta+            ts <- readTimeStamps drType             return (d, ts)          readTimeStamps :: (Functor m, Monad m)-                       => DataRateType -> Int -> TimeStamp+                       => DataRateType                        -> Iteratee ByteString m [TimeStamp]-        readTimeStamps drType count entry = map TS <$> case drType of+        readTimeStamps drType = map TS <$> case drType of             ConstantDR -> do-                return $ take count [unTS entry ..]+                return $ take count [unTS entryTime ..]             VariableDR -> do                 deltaDecode <$> replicateM count readInt64be -readSummaryBlock :: (Functor m, Monad m)-                 => IntMap TrackSpec-                 -> Iteratee ByteString m (TrackNo, Maybe ZoomSummary)-readSummaryBlock specs = do+readSummaryBlockPred :: (Functor m, Monad m)+                     => IntMap TrackSpec+                     -> ((TrackNo, Int, TimeStamp, TimeStamp) -> Bool)+                     -> Iteratee ByteString m (TrackNo, Maybe ZoomSummary)+readSummaryBlockPred specs p = do     trackNo <- readInt32be     lvl <- readInt32be     entryTime <- TS <$> readInt64be     exitTime <- TS <$> readInt64be     byteLength <- readInt32be+    summary <- if (p (trackNo, lvl, entryTime, exitTime))+        then do+            readSummaryBlockData specs trackNo lvl entryTime exitTime byteLength+        else do+            I.drop byteLength+            return Nothing+    return (trackNo, summary) -    summary <- case IM.lookup trackNo specs of+readSummaryBlockTrackNo :: (Functor m, Monad m)+                        => IntMap TrackSpec+                        -> TrackNo+                        -> Iteratee ByteString m (TrackNo, Maybe ZoomSummary)+readSummaryBlockTrackNo specs wantTrackNo =+    readSummaryBlockPred specs (\(trackNo, _, _, _) -> trackNo == wantTrackNo)++readSummaryBlock :: (Functor m, Monad m)+                 => IntMap TrackSpec+                 -> Iteratee ByteString m (TrackNo, Maybe ZoomSummary)+readSummaryBlock specs = readSummaryBlockPred specs (const True)++readSummaryBlockData :: (Functor m, Monad m)+                     => IntMap TrackSpec+                     -> TrackNo+                     -> Int+                     -> TimeStamp -> TimeStamp+                     -> Int+                     -> Iteratee ByteString m (Maybe ZoomSummary)+readSummaryBlockData specs trackNo lvl entryTime exitTime byteLength =+    case IM.lookup trackNo specs of         Just TrackSpec{..} -> do-            sd <- readSummaryCodec specType trackNo lvl entryTime exitTime-            return $ Just sd+            Just <$> readSummaryCodec specType+            -- sd <- readSummaryCodec specType+            -- return $ Just sd         Nothing -> do             I.drop byteLength             return Nothing-    return (trackNo, summary)     where         readSummaryCodec :: (Functor m, Monad m)-                         => Codec -> TrackNo -> Int -> TimeStamp -> TimeStamp+                         => Codec                          -> Iteratee ByteString m ZoomSummary-        readSummaryCodec (Codec a) trackNo lvl entryTime exitTime = do+        readSummaryCodec (Codec a) = do             ZoomSummary <$> (Summary trackNo lvl entryTime exitTime <$> readSummaryAs a)          readSummaryAs :: (ZoomReadable a, Functor m, Monad m)@@ -272,39 +433,6 @@   ------------------------------------------------------------------------- Convenience functions---- | Map a monadic 'Stream' processing function over an entire zoom-cache file.-mapStream :: (Functor m, MonadIO m)-          => [IdentifyCodec]-          -> (Stream -> m ())-          -> Iteratee ByteString m ()-mapStream mappings = I.joinI . enumCacheFile mappings . I.mapChunksM_-{-# INLINABLE mapStream #-}---- | Map a monadic 'Packet' processing function over an entire zoom-cache file.-mapPackets :: (Functor m, MonadIO m)-           => [IdentifyCodec]-           -> (Packet -> m ())-           -> Iteratee ByteString m ()-mapPackets mappings f = mapStream mappings process-    where-        process StreamPacket{..} = f strmPacket-        process _                = return ()-{-# INLINABLE mapPackets #-}---- | Map a monadic 'Summary' processing function over an entire zoom-cache file.-mapSummaries :: (Functor m, MonadIO m)-             => [IdentifyCodec]-             -> (ZoomSummary -> m ())-             -> Iteratee ByteString m ()-mapSummaries mappings f = mapStream mappings process-    where-        process StreamSummary{..} = f strmSummary-        process _                 = return ()-{-# INLINABLE mapSummaries #-}------------------------------------------------------------------------ -- zoom-cache datatype parsers  readVersion :: (Functor m, Monad m)@@ -314,12 +442,12 @@ readCodec :: (Functor m, Monad m)           => [IdentifyCodec]           -> Iteratee ByteString m Codec-readCodec mappings = do+readCodec identifiers = do     tt <- B.pack <$> (I.joinI $ I.takeUpTo 8 I.stream2list)-    maybe (error "Unknown track type") return (parseCodec mappings tt)+    maybe (error "Unknown track type") return (parseCodec identifiers tt)  parseCodec :: [IdentifyCodec] -> IdentifyCodec-parseCodec mappings h = msum . map ($ h) $ mappings+parseCodec identifiers h = msum . map ($ h) $ identifiers  readFlags :: (Functor m, Monad m)           => Iteratee ByteString m (DataRateType, Bool, Bool)
Data/ZoomCache/Dump.hs view
@@ -24,8 +24,6 @@ ) where  import Control.Applicative ((<$>))-import Control.Monad.Trans (MonadIO)-import Data.ByteString (ByteString) import Data.Int import qualified Data.IntMap as IM import qualified Data.Iteratee as I@@ -37,35 +35,22 @@  zoomInfoFile :: [IdentifyCodec]              -> FilePath -> IO ()-zoomInfoFile mappings path =-    I.fileDriverRandom (iterHeadersBS mappings) path >>= info--zoomDumpFile :: [IdentifyCodec]-             -> TrackNo -> FilePath -> IO ()-zoomDumpFile mappings trackNo =-    I.fileDriverRandom (mapStreamBS mappings (dumpData trackNo))--zoomDumpSummary :: [IdentifyCodec]-                -> TrackNo -> FilePath -> IO ()-zoomDumpSummary mappings trackNo =-    I.fileDriverRandom (mapStreamBS mappings (dumpSummary trackNo))+zoomInfoFile identifiers path =+    I.fileDriverRandom (iterHeaders identifiers) path >>= info -zoomDumpSummaryLevel :: [IdentifyCodec]-                     -> TrackNo -> Int -> FilePath -> IO ()-zoomDumpSummaryLevel mappings trackNo lvl =-    I.fileDriverRandom (mapStreamBS mappings (dumpSummaryLevel trackNo lvl))+zoomDumpFile :: [IdentifyCodec] -> TrackNo -> FilePath -> IO ()+zoomDumpFile = dumpSomething dumpData -----------------------------------------------------------------------+zoomDumpSummary :: [IdentifyCodec] -> TrackNo -> FilePath -> IO ()+zoomDumpSummary = dumpSomething dumpSummary -iterHeadersBS :: [IdentifyCodec]-              -> I.Iteratee ByteString IO CacheFile-iterHeadersBS = iterHeaders+zoomDumpSummaryLevel :: Int+                     -> [IdentifyCodec] -> TrackNo -> FilePath -> IO ()+zoomDumpSummaryLevel lvl = dumpSomething (dumpSummaryLevel lvl) -mapStreamBS :: (Functor m, MonadIO m)-            => [IdentifyCodec]-            -> (Stream -> m ())-            -> I.Iteratee ByteString m ()-mapStreamBS = mapStream+dumpSomething :: (Stream -> IO ()) -> [IdentifyCodec] -> TrackNo -> FilePath -> IO ()+dumpSomething f identifiers trackNo = I.fileDriverRandom+    (I.joinI . enumCacheFile identifiers . I.joinI . filterTracks [trackNo] . I.mapM_ $ f)  ---------------------------------------------------------------------- @@ -75,13 +60,10 @@     mapM_ (putStrLn . uncurry prettyTrackSpec) . IM.assocs $ cfSpecs  streamRate :: Stream -> Maybe Rational-streamRate StreamNull = Nothing-streamRate s          = specRate <$> IM.lookup (strmTrack s) (cfSpecs (strmFile s))+streamRate s = specRate <$> IM.lookup (strmTrack s) (cfSpecs (strmFile s)) -dumpData :: TrackNo -> Stream -> IO ()-dumpData trackNo s@StreamPacket{..}-    | strmTrack == trackNo = mapM_ (\(t,d) -> printf "%s: %s\n" t d) tds-    | otherwise            = return ()+dumpData :: Stream -> IO ()+dumpData s@StreamPacket{..} = mapM_ (\(t,d) -> printf "%s: %s\n" t d) tds     where         pretty = case streamRate s of             Just r  -> prettyTimeStamp r@@ -89,22 +71,20 @@         tds = zip (map pretty (packetTimeStamps strmPacket)) vals         vals = f (packetData strmPacket)         f (ZoomRaw a) = map prettyRaw a-dumpData _ _ = return ()+dumpData _ = return () -dumpSummary :: TrackNo -> Stream -> IO ()-dumpSummary trackNo s@StreamSummary{..}-    | strmTrack == trackNo = case streamRate s of+dumpSummary :: Stream -> IO ()+dumpSummary s@StreamSummary{..} = case streamRate s of         Just r  -> putStrLn $ f r strmSummary         Nothing -> return ()-    | otherwise            = return ()     where         f r (ZoomSummary a) = prettySummary r a-dumpSummary _ _           = return ()+dumpSummary _ = return () -dumpSummaryLevel :: TrackNo -> Int -> Stream -> IO ()-dumpSummaryLevel trackNo level s@StreamSummary{..}-    | level == opLevel strmSummary && strmTrack == trackNo = dumpSummary trackNo s-    | otherwise                                            = return ()+dumpSummaryLevel :: Int -> Stream -> IO ()+dumpSummaryLevel level s@StreamSummary{..}+    | level == opLevel strmSummary = dumpSummary s+    | otherwise                    = return ()     where opLevel (ZoomSummary a) = summaryLevel a-dumpSummaryLevel _ _ _ = return ()+dumpSummaryLevel _ _ = return () 
+ Data/ZoomCache/Numeric.hs view
@@ -0,0 +1,141 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE RecordWildCards #-}+{-# OPTIONS -Wall #-}+----------------------------------------------------------------------+-- |+-- Module      : Data.ZoomCache.Types+-- Copyright   : Conrad Parker+-- License     : BSD3-style (see LICENSE)+--+-- Maintainer  : Conrad Parker <conrad@metadecks.org>+-- Stability   : unstable+-- Portability : unknown+--+-- ZoomCache numeric API+----------------------------------------------------------------------++module Data.ZoomCache.Numeric (+    ZoomNum+  , numEntry+  , numExit+  , numMin+  , numMax+  , numAvg+  , numRMS++  , toSummaryDouble++  , enumDouble+  , enumSummaryDouble++  , module Data.ZoomCache+) where++import Control.Applicative ((<$>))+import Control.Monad.Trans (MonadIO)+import Data.Int+import qualified Data.Iteratee as I+import Data.Maybe+import Data.Typeable+import Data.Word+import Data.ZoomCache+import Data.ZoomCache.Numeric.Types+import Data.ZoomCache.Types++----------------------------------------------------------------------++rawToDouble :: ZoomRaw -> [Double]+rawToDouble (ZoomRaw xs) | typeOf xs == typeOf (undefined :: [Double]) =+                              fromMaybe [] (cast xs :: Maybe [Double])+                         | typeOf xs == typeOf (undefined :: [Float]) =+                                         f (cast xs :: Maybe [Float])+                         | typeOf xs == typeOf (undefined :: [Int]) =+                                         f (cast xs :: Maybe [Int])+                         | typeOf xs == typeOf (undefined :: [Int8]) =+                                         f (cast xs :: Maybe [Int8])+                         | typeOf xs == typeOf (undefined :: [Int16]) =+                                         f (cast xs :: Maybe [Int16])+                         | typeOf xs == typeOf (undefined :: [Int32]) =+                                         f (cast xs :: Maybe [Int32])+                         | typeOf xs == typeOf (undefined :: [Int64]) =+                                         f (cast xs :: Maybe [Int64])+                         | typeOf xs == typeOf (undefined :: [Integer]) =+                                         f (cast xs :: Maybe [Integer])+                         | typeOf xs == typeOf (undefined :: [Word]) =+                                         f (cast xs :: Maybe [Word])+                         | typeOf xs == typeOf (undefined :: [Word8]) =+                                         f (cast xs :: Maybe [Word8])+                         | typeOf xs == typeOf (undefined :: [Word16]) =+                                         f (cast xs :: Maybe [Word16])+                         | typeOf xs == typeOf (undefined :: [Word32]) =+                                         f (cast xs :: Maybe [Word32])+                         | typeOf xs == typeOf (undefined :: [Word64]) =+                                         f (cast xs :: Maybe [Word64])+                         | otherwise = []+    where+        f :: Real a => Maybe [a] -> [Double]+        f = maybe [] (map realToFrac)++----------------------------------------------------------------------++-- | Coercion of numeric summaries to type Summary Double.+toSummaryDouble :: Typeable a => Summary a -> Maybe (Summary Double)+toSummaryDouble s | typeOf s == typeOf (undefined :: Summary Double) =+                                id (cast s :: Maybe (Summary Double))+                  | typeOf s == typeOf (undefined :: Summary Float) =+                            sd <$> (cast s :: Maybe (Summary Float))+                  | typeOf s == typeOf (undefined :: Summary Int) =+                            sd <$> (cast s :: Maybe (Summary Int))+                  | typeOf s == typeOf (undefined :: Summary Int8) =+                            sd <$> (cast s :: Maybe (Summary Int8))+                  | typeOf s == typeOf (undefined :: Summary Int16) =+                            sd <$> (cast s :: Maybe (Summary Int16))+                  | typeOf s == typeOf (undefined :: Summary Int32) =+                            sd <$> (cast s :: Maybe (Summary Int32))+                  | typeOf s == typeOf (undefined :: Summary Int64) =+                            sd <$> (cast s :: Maybe (Summary Int64))+                  | typeOf s == typeOf (undefined :: Summary Integer) =+                            sd <$> (cast s :: Maybe (Summary Integer))+                  | typeOf s == typeOf (undefined :: Summary Word) =+                            sd <$> (cast s :: Maybe (Summary Word))+                  | typeOf s == typeOf (undefined :: Summary Word8) =+                            sd <$> (cast s :: Maybe (Summary Word8))+                  | typeOf s == typeOf (undefined :: Summary Word16) =+                            sd <$> (cast s :: Maybe (Summary Word16))+                  | typeOf s == typeOf (undefined :: Summary Word32) =+                            sd <$> (cast s :: Maybe (Summary Word32))+                  | typeOf s == typeOf (undefined :: Summary Word64) =+                            sd <$> (cast s :: Maybe (Summary Word64))+                  | otherwise = Nothing++    where+        sd :: ZoomNum a => Summary a -> Summary Double+        sd s' = s' { summaryData = toSummaryDataDouble (summaryData s') }+        +toSummaryDataDouble :: ZoomNum a => SummaryData a -> SummaryData Double+toSummaryDataDouble s = numMkSummary+    (realToFrac . numEntry $ s)+    (realToFrac . numExit $ s)+    (realToFrac . numMin $ s)+    (realToFrac . numMax $ s)+    (numAvg s)+    (numRMS s)++----------------------------------------------------------------------++enumDouble :: (Functor m, MonadIO m)+           => I.Enumeratee [Stream] [(TimeStamp, Double)] m a+enumDouble = I.joinI . enumPackets . I.mapChunks (concatMap f)+    where+        f :: Packet -> [(TimeStamp, Double)]+        f Packet{..} = zip packetTimeStamps (rawToDouble packetData)++enumSummaryDouble :: (Functor m, MonadIO m)+                  => Int+                  -> I.Enumeratee [Stream] [Summary Double] m a+enumSummaryDouble level =+    I.joinI . enumSummaryLevel level .+    I.mapChunks (catMaybes . map toSD)+    where+        toSD :: ZoomSummary -> Maybe (Summary Double)+        toSD (ZoomSummary s) = toSummaryDouble s
Data/ZoomCache/Numeric/Types.hs view
@@ -3,7 +3,7 @@ {-# OPTIONS -Wall #-}  module Data.ZoomCache.Numeric.Types (-    -- * Classes+    -- * Summaries of numeric values       ZoomNum(..) ) where @@ -13,11 +13,20 @@ -- ZoomNum  class (Ord a, Real a, ZoomReadable a, ZoomWritable a) => ZoomNum a where+    -- | Value at start of interval     numEntry :: SummaryData a -> a+    -- | Value at end of interval     numExit  :: SummaryData a -> a++    -- | Minimum value in the summary interval     numMin   :: SummaryData a -> a+    -- | Maximum value in the summary interval     numMax   :: SummaryData a -> a++    -- | Mean value in the summary interval     numAvg   :: SummaryData a -> Double++    -- | Root mean square value in the summary interval     numRMS   :: SummaryData a -> Double      numWorkTime  :: SummaryWork a -> TimeStamp@@ -31,4 +40,3 @@     numMkSummary :: a -> a -> a -> a -> Double -> Double -> SummaryData a     numMkSummaryWork :: TimeStamp -> Maybe a -> a -> a -> a -> Double -> Double                      -> SummaryWork a-
tools/zoom-cache.hs view
@@ -202,7 +202,8 @@     (config, filenames) <- liftIO . processArgs =<< appArgs     liftIO . (f (track config)) $ filenames     where-        f trackNo (lvl:paths) = mapM_ (zoomDumpSummaryLevel standardIdentifiers trackNo (read lvl)) paths+        f trackNo (lvl:paths) = mapM_ (zoomDumpSummaryLevel (read lvl)+                                       standardIdentifiers trackNo) paths         f _ _ = putStrLn "Usage: zoom-cache summary n file.zxd"  ------------------------------------------------------------
zoom-cache.cabal view
@@ -3,7 +3,7 @@ -- The package version. See the Haskell package versioning policy -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for -- standards guiding when and how versions should be incremented.-Version:             0.7.0.0+Version:             0.8.0.0  Synopsis:            A streamable, seekable, zoomable cache file format @@ -99,6 +99,7 @@     Data.ZoomCache.Dump     Data.ZoomCache.Format     Data.ZoomCache.Identify+    Data.ZoomCache.Numeric     Data.ZoomCache.Numeric.Delta     Data.ZoomCache.Numeric.FloatMinMax     Data.ZoomCache.Numeric.IEEE754