2

Every day in my work I need to monitor the evolution of a few scalar values (or display images) in an iterative process that is often very long. I imagine it is a common problem.

So until now I had in my code a loop constructed like this:

scalar_value1_vector=[]
scalar_value2_vector=[]
iterations_vector=[]
N=999999999999999999
display_steps=100

for i in xrange(N):
  new_scalar_value1, new_scalar_value2=perform some calculations(...)
  if (i%display_steps==0):
    scalar_value1_vector.append(new_scalar_value1)
    scalar_value2_vector.append(new_scalar_value2)
    iterations_vector.append(i)
    plt.plot(iterations, scalar_value1, "Scalar value 1")
    plt.plot(iterations, scalar_value2, "Scalar value 2")
    plt.legend()

Runing it I get all kinds of warnings of deprecations from matplotlib saying I should not do that. (Plus the plot is only "active" every iterations and becomes non-interactive and blackish in between each iteration). I figure they want me to use matplotlib.animation objects but it seems a little bit too complicated for my needs (but maybe it is the way to go ?)

What would be the simplest, most lightweight and most elegant solution for basic plotting ? Would it work for images plots (obtained with plt.imshow too?) ?

EDIT: I guess this question is relevant

EDIT 1: I used fig.canvas.draw_idle() in combination with ax.set_data() and fig.canvas.flush_events() but it still is being unresponsive all the time !

scalar_value1_vector=[]
scalar_value2_vector=[]
iterations_vector=[]
N=999999999999999999
display_steps=100
plt.ion()
fig, ax=plt.subplots()
sc1,=ax.plot(steps,scalar_value1_vector, label="Scalar value 1")
sc2,=ax.plot(steps,scalar_value2_vector, label="Scalar value 2")
plt.legend()

for i in xrange(N):
  #calculations that take on average 3 seconds (+-1s)
  new_scalar_value1, new_scalar_value2=perform some calculations(...)
  if (i%display_steps==0):
    scalar_value1_vector.append(new_scalar_value1)
    scalar_value2_vector.append(new_scalar_value2)
    iterations_vector.append(i)
    sc1.set_data(steps,scalar_value1_vector)
    sc2.set_data(steps,scalar_value2_vector)
    fig.canvas.draw_idle()
    try:
      fig.canvas.flush_events()
    except NotImplementedError:
      pass
jeandut
  • 2,471
  • 4
  • 29
  • 56
  • For a comparisson between the interactive plotting and the animation, see e.g. [this answer](https://stackoverflow.com/a/42738014/4124317) or maybe [this one](https://stackoverflow.com/a/45030346/4124317) for images. The "best" solution however will surely depend on how long `perform some calculations(...)` takes and if the time it takes is somehow predictable or constant. The savest way to perform a calculation and show intermediate steps in a plot is clearly using Threads; but that will neither be the simples nor most lightweight way to do it. – ImportanceOfBeingErnest Jul 31 '17 at 13:33
  • Thanks for the answer, I am mostly concerned about simplicity and efficiency (I know both sometimes dont go together). In my case perform some calculations execution time is known to some extents. – jeandut Jul 31 '17 at 13:54
  • The simplest solution is then probably the one in interactive mode. You may also look at [this example](https://matplotlib.org/examples/pylab_examples/system_monitor.html), where `fig.canvas.flush_events()` makes sure the window does not become unresponsive. – ImportanceOfBeingErnest Jul 31 '17 at 14:16
  • Ok will do I will post an updated answer in the next few days if you don't – jeandut Jul 31 '17 at 14:46

0 Answers0