module Simulation.Aivika.Dynamics.Signal
(Signal,
SignalSource,
newSignalSource,
newSignalSourceWithUpdate,
publishSignal,
triggerSignal,
handleSignal,
handleSignal_,
updateSignal,
awaitSignal,
mapSignal,
composeSignal,
apSignal,
filterSignal,
merge2Signals,
merge3Signals,
merge4Signals,
merge5Signals,
SignalHistory,
signalHistorySignal,
newSignalHistory,
readSignalHistory) where
import Data.IORef
import Data.Array
import Control.Monad
import Control.Monad.Trans
import Simulation.Aivika.Dynamics.EventQueue
import Simulation.Aivika.Dynamics.Internal.Signal
import Simulation.Aivika.Dynamics.Internal.Simulation
import Simulation.Aivika.Dynamics.Internal.Dynamics
import Simulation.Aivika.Dynamics.Internal.Cont
import Simulation.Aivika.Dynamics.Internal.Process
import qualified Simulation.Aivika.Vector as V
import qualified Simulation.Aivika.UVector as UV
newSignalSource :: EventQueue -> Simulation (SignalSource a)
newSignalSource queue =
newSignalSourceWithUpdate $ queueRun queue
awaitSignal :: Signal a -> Process a
awaitSignal signal =
Process $ \pid ->
Cont $ \c ->
Dynamics $ \p ->
do r <- newIORef Nothing
let Simulation m =
handleSignal signal $
\a -> Dynamics $
\p -> do x <- readIORef r
case x of
Nothing ->
error "The signal was lost: awaitSignal."
Just x ->
do let Simulation m = x
m $ pointRun p
let Dynamics m = resumeContByParams c a
m p
h <- m $ pointRun p
writeIORef r $ Just h
data SignalHistory a =
SignalHistory { signalHistorySignal :: Signal a,
signalHistoryTimes :: UV.UVector Double,
signalHistoryValues :: V.Vector a }
newSignalHistory :: Signal a -> Simulation (SignalHistory a)
newSignalHistory signal =
do ts <- liftIO UV.newVector
xs <- liftIO V.newVector
handleSignal_ signal $ \a ->
Dynamics $ \p ->
do liftIO $ UV.appendVector ts (pointTime p)
liftIO $ V.appendVector xs a
return SignalHistory { signalHistorySignal = signal,
signalHistoryTimes = ts,
signalHistoryValues = xs }
readSignalHistory :: SignalHistory a -> Dynamics (Array Int Double, Array Int a)
readSignalHistory history =
do updateSignal $ signalHistorySignal history
xs <- liftIO $ UV.freezeVector (signalHistoryTimes history)
ys <- liftIO $ V.freezeVector (signalHistoryValues history)
return (xs, ys)