Safe Haskell | None |
---|---|
Language | Haskell2010 |
- runPlotter :: Maybe PlotterOptions -> [Channel] -> IO ()
- data PlotterOptions = PlotterOptions {}
- data Channel
- data AxisType
- data XAxisType
- newHistoryChannel :: forall a. Lookup a => String -> XAxisType -> IO (Channel, a -> Bool -> IO ())
- type Meta = Tree ([String], Either String Int)
- newHistoryChannel' :: String -> IO (Channel, Either Meta (Double, Vector Double) -> IO ())
- newChannel :: forall a. String -> (a -> a -> Bool) -> (a -> SignalTree a) -> IO (Channel, a -> IO ())
- def :: Default a => a
- class Lookup a
Usage
The easiest way to use this library is to use Generic
to derive an instance of Lookup
for your data type, and then use newHistoryChannel
to create a time series plot.
The newHistoryChannel
function will return an action which is used to send new data to the plotter.
For example:
{-# LANGUAGE DeriveGeneric #-} import GHC.Generics ( Generic ) import Accessors ( Lookup ) import Control.Concurrent ( forkIO ) import PlotHo data Foo = = Foo { value1 :: Double , value2 :: Double } deriving Generic instance Lookup Foo messageSender :: (Foo -> Bool -> IO ()) -> IO () messageSender newMessage = go True where go firstMessage = do CC.threadDelay 100000 foo <- receiveFooFromNetworkOrSomething :: IO Foo let reset = firstMessage -- reset on the first message newMessage foo reset go False main :: IO () main = do (channel, newMessage) <- addHistoryChannel "it's foo" XAxisCount _ <- forkIO (messageSender newMessage) runPlotter Nothing [channel]
When main is run, a new channel is created which returns the "new message" action.
messageSender
is then forked and periodically sends new messages to the plotter.
The plotter is then started with runPlotter
.
Dynamic data
(Placeholder)
runPlotter :: Maybe PlotterOptions -> [Channel] -> IO () Source #
fire up the the GUI
data PlotterOptions Source #
Some options
PlotterOptions | |
|
XAxisTime | time since the first message |
XAxisTime0 | time since the first message, normalized to 0 (to reduce plot jitter) |
XAxisCount | message index |
XAxisCount0 | message index, normalized to 0 (to reduce plot jitter) |
:: Lookup a | |
=> String | channel name |
-> XAxisType | what to use for the X axis |
-> IO (Channel, a -> Bool -> IO ()) | return a channel and a "new message" action which can also reset the history |
Simplified time-series channel which automatically generates the signal tree
based on Lookup
.
You have to recompile the plotter if the types change.
The plotter will plot a time series of messages put by the action returned by this function.
The worker should pass True to reset the message history, so sending True the first message and False subsequent messages is a good starting place.
If this is too restrictive, use the more generic newChannel
and use a Tree-like type to represent your data, or use newHistoryChannel'
.
History channel which supports data whose structure can change.
It does NOT automatically generate the signal tree like newHistoryChannel
does.
This returns a channel and an action which takes x-axis value, a vector of y axis values, and a tree which
indexes these y axis values.
If the data structure changes, a new tree should be sent, otherwise there could be indexing errors.
:: String | channel name |
-> (a -> a -> Bool) | Is the signal tree the same? This is used for instance if signals have changed and the plotter needs to rebuild the signal tree. This lets you keep the plotter running and change other programs which send messages to the plotter. |
-> (a -> SignalTree a) | how to build the signal tree |
-> IO (Channel, a -> IO ()) | Return a channel and a "new message" function. You should for a thread which receives messages and calls this action. |
This is the general interface to plot whatever you want.
Use this when you want to give the whole time series in one go, rather than one at a time
such as with addHistoryChannel
.
Using types or data, you must encode the signal tree with the message so that
the plotter can build you the nice signal tree.
For examples of this, see the implementation of addHistoryChannel
and addHistoryChannel'
.