Closed DominiqueMakowski closed 4 months ago
I don't know if you need to use a DataFrame for the purposes of plotting, but I think simulate
is the method you are looking for.
using DataFrames
using SequentialSamplingModels
model = RDM()
_,trace = simulate(model)
df = DataFrame(trace, :auto)
In terms of plotting, you can do the following:
using Plots
using SequentialSamplingModels
model = RDM()
times,trace = simulate(model)
plot(times, trace)
If you want to plot the accumulation process incrementally, you can do something like this:
using GLMakie
using SequentialSamplingModels
model = RDM()
times, evidence = simulate(model)
idx = Observable(1)
ys_1 = @lift(evidence[$idx,1])
ys_2 = @lift(evidence[$idx,2])
fig = lines(times, ys_1, color = :blue, linewidth = 4,
axis = (title = @lift("t = $(round(times[$idx], digits = 1))"),))
lines!(times, ys_2, color = :red, linewidth = 4)
indices = 1:length(times)
record(fig, "time_animation.mp4", indices;
framerate = length(times)) do i
println("i $i")
idx[] = i
end
update
This code is closer, but it throws a type error. I'm not familiar with Makie, so its not immediately clear how to fix the problem. Another improvement would be to generate the lines programatically based on the number of columns in evidence
.
I managed to animate the way I wanted :) Thanks a lot!
See here the result
No problem. If the animation code was written in Julia, do you mind sharing it?
Thanks. Do you know how to generalize to the case with an arbitrary number of options? That was one of the problems I had above.
Maybe I need to make a vector of points similar to points = [(i, j) for (i, j) in zip(x, trace)]
in your code, but adapt it for multiple accumulators rather than simulations
Thanks. Do you know how to generalize to the case with an arbitrary number of options?
Not at the moment, I spent my day on it fighting Makie and my brain is fried 😅
The trick bit was to figure out when to use @lift()
and Observable()
fighting Makie and my brain is fried
Haha. I feel the same.
Perhaps I would consider adding an arguments like n_traces=1
in the simulate()
methods that would return a matrix of n traces, of the length of the longest and potentially filled with missing.
Unfortunately, that approach doesn't generalize well for SSMs with more than 1 accumulators.
There are some alternatives that I considered, but their design tradeoffs do not result in a clear net gain. For example, simulate
could return a matrix with time in the first column and samples from the other accumulators in the other columns. With this approach, its not possible to use plot(simulate(model))
because the matrix needs to be sliced. I could stack the matrices following map
, but the simulation id would be lost. A similar alternative would be to add a simulation id and throw it into a dataframe, but that still doesn't integrate well with Plots or StatsPlots because it requires explicitly calling column names in the plotting function. Although not perfect, the current set up is simple and integrates well with Plots. If I want to plot multiple traces of the RDM and color code the accumulators, I can run this:
p = plot(); foreach(_ -> plot!(p, simulate(RDM()), color = [:red :black], leg = false), 1:4); p
No need to worry about padding with Missing
.
The integration with Makie is poor, but as far as I can tell, the alternatives do not integrate any better. Here, you have to iterate over each accumulator (as far as I can tell):
using Makie
fig = Figure()
ax = Axis(fig[1, 1], yautolimitmargin = (0.2, 0.2))
times, evidence = simulate(RDM())
map(e -> lines!(ax, times, e), eachcol(evidence))
If you wrap that in a function, it is possible to iterate over multiple traces without need for padding.
The plotting of DDMs allows to visualize n traces, but I was wondering if there was a way (I looked at the plotting code but didn't find) to extract the traces as for instance a DataFrame of n traces n* time points?
If not maybe it would be worth adding such a method, to 1) modularize/streamline the plotting code and 2) allow users to extract and flexibly plot (and in my case, animate) the bits and pieces they want