-- | This module provides the core functionality of the ansigraph package: -- terminal-based graphing for vectors and matrices of real and complex numbers. -- -- This is implemented via a 'Graphable' type class. -- -- __Ansigraph is intended to be used in on of two ways:__ -- -- * __By importing "System.Console.AnsiGraph"__. -- This provides all the functionality we typically use, including the FlexibleInstances -- extension which makes it easier to use graphing functions by allowing instances like -- 'Graphable [Double]'. -- -- -- * __By directly importing "System.Console.AnsiGraph.Core"__, which does not activate FlexibleInstances but -- includes everything else provided by the other module. This just means you must use one of a -- handful of newtype wrappers, namely: 'Graph', 'PosGraph', 'CGraph', 'Mat', 'CMat'. -- These wrappers are also available from the standard module. module System.Console.Ansigraph.Core ( -- * Core Functionality -- *** The Graphable class Graphable (graphWith) , graph , animateWith , animate -- *** Graphing options , AGSettings (..) -- *** Default options , graphDefaults , defaultScaling , blue, pink, white -- *** ANSI data , AnsiColor (..) , Coloring (..) -- *** ANSI helpers , realColors , imagColors , colorSets , invert , setFG , setBG , lineClear , applyColor , withColoring -- * Graphable wrapper types , Graph (..) , CGraph (..) , PosGraph (..) , Mat (..) , CMat (..) -- * Graphing -- *** Horizontal vector graphing , displayRV , displayCV , simpleRender , simpleRenderR -- *** Matrix graphing , matShow , displayMat , displayCMat -- *** Simple (non-ANSI) graphing for strictly-positive data , posgraph , posanim ) where import System.Console.Ansigraph.Internal.Core import System.Console.Ansigraph.Internal.Horizontal import System.Console.Ansigraph.Internal.Matrix import System.Console.ANSI import System.IO (hFlush,stdout) import Control.Concurrent (threadDelay) import Data.List (intersperse,transpose) import Data.Complex (Complex,realPart,imagPart,magnitude) -- | Things that ansigraph knows how to render at the terminal are -- instances of this class. class Graphable a where graphWith :: AGSettings -> a -> IO () -- | Invokes the 'Graphable' type class method 'graphWith' with the -- default 'AGSettings' record, 'graphDefaults'. graph :: Graphable a => a -> IO () graph = graphWith graphDefaults ---- IO / ANSI helpers ---- -- | Pauses for the specified number of µs. pauseFor :: Int -> IO () pauseFor n = hFlush stdout >> threadDelay n -- | 'pauseFor' some time interval, then clear screen and set the cursor at (0,0). next :: Int -> IO () next n = do pauseFor n clearScreen setCursorPosition 0 0 -- | For some number of frames per second, return the corresponding time delta in microseconds. deltaFromFPS :: Int -> Int deltaFromFPS fps = 1000000 `div` fps ---- Animation ---- -- | Any list of a 'Graphable' type can be made into an animation, by -- 'graph'ing each element with a time delay and screen-clear after each. -- 'AGSettings' are used to determine the time delta and any coloring/scaling options. animateWith :: Graphable a => AGSettings -> [a] -> IO () animateWith s xs = let delta = deltaFromFPS $ framerate s in sequence_ $ intersperse (next delta) (graphWith s <$> xs) -- | Perform 'animateWith' using default options. Equivalent to 'graph'ing each member -- of the supplied list with a short delay and screen-clear after each. animate :: Graphable a => [a] -> IO () animate = animateWith graphDefaults ---- Wrappers to avoid needing FlexibleInstances ---- -- | Wrapper type for graph of a real vector/function newtype Graph = Graph { unGraph :: [Double] } -- | Wrapper type for graph of a complex vector/function newtype CGraph = CGraph { unCGraph :: [Complex Double] } -- | Wrapper type for graph of a non-negative real vector/function newtype PosGraph = PosGraph { unPosGraph :: [Double] } -- | Wrapper type for graph of a real two-index vector/two-argument function newtype Mat = Mat { unMat :: [[Double]] } -- | Wrapper type for graph of a complex two-index vector/two-argument function newtype CMat = CMat { unCMat :: [[Complex Double]] } instance Graphable Graph where graphWith s = displayRV s . unGraph instance Graphable CGraph where graphWith s = displayCV s . unCGraph instance Graphable PosGraph where graphWith s = withColoring (realColors s) . putStrLn . simpleRender . unPosGraph instance Graphable Mat where graphWith s = displayMat s . unMat instance Graphable CMat where graphWith s = displayCMat s . unCMat ---- helpers for graphing/animating strictly-positive real functions ---- -- | Display a graph of the supplied (non-negative) real vector. posgraph :: [Double] -> IO () posgraph = graph . PosGraph -- | Display an animation of the supplied list of (non-negative) real vectors. posanim :: [[Double]] -> IO () posanim = animate . map PosGraph