AnyarInc / gnugraph

Header only C++ plotting interface for Gnuplot
Apache License 2.0
10 stars 0 forks source link

Real time plotting of evolving variable? #2

Open Alteregoxxx opened 4 years ago

Alteregoxxx commented 4 years ago

Hello, thank you for your work on this Gnuplot interface! However, as descripted in the issue subject, I'm having really hard time understanding how to plot a variable as it evolves in "realtime". From my knowledge, it should be possible in Gnuplot...

Could you add an example of this kind?

Thank you!

stephenberry commented 4 years ago

Hi! We do plot changing variables during run time. The way this is done is by putting the plot call within a for loop or the simulation loop:

GnuGraph graph;
const size_t n = 200;
vector<vector<double>> vec(n);
for (size_t i = 0; i < n; ++i)
{
   vec[i] = { cos(i / 20.0), sin(i / 30.0), cos(i / 50.0) };
   graph.addLine3D(vec);
   graph.plot3D(); // CALL PLOT WITHIN LOOP FOR LIVE UPDATES
}

Note that this is not very efficient, because it has to redraw the entire graph each frame, but I do not know of other solutions for working with gnuplot. It is however efficient enough for most of our use cases, and there is an addLineSparse3D method that takes in an integer and saves a sample within that many samples (to make the line more sparse and faster to draw).

Alteregoxxx commented 4 years ago

Hi! We do plot changing variables during run time. The way this is done is by putting the plot call within a for loop or the simulation loop:

GnuGraph graph;
const size_t n = 200;
vector<vector<double>> vec(n);
for (size_t i = 0; i < n; ++i)
{
   vec[i] = { cos(i / 20.0), sin(i / 30.0), cos(i / 50.0) };
   graph.addLine3D(vec);
   graph.plot3D(); // CALL PLOT WITHIN LOOP FOR LIVE UPDATES
}

Note that this is not very efficient, because it has to redraw the entire graph each frame, but I do not know of other solutions for working with gnuplot. It is however efficient enough for most of our use cases, and there is an addLineSparse3D method that takes in an integer and saves a sample within that many samples (to make the line more sparse and faster to draw).

Hi! Thank you for the feedback! However, I guess I should have been more clear in posing my question: I was referring to plotting changing variables on a 2D graph at runtime, not 3D graphs :-) Please, can you write an example for such a case, too? Thank you!

stephenberry commented 4 years ago

It's the same idea for 2D plots.

vector<double> x, y;
for (size_t i = 0; i < 200; ++i)
{
   x.push_back(double(i));
   y.push_back(sqrt(x[i]));
   graph.plot(x, y); // call "plot" within the loop for live updates
}
Alteregoxxx commented 4 years ago

It's the same idea for 2D plots.

vector<double> x, y;
for (size_t i = 0; i < 200; ++i)
{
   x.push_back(double(i));
   y.push_back(sqrt(x[i]));
   graph.plot(x, y); // call "plot" within the loop for live updates
}

I see... however I've already tried such approach without success...maybe it can be more clear if I try to explain what I'm trying to do using a code snippet example, let's try:

//some code...
.....
....
// then...
GnuGraph graph;
vector<double> epoch, loss;
double train_cost = 0.0;
for (i = 0; i < max_epoch; ++i) {
train_cost += function_calculating_train_cost();
fprintf(stderr, "epoch: %d; training cost: %g", i+1, train_cost);
epoch.push_back(double(i+1));
loss.push_back(train_cost);
if(i > 0) //To avoid empty vector error
{
  cout << graph.plot(epoch,loss,"y = loss") << '\n';
}

Now, such a code compile correctly and executing it I receive the following output on the console:

epoch: 1; training cost: 0.660959
epoch: 2; training cost: 0.568056

--> At this point the Gnuplot window appears having the first two points traced:

image

then, back on the console output, I get:

epoch: 3; training cost: 0.417634 (class error: 0.00%); validation cost: 0.347399 (class error: 0.00%)

epoch: 4; training cost: 0.287339 (class error: 0.00%); validation cost: 0.237363 (class error: 0.00%)

gnuplot> 1 0.660958503749
         ^
         line 3: invalid command

gnuplot> 2 0.568056269858
         ^
         line 3: invalid command

gnuplot> 3 0.417634077511
         ^
         line 3: invalid command

gnuplot> e
         ^
         line 3: invalid command

epoch: 5; training cost: 0.202103 (class error: 0.00%); validation cost: 0.173506 (class error: 0.00%)

gnuplot> 1 0.660958503749
         ^
         line 3: invalid command

gnuplot> 2 0.568056269858
         ^
         line 3: invalid command

gnuplot> 3 0.417634077511
         ^
         line 3: invalid command

gnuplot> 4 0.287338920589
         ^
         line 3: invalid command

gnuplot> e
         ^
         line 3: invalid command

epoch: 6; training cost: 0.153443 (class error: 0.00%); validation cost: 0.136481 (class error: 0.00%)

and so on, with a repeating "pattern"....

What am I doing wrong? Thank you!

stephenberry commented 4 years ago

That is strange, it looks like you are using it as intended. I will have to look more at what could be the potential problem. Are you using the latest version of gnuplot?

One other question: are you needing live plotting? This library isn't well optimized for live plotting. I haven't tried this project out, but it looks promising: https://github.com/soulthreads/imgui-plot. I have used IMGUI for live plotting in the past, and you can get much better performance.