{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE IncoherentInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} module Amby.Plot ( plot , plotEq , getEC , save , saveSvg , cairoDefSave , diagramsDefSave ) where import Control.Arrow import Control.Monad import Control.Monad.State import qualified Data.List as L import qualified Data.Vector.Generic as G import Data.Default.Class import Graphics.Rendering.Chart.Easy hiding (plot) import qualified Graphics.Rendering.Chart.Easy as Chart import qualified Graphics.Rendering.Chart.Backend.Cairo as Cairo import qualified Graphics.Rendering.Chart.Backend.Diagrams as Diagrams import Lens.Micro import Statistics.Distribution import Amby.Types import Amby.Numeric import Amby.Theme import Amby.Style cairoDefSave :: FilePath cairoDefSave = ".__amby.png" diagramsDefSave :: FilePath diagramsDefSave = ".__amby.svg" getEC :: AmbyChart () -> EC (Layout Double Double) () getEC compute = getLayout $ execState compute def getState :: AmbyChart () -> AmbyState getState compute = execState compute def -- | Quick render. -- Short-hand to render to png file using Cairo backend. save :: AmbyChart () -> IO () save chart = Cairo.toFile def { Cairo._fo_size = size } cairoDefSave (getLayout st) where st = getState chart size = getSize st -- | Short-hand to render to svg using Cairo backend saveSvg :: AmbyChart () -> IO () saveSvg chart = Diagrams.toFile def { Diagrams._fo_size = join (***) fromIntegral size } diagramsDefSave (getLayout st) where st = getState chart size = getSize st -- | Basic x y line plot. instance (G.Vector v Double, G.Vector v (Double, Double)) => AmbyContainer (v Double) Double where plot :: v Double -> v Double -> AmbyChart () plot x y = plotList $ G.toList (G.zip x y) plotEq :: v Double -> (Double -> Double) -> AmbyChart () plotEq x fn = plotList $ G.toList (G.zip x (G.map fn x)) instance (Real a) => AmbyContainer [a] a where plot :: [a] -> [a] -> AmbyChart () plot x y = plotList $ L.zipWith (\a b -> (realToFrac a, realToFrac b)) x y plotEq x fn = plotList $ L.zipWith (\a b -> (realToFrac a, realToFrac b)) x (map fn x) plotList :: [(Double, Double)] -> AmbyChart () plotList plotVals = do theme <- takeTheme layout <- takeLayout putLayout $ layout >> mkLayout theme where linePlot :: EC l (PlotLines Double Double) linePlot = liftEC $ do nextColor <- takeColor plot_lines_values .= [plotVals] plot_lines_style . line_width .= 2.5 plot_lines_style . line_color .= nextColor mkLayout :: Theme -> EC (Layout Double Double) () mkLayout theme = do Chart.plot linePlot