module Graphics.Gnuplot.Private.Plot where
import qualified Graphics.Gnuplot.Private.Display as Display
import qualified Graphics.Gnuplot.Private.FrameOptionSet as OptionSet
import qualified Graphics.Gnuplot.Private.Graph as Graph
import qualified Graphics.Gnuplot.Private.File as FileClass
import qualified Graphics.Gnuplot.File as File
import Graphics.Gnuplot.Utility (quote, commaConcat, )
import qualified Control.Monad.Trans.Reader as MR
import qualified Control.Monad.Trans.State as MS
import qualified Control.Monad.Trans.Class as MT
import qualified Data.Accessor.Monad.Trans.State as AccState
import qualified Data.Accessor.Tuple as AccTuple
import qualified Data.Foldable as Fold
import Control.Monad (liftM2, return, )
import Data.Monoid (Monoid, mempty, mappend, )
import Data.Semigroup (Semigroup, (<>), )
import Data.Maybe (Maybe(Just, Nothing), mapMaybe, )
import Data.List (concatMap, map, (++), )
import Data.Function (($), (.), )
import qualified System.FilePath as Path
import System.FilePath (FilePath, (</>), )
import Prelude (Functor, fmap, String, show, Int, succ, writeFile, )
newtype T graph = Cons (MS.StateT Int (MR.Reader FilePath) [File graph])
pure :: [File graph] -> T graph
pure = Cons . return
instance Semigroup (T graph) where
Cons s0 <> Cons s1 = Cons (liftM2 (<>) s0 s1)
instance Monoid (T graph) where
mempty = Cons $ return mempty
mappend = (<>)
withUniqueFile :: String -> [graph] -> T graph
withUniqueFile content graphs = Cons $ do
n <- MS.get
dir <- MT.lift MR.ask
MS.put $ succ n
return $
[File
(dir </> Path.addExtension (tmpFileStem ++ show n) "csv")
(Just content) graphs]
fromGraphs :: FilePath -> [graph] -> T graph
fromGraphs name gs =
pure [File name Nothing gs]
data File graph =
File {
filename_ :: FilePath,
content_ :: Maybe String,
graphs_ :: [graph]
}
instance FileClass.C (File graph) where
write (File fn cont _) =
Fold.mapM_ (writeFile fn) cont
tmpFileStem :: FilePath
tmpFileStem = "curve"
instance Functor T where
fmap f (Cons mp) =
Cons $
fmap (map (\file -> file{graphs_ = map f $ graphs_ file}))
mp
toScript :: Graph.C graph => T graph -> Display.Script
toScript p@(Cons mp) =
Display.Script $ do
blocks <- AccState.liftT AccTuple.first mp
let files =
mapMaybe
(\blk -> fmap (File.Cons (filename_ blk)) (content_ blk))
blocks
graphs =
concatMap
(\blk ->
map
(\gr ->
quote (filename_ blk) ++ " " ++
Graph.toString gr) $ graphs_ blk) $
blocks
return $
Display.Body files
[Graph.commandString (plotCmd p) ++ " " ++ commaConcat graphs]
optionsToScript :: Graph.C graph => OptionSet.T graph -> Display.Script
optionsToScript opts =
Display.Script $
AccState.liftT AccTuple.second $ do
opts0 <- MS.get
let opts1 = OptionSet.decons opts
MS.put opts1
return $
Display.Body [] $
OptionSet.diffToString opts0 opts1
defltOpts :: Graph.C graph => T graph -> OptionSet.T graph
defltOpts _ = Graph.defltOptions
instance Graph.C graph => Display.C (T graph) where
toScript plot =
optionsToScript (defltOpts plot) `mappend` toScript plot
plotCmd :: Graph.C graph => T graph -> Graph.Command graph
plotCmd _plot = Graph.command