{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-} module Eventlog.Bands (bands, series, bandsToSeries) where import Control.Monad (forM_) import Control.Monad.ST (runST) import Data.Array.Base (unsafeFreezeSTUArray, (!), bounds) import Data.Array.ST (writeArray, readArray, newArray) import Data.Array.Unboxed (UArray) import Data.Map (Map, lookup, size, foldrWithKey) import Prelude hiding (lookup, lines, words, length) import Data.Text (Text) import Eventlog.Types import Data.HashTable.ST.Basic hiding (lookup) import Data.Aeson hiding (Series) import GHC.Generics import Data.Set (Set, notMember) bands :: Header -> Map Text Int -> [Frame] -> (UArray Int Double, UArray (Int, Int) Double) bands h bs frames = runST $ do times <- newArray (1, hCount h) 0 vals <- newArray ((-1,1), (size bs, hCount h)) 0 forM_ (zip [1 ..] frames) $ \(i, (Frame t ss)) -> do writeArray times i t forM_ ss $ \(Sample k v) -> do case k `lookup` bs of Nothing -> writeArray vals (0, i) . (+ v) =<< readArray vals (0, i) Just b -> writeArray vals (b, i) v times' <- unsafeFreezeSTUArray times vals' <- unsafeFreezeSTUArray vals return (times', vals') bandsToSeries :: Map Text Int -> (UArray Int Double, UArray (Int, Int) Double) -> [Series] bandsToSeries ks (ts, vs) = let (t1, tn) = bounds ts go k v rs = Series k go_1 : rs where go_1 :: [(Double, Double)] go_1 = flip map [t1 .. tn] $ \t -> (ts ! t, vs ! (v, t)) in foldrWithKey go (go "OTHER" 0 []) ks data Series = Series { key :: Text, values :: [(Double, Double)] } deriving (Show, ToJSON, Generic) series :: Set Text -> [Frame] -> [Series] series ks fs = runST $ do m <- new forM_ (reverse fs) $ \(Frame t s) -> forM_ s $ \(Sample k v) -> do let ins _ | notMember k ks = (Nothing, ()) ins Nothing = (Just [(t, v)] , ()) ins (Just ss) = (Just ((t,v) : ss), ()) mutate m k ins foldM (\r (k,v) -> return (Series k v : r)) [] m