This is beautiful. So simple, so clean. Thank you! <3
How should I change marker style, like in scatter plot from this c++ demo:
if (ImPlot::BeginPlot("Scatter Plot", NULL, NULL)) {
ImPlot::PlotScatter("Data 1", xs1, ys1, 100);
ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f);
ImPlot::SetNextMarkerStyle(ImPlotMarker_Square, 6, ImVec4(0,1,0,0.5f), IMPLOT_AUTO, ImVec4(0,1,0,1));
ImPlot::PlotScatter("Data 2", xs2, ys2, 50);
ImPlot::PopStyleVar();
ImPlot::EndPlot();
}
Looks like some ImPlotStyleVar_...
and SetNext...
methods are missing?
Hi all,
First of all thanks for the amazing work on ImPlot.
I’m trying to use use CImGui/ImPlot to display/process data I receive from a UDP socket. Baslically, my infinite_loop
function (which I renamed listen!
) looks like this :
function listen!(cb::Listener)
cb.stopped = false
@async while true
cb.stopped && break
data = process(copy(recv(cb.socket)))
push!(cb, data)
yield()
end
end
I’ve setup everything following this example with @async
/ yield()
in the renderloop
and everything goes smoothly with low UDP framerate (about 5 UDP frames per seconds).
However I’m loosing UDP frames when the rate at which data is sent to the UDP socket is increased. In the real life application I need to receive and display 3200 bytes every 64 µs. I guess that the Julia scheduler does not yield to the listen!
function often enough for the data to be recv
and processed in time.
Things get better when I yield()
after every instruction in the rendering loop but I’m still loosing a lot of data.
I also tried to get things working with Threads.@spawn
as in this example but without any sucess.
Any hints ?
Thanks !
What if you had the render thread always plot the latest data from an array, while another thread updates that array whenever data is available?
I use that pattern to show updates at 60fps while the data itself updates at 200hz.
What’s the definition of Listener
? Have you tried using Channel
with spawn = true
?
Are you sure the data need to be displayed at this high framerate? That’s about 15000fps. Common monitors have a refresh rate of up to 240Hz.
If what you meant is displaying at a common fps but processing the data every 64us, then I believe the Channel
is enough for this use case.
Data is coming in at about 15 kHz but indeed processing and display is performed at common fps rates (every 20 to 100 ms).
It basically consists in :
- a UDP socket,
- a 2D circular buffer for data, and a 1D circular buffer for storing UDP frames indices (updated every 64 µs)
- 2 arrays which store the current data to be displayed (updated every ~20 ms)
mutable struct Listener <: AbstractArray{Cfloat, 2}
# UDP data
IP_adress :: IPv4
port :: Int
socket :: UDPSocket
# Buffer
capacity :: Int
nb_channels :: Int
first :: Int
length :: Int
buffer :: Array{Cfloat, 2}
indices :: Vector{Int64}
# Current data
current_data :: Array{Cfloat, 2}
current_indices :: Vector{Int64}
counter :: Int64
# State
stopped :: Bool
end
Indeed, that’s what I’m trying to do with @async
tasks and yield()
, but I guess Channel
or Threads@spawn
better suit my needs. Thank you to both of you for the tips; I’ll give it a try and keep you posted.
Got it working with Threads.@spawn
and lock()/unlock()
in both rendering/listening loops.
Thanks @sefffal and @Gnimuc !
Would you mind publishing a simplified example in a gist? I believe this will benefit others in the future.
All examples from cpp demo are now reimplemented in Julia!
@wsphillips can you update first message with this notification, and maybe change gif image to something more interesting from demo examples?