Easiest way to live plot?

Hey guys, so I have this case; I am running a simulation program which at every time steps outputs a data file, which I then strip for data - I would like to do this and showcase it with a live plot but I am struggling a bit to find a way to update x and y values, so do anyone happen to have some very basic examples of how to proceed with this? Currently I have:

  1. Function to check if new files are added at every 5 seconds
  2. If new files are added then read this data in and put it into x and y array
  3. Then plot

Of course I could just rerun these 3 steps again, but the problem with that is that I would have to reread all the data, instead of just reading the new data added in the folder, so I would rather have it like:

  1. Function to check if new files are added at every 5 seconds
    2a. If new files are added then read this data in and put it into x and y array
    2b. If new files are added after first creation, then update these arrays by appending new data
  2. Then plot

Hope it makese sense.

Kind regards

Since you have a possible strategy laid out, did you just try to implement it? It should be pretty straightforward to keep a list of files that have already been processed and update the data arrays and the plot only when new data shows up.

If you have concrete questions in the process, we’ll be here to help!

Just finishing up my script to gather the new files (difFiles), but I am having a problem in the first iteration:

So this picture shows the new files which are read each 5 seconds. The problem is that it is not reading “Part_0000.bi4”, “Part_0001.bi4” etc., so I am having some trouble in my first iteration of how to tell my program, that in the first iteration, do not use my function, just read the files which are available right now.

Kind regards

Two options come to mind:

  • I assume you know when the first iteration is taking place? If so, you can just code that case manually
  • How do you check if a file has been read? My first idea would be a list (or a set) of paths which you have loaded already. If the a path is already in there, don’t load it. If you run your program for the first time, that list should be empty and all files should be loaded.

Finally got it to work, did it like this:

function test()
    i = 1
    while true
        if i == 1
            difFiles = _dirFiles()
            println(difFiles)
            i = 0
        else
            curFiles = _dirFiles()
            sleep(2.5)
            newFiles = _dirFiles()
            difFiles = setdiff(newFiles,curFiles)
            println(difFiles)
        end
    end
end

Where sleep is a parameter currently set by the user and “_dirFiles” is my implementation of readdir in my case. So now I get an array only having the new names of data to be read.

Kind regards

I think you should be able to simplify it like this, which also avoids calling _dirFiles() back to back:

function test()
    already_loaded = String[]  # the files you have loaded, none in the beginning
    while true
        all_files = _dirFiles()
        new_files = setdiff(all_files, already_loaded)
        println(new_files)
        already_loaded = all_files
        sleep(2.5)
    end
end

This assumes _dirFiles() returns an array of Strings, otherwise you have to change the arrays type.

Thanks! I will look at then when I optimize it later. Now I managed to get the data as I wanted:

image

So this is x-coordinate pr. time step.

Now I just need to figure out how to update the plot with this data, instead of calling plot multiple times. Hope somebody can help out

Kind regards

If you want to update your plot, use plot!(...) instead of plot(...). However, I think that the whole image is re-rendered anyways. If you use something like GR for plotting, that should be pretty quick though.

Using “plot!” I get something like this:

It is constantly adding new legend entries, which I do not want, and it is not continuing the previous lines, ie. I expected a straight line but it is constantly starting from one again. Any suggestions?

The code:

function test()
    i = 1
    while true
        if i == 1
            difFiles = _dirFiles()
            i = 0
        else
            curFiles = _dirFiles()
            sleep(2.5)
            newFiles = _dirFiles()
            difFiles = setdiff(newFiles,curFiles)
        end
        data     = readBi4Body(MovingSquare,Points,difFiles)
        y        = getindex.(mean.(data),1)[:]
        pp = plot!(y)
        display(pp)
    end
end

Kind regards

Replace plot!(y) by plot!(y,label="").

And you currently only provide y values, but I assume you have some x values as well? Maybe just time, on that axis? This is what you would need to modify. This shows what you are currently doing:

plot()
for i in 1:10
    plot!(i:i+5, label = "")
end

But you’d need to provide information about the x values as well:

plot()
for i in 1:10
    plot!(i:i+5, i:i+5, label = "")
end

This should give you something like you are looking for.

(If you are using Juno, add a plot!() at the end to show the plot.)

I would prefer if I did not need to provide x-axis values and just could make it a continous series, but I see…

I use display in Atom to show it yes

Thanks everybody

Thanks, it fixes label problem

You can’t not have x-axis values. If you don’t provide them, Plots invents them for you (otherwise, all y points would land on the same x point, and a vertical line is not what you want either). If you try

a = [1, 2, 4]
plot(a)

this gets expanded to

plot(1:length(a), a)

If you really don’t want to provide x-axis values, you can mix old and new data together and then plot that.

Thanks for the suggestion, my case is a bit more intricate right now, so that solution is not working properly. Will try again in the future, when Julia plotting becomes a bit faster to start up as well.

Thanks for all the help!

Kind regards