0

I suspect I am using the interactive features of matplotlibsomehow in the wrong way, because I have to wait several seconds between one plot and the next when using the following code and structures.

My data base is a pandas DataFrame of around (3800 x 56) float, with a 3-D hyerachical index.

df = mydf.set_index(['l1','l2','l3'])

I then go on creating the matplotlib figure and axes

fig = plt.figure()
ax = fig.add_subplot(111)
up_button_ax  = fig.add_axes([0.25, 0.15, 0.1, 0.03], facecolor='grey')
up_button= Button(up_button_ax, 'pga_up')
dn_button_ax  = fig.add_axes([0.25, 0.1, 0.1, 0.03], facecolor='grey')
dn_button= Button(dn_button_ax, 'pga_dn')

I struggled with the Slider as I wanted it to take only integers, so I finally went for two buttons and had to use a small object to keep their state.

(not directly my question, but any suggestion whether there are other interactive elements which would avoid creation of this object would be welcome)

class Index(object):
    ind = 0

    def next(self):
        self.ind += 1

    def prev(self):
        self.ind -= 1

callback = Index()

def up_button_on_clicked(mouse_event):
    callback.next()
    plot_data(callback.ind)
    print('up i: {}'.format(callback.ind))
up_button.on_clicked(up_button_on_clicked)

def dn_button_on_clicked(mouse_event):
    callback.prev()
    plot_data(callback.ind)
    print('dn i: {}'.format(callback.ind))
dn_button.on_clicked(dn_button_on_clicked)

def plot_data(i):        
    dfnow = df.xs(df.index.levels[0][i]) #slice by CMOD TUNE
    ax.clear()
    for c_pga in dfnow.index.levels[0]:
        if not(dfnow.xs(c_pga).empty):
            ax.plot(dfnow.xs(c_pga)['L1 (dBm)'],marker = 'o',markersize=1,label=c_pga)
    ax.set_title('CMOD TUNE: {}'.format(df.index.levels[0][i]))

Upon execution, every time I click the button, I see the printout immediately, but have to wait quite a long time to have the data finally plotted.

If, on the other hand, I call plot_data(i) from the shell, plotting is immediate. I am therefore assuming that I am not calling the right drawing functions, but have no clue here.

EDIT

Inspired by a second read of Joe_Kington's reply on discrete Slider (thanks to Tom for this), I thought of adding this simple line to my plot_data(i) function:

fig.canvas.draw()

Drawing is now immediate. I would still be grateful if somebody would point me to the reasons why this is needed.

Michele Ancis
  • 1,265
  • 4
  • 16
  • 29
  • Regarding your secondary question: You can make a discrete slider to take only integers. See the excellent answer by @JoeKington here: https://stackoverflow.com/questions/13656387/can-i-make-matplotlib-sliders-more-discrete – tmdavison Apr 20 '18 at 16:08
  • Thanks @tom -- I had tried the first line suggested, i.e. using a proper `fmt` specification, but had the impression that this was only *displaying* the integer steps, while internally keeping a "continuous" sweep. I decided this would have caused problems as I'm using the slider to index a discrete set of rows in my `df`. I firstly stumbled on what I think would have been the easiest solution of all: specify a step interval. However, the `valstep` keyword is not recognized by my version. https://matplotlib.org/api/widgets_api.html?highlight=slider#matplotlib.widgets.Slider – Michele Ancis Apr 20 '18 at 16:23
  • Yep, I meant the later part of the answer where he subclasses Slider – tmdavison Apr 20 '18 at 16:28
  • Yes, I was up for a quick one yesterday :) I was trying to work around the use of classes, mainly because I'm ignorant. – Michele Ancis Apr 20 '18 at 16:36

0 Answers0