{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE QuasiQuotes #-} 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)