packages feed

liquidhaskell-0.8.0.2: scripts/plot-benchmarks/src/Plot.hs

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleContexts #-}

module Plot where

import Benchmark
import Parse
import qualified Data.Map as Map
import Data.Foldable
import Data.List
import Graphics.Rendering.Chart.Easy
import Graphics.Rendering.Chart.Backend.Diagrams
import Data.Time.LocalTime
import Data.Colour ()
import Data.Colour.Names ()
import System.FilePath

fileOptions :: FileOptions
fileOptions = def-- (def {_fo_size = (1024, 768)} :: FileOptions)

lineColor1 :: AlphaColour Double
lineColor1 = withOpacity darkred 0.5

pointColor1 :: AlphaColour Double
pointColor1 = opaque red

lineColor2 :: AlphaColour Double
lineColor2 = withOpacity darkgreen 0.5

pointColor2 :: AlphaColour Double
pointColor2 = opaque green

plotData :: (Default r, ToRenderable r)
            => FilePath
            -> [(String, [(LocalTime, a)])]
            -> (String -> [(LocalTime, a)] -> EC r ())
            -> IO ()
plotData out dps with = sequence_ $ fmap plotDp dps
   where
      plotDp (n, dps') = do
         let n' = specToUscore n
         let options = fileOptions
         toFile options (out </> n' ++ ".svg") $ with n dps'
      specToUscore s = fmap mapper s
         where
            mapper c = case c of
               '/' -> '_'
               '.' -> '_'
               c' -> c'

plotCompareData :: (Default r, ToRenderable r)
                   => FilePath
                   -> [((String, [(LocalTime, a)]),(String, [(LocalTime, a)]))]
                   -> (String
                       -> String
                       -> ([(LocalTime, a)],[(LocalTime, a)]) -> EC r ())
                   -> IO ()
plotCompareData out dps with = sequence_ $ fmap plotDp dps
   where
      plotDp ((ln, ldps'), (rn, rdps')) = do
         let ln' = specToUscore ln
         let rn' = specToUscore rn
         let dps' = (ldps', rdps')
         let options = fileOptions
         toFile
            options
            (out </> ln' ++ "_vs_" ++ rn' ++ ".svg")
            $ with ln rn dps'
      specToUscore s = fmap mapper s
         where
            mapper c = case c of
               '/' -> '_'
               '.' -> '_'
               c' -> c'

plotCompareTimeData :: FilePath
                       -> [((String, [(LocalTime, Double)]),
                            (String, [(LocalTime, Double)]))]
                       -> IO ()
plotCompareTimeData out dps = plotCompareData out dps with
   where
      with ln rn (ldps, rdps) = do
         layoutlr_title .= ln ++ " vs. " ++ rn ++ " Times"
         setColors [lineColor1, lineColor2, pointColor1, pointColor2]
         setShapes [PointShapeCircle, PointShapeCircle]
         plotLeft $ line "" [ldps]
         plotRight $ line "" [rdps]
         plotLeft $ points ln ldps
         plotRight $ points rn rdps

plotTimeData :: FilePath -> [(String, [(LocalTime, Double)])] -> IO ()
plotTimeData out dps = plotData out dps with
   where
      with n' dps' = do
            layout_title .= n' ++ " Times"
            setColors [lineColor1, pointColor1]
            plot $ line "" [dps']
            plot $ points n' dps'

getCompareData :: ([Benchmark] -> [(LocalTime, a)])
                  -> FilePath
                  -> [(String, String)]
                  -> IO [((String, [(LocalTime, a)]),
                          (String, [(LocalTime, a)]))]
getCompareData mapper f bps = sequence $ fmap pairUp bps
   where
      pairUp (l, r) = do
         [l'] <- getData mapper f [l]
         [r'] <- getData mapper f [r]
         return (l', r')

getData :: ([Benchmark] -> [(LocalTime, a)])
                -> FilePath
                -> [String]
                -> IO [(String, [(LocalTime, a)])]
getData mapper f bs = do
   logs <- gulpLogs f
   let logMaps = fmap toBenchMap logs
   let combined = foldl' unionAppend Map.empty logMaps
   let onlyBs = Map.filterWithKey (\k _ -> k `elem` bs) combined
   let dataPs = Map.toList $ fmap mapper onlyBs
   let sorted =  fmap sortMapper dataPs
   return sorted
   where
      comparator (tsl, _) (tsr, _) = compare tsl tsr
      sortMapper (name, dps) = (name, sortBy comparator dps)

getTimeData :: FilePath -> [String] -> IO [(String, [(LocalTime, Double)])]
getTimeData = getData timeDataMapper


getCompareTimeData :: FilePath
                   -> [(String, String)]
                   -> IO [((String, [(LocalTime, Double)]),
                           (String, [(LocalTime, Double)]))]
getCompareTimeData = getCompareData timeDataMapper

timeDataMapper :: [Benchmark] -> [(LocalTime, Double)]
timeDataMapper bs' = [(benchTimestamp x, benchTime x) | x <- bs' ]



getSuccessData :: FilePath -> [String] -> IO [(String, [(LocalTime, Bool)])]
getSuccessData = getData mapper
   where
      mapper bs' = [(benchTimestamp x, benchPass x) | x <- bs' ]

plotSuccessData :: FilePath -> [(String, [(LocalTime, Bool)])] -> IO ()
plotSuccessData out dps = plotData out dps with
   where
      dps'' v = fmap (\(l, r) -> case r of
                                  True -> (l, (1 :: Integer))
                                  False -> (l, 0)) v
      with n' dps' = do
         layout_title .= n' ++ " Test Result"
         plot (line n' [dps'' dps'])

getAllData :: FilePath -> [String] -> IO [(String, [(LocalTime, Benchmark)])]
getAllData = getData mapper
   where
      mapper bs' = [(benchTimestamp x, x) | x <- bs']