module Graphics.TinyPlot where
import Control.Applicative
import Control.Concurrent
import Control.Monad
import Control.Monad.Trans
import Control.Exception
import Data.Char
import System.IO
import System.Process
import System.FilePath
import Text.Heredoc_RL
import Text.Printf
data PlotData = PlotData {
ps_filename :: String
, ps_handle :: Handle
} deriving(Show)
newData :: FilePath -> IO PlotData
newData ((-<.> ".dat") -> filename) = PlotData filename <$> openFile filename WriteMode
pushData :: (MonadIO m, Fractional num, Real num) => PlotData -> num -> num -> m ()
pushData PlotData{..} (fromRational . toRational -> x :: Double) (fromRational . toRational -> y :: Double) = liftIO $ do
hPutStrLn ps_handle (show x ++ "\t" ++ show y) >> hFlush ps_handle
dat :: PlotData -> String
dat PlotData{..} = printf "\"%s\"" ps_filename
data Plot = Plot {
pl_handle :: ProcessHandle
}
spawnPlot :: String -> String -> IO Plot
spawnPlot ((-<.> ".gnuplot") -> name) plot =
Plot <$> do
writeFile name plot *> spawnProcess "gnuplot" [name]
withPlot :: String -> String -> IO a -> IO a
withPlot ((-<.> ".gnuplot") -> name) plot h = do
writeFile name plot
p <- spawnProcess "gnuplot" [name]
r <- h `finally` terminateProcess p
return r
test = do
d <- newData "plot.dat"
spawnPlot "plot1" [heredoc|
set xrange [0:20]
set yrange [0:400]
done = 0
bind all 'd' 'done = 1'
while(!done) {
plot ${dat d} using 1:2 with lines
pause 1
}
|]
forM_ [0..100] $ \i@(fromInteger -> r) -> do
when (i`mod`10 == 0) $ do
threadDelay (10^6)
pushData d r (r*r / 3.2)