0

I'm not too used to matplotlib dynamic plots, and thus I have some difficulties to create a desired plot. I'm trying to plot N timelines (not too much, less say less than 5) of the same large size (800k points). I would like to use a slider to represent this.

import numpy as np from matplotlib import pyplot as plt from matplotlib.widgets import Slider plt.ioff() timelines = [np.random.randint(-2, 5, size = 800000), np.random.randint(-2, 5, size = 800000), np.random.randint(-2, 5, size = 800000)] timelines_labels = ["label1", "label2", "label3"] def slide_plot(timelines, timelines_labels): f, ax = plt.subplots(len(timelines), 1, sharex = True, figsize = (20, 10)) def update(pos, ax = ax, timelines = timelines): for k, a in enumerate(ax): a.axis([pos,pos+80,-max(timelines[k])-1, max(timelines[k])+1]) f.canvas.draw_idle() f.subplots_adjust(bottom=0.25) plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False) t = np.arange(0.0, len(timelines[0]), 1) for k, a in enumerate(ax): a.plot(t, timelines[k], lw = 0.55, label=timelines_labels[k]) a.legend(loc="upper right") a.axis([0, 160000, -max(timelines[k])-1, max(timelines[k])+1]) ax[-1].set_xticks(np.arange(0.0, len(timelines[0])+80000, 80000)) axpos = plt.axes([0.2, 0.1, 0.65, 0.03]) spos = Slider(axpos, 'Time (ms)', valmin =0, valmax=800000, valinit=0) spos.on_changed(update) plt.show() slide_plot(timelines, timelines_labels) 

As you see, since my plots are sharing the X-axis, I'm taking out the xticks labels (will do the same with the xticks later) from all the axis except the bottom one.

Then I create the variable t which is just the time, I feel like it is useless, and ax[k].plot(timelines[k]) would be enough.

I do some more formatting by setting one tick every 80000 points.

And finally, I got the slider. Obviously, the update function does not work. I do not know the correct syntax, nor the right way to achieve this.

Thanks :)

EDIT: By placing the argument ax = ax and timelines = timelines it seems to start working, however I do not like the look of the function. I'm quite sure a better way exist.

EDIT: Latest script... And the output:

output

8
  • Your indentation seems screwed, please verify it and fix it. Further, you never call slide_plot Commented Aug 10, 2018 at 11:07
  • @ReblochonMasque No the indentation is correct. Indeed I didn't had the line with the call... I just build that dummy example with the randoms. Commented Aug 10, 2018 at 11:14
  • With the slight change in the EDIT, update doesn't crash. However, the scrollbar doesn't work, and the window is equal to the complete set of points :/ Commented Aug 10, 2018 at 11:24
  • You may directly use def update(pos): and remove the line pos = spos.val if you want. However the code as it currently is would already work. Hence the question where and how are you running this? Commented Aug 10, 2018 at 11:33
  • @ImportanceOfBeingErnest Interesting. I've started the try with this post: stackoverflow.com/questions/31001713/… which works once the axcolors lines are taken out. I'm using spyder, I've first set %matplotlib in the Ipytohn Constrole to open a new windows with the plots. The exammple in the post works, however, we my scenario, the scrolling bar doesn't work. Commented Aug 10, 2018 at 11:38

1 Answer 1

1

The problem should only occur in IPython (or Spyder using IPython). The problem is that plt.show() will not block and the function slide_plot will return. Once it returned, all references to the slider and hence the callbacks are gone. (The code in this linked answer does not use a function, hence this problem does not occur there.)

A solution is to let the function return a reference to the slider and store it.

import numpy as np from matplotlib import pyplot as plt from matplotlib.widgets import Slider timelines = [np.random.randint(-2, 5, size = 800000), np.random.randint(-2, 5, size = 800000), np.random.randint(-2, 5, size = 800000)] timelines_labels = ["label1", "label2", "label3"] def slide_plot(timelines, timelines_labels): f, ax = plt.subplots(len(timelines), 1, sharex = True) def update(pos): for k, a in enumerate(ax): a.axis([pos,pos+25,-max(timelines[k])-1, max(timelines[k])+1]) f.canvas.draw_idle() f.subplots_adjust(bottom=0.25) plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False) t = np.arange(0.0, len(timelines[0]), 1) for k, a in enumerate(ax): a.plot(t, timelines[k], lw = 0.55, label=timelines_labels[k]) a.legend(loc="upper right") a.axis([0, 25, -max(timelines[k])-1, max(timelines[k])+1]) ax[-1].set_xticks(np.arange(0.0, len(timelines[0]) / 8000, 10)) axpos = plt.axes([0.2, 0.1, 0.65, 0.03]) spos = Slider(axpos, 'Time (ms)', 0.1, 90.0) spos.on_changed(update) plt.show() return spos slider = slide_plot(timelines, timelines_labels) 

Alternatively you may configure Spyder not to use its "matplotlib graphics support" under Preferences/IPython/Graphics, disable "Activate support" and start a new IPython console to let this take effect.

Sign up to request clarification or add additional context in comments.

1 Comment

Well thanks a lot, I would never have guessed it x')

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.