Search code examples
pythonpython-3.xuser-interfacejupyter-notebookipywidgets

How to stop flickering while dragging the slider in interact feature of ipywidgets in Jupyter notebook in Python?


I have written a function to display bar plots in a certain order. The function takes demand as an argument.

The code looks as follows:

def display_plot(demand = 0):
    
    plt.figure(figsize = (20, 10))
    
    x = ["A","B","C","D","E","F","G","H"]
    y = [-25, -10, 5, 10, 30, 40, 50, 60]
    w = [300, 200, 205, 400, 200, 400, 540, 630]
    w_cumulative = [300, 500, 705, 1105, 1305, 1705, 2245, 2875]

    colors = ["yellow","limegreen","green","blue","red","brown","grey","black"]

    xpos = [150.0, 400.0, 602.5, 905.0, 1205.0, 1505.0, 1975.0, 2560.0]

    fig = plt.bar(xpos,
            height = y,
            width = w,
            color = colors,
            alpha = 0.5,
          )
    
    #For loop to get the cutoff value 
    for index in range(len(w_cumulative)):

        if w_cumulative[index] < demand:
            pass

        else:
            cut_off_index = index
            print (cut_off_index)
            break

    plt.hlines(y = y[cut_off_index],
          xmin = 0,
          xmax = demand,
          color = "red",
          linestyle = "dashed")
        
    plt.xlim((0, w_cumulative[-1]))

    plt.vlines(x = demand,
              ymin = 0,
              ymax = y[cut_off_index])
    
    plt.text(x = demand - 5,
            y = y[cut_off_index]+5,
            s = str(y[cut_off_index]))

    plt.show()
    

I tried to interact with the plot created by this function. The user-defined feature here is demand. When I change the demand, the hlines and vlines change accordingly. As well as the text such that the height of each bar is displayed.

Using

from ipywidgets import *
interact(display_plot, demand = (0, sum(w), 10))

I am getting the desired output, which is as shown enter image description here

When I click at a point on the slider to change value, it is relatively fine. However, when I drag the slider, the plot flickers a lot. This is very annoying. I think this is because of the for-loop I have used inside the display_plot function, which calculates the instantaneous value of cut_off_index while changing demand by dragging the slider.

I tried adding clear_output(wait=True) inside display_plot() function by calling from from IPython.display import clear_output. I also tried adding time.sleep(1) inside the function. However, the plot is still flickering a lot while dragging the slider. The height of the plot is always constant. But only the contents inside it needs to be updated when I interact. Is there any way to avoid flickering the plot in this case?


Solution

  • Ok. This helped me to avoid flickering.

    I used the following code for interactive output:

    demand = widgets.IntSlider(value = 10,
                              min = 0, 
                              max = sum(w),
                              step = 10,
                              description = "Demand",
                              continuous_update = False)
    
    interactive_plot = interact(display_plot,
                               demand = demand)