Clearing an interactive animated plot

30 views Asked by At

I have the following simple exmample of animation across subplots and now I am trying to make it interactive. When I changes the parameters via interaction I have know it is calling run because my print statement is outputing the new values. However the chart doesn't redraw.

    %matplotlib widget
    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    import numpy as np
    from ipywidgets import interact
    import ipywidgets as widgets
    
    #sample from a bunch of distributions
    def sample(n):
        x1 = np.random.normal(0, 1, n)
        x2 = np.random.normal(0, 4, n)
        return (x1,x2)
    
    # a function that binds data to outer function and holds them in closure to the 
    #   high-order "update" function returned whcih is called for each animation frame
    def bind_update(sample1, sample2, ax1, ax2, batch=1):
        def update(curr):
            if ((curr % batch) != 0):
                return 
        
            ax1.clear()
            ax1.set_xlim(np.min(sample1), np.max(sample1))
            ax1.set_title(f'Sample 1')
            ax1.hist(sample1[:curr], density=True, bins=20, alpha=0.5)
            
            ax2.clear()
            ax2.set_xlim(np.min(sample2), np.max(sample2))
            ax2.set_title('Sample 2')
            ax2.hist(sample2[:curr], density=True, bins=20, alpha=0.5)
            
    
        return update
    
    @interact(
        interval=widgets.RadioButtons(
            options=[5, 50, 100],
            value=5,
            description='refresh interval:',
            disabled=False
        ),
        batch=widgets.RadioButtons(
            options=[5, 10, 50, 100],
            value=100,
            description='batch size:',
            disabled=False
        ),
        n=widgets.IntSlider(
            value=300,
            min=1,
            max=1000,
            step=1,
            description='Number of Smaples:',
            disabled=False,
            continuous_update=False,
            orientation='horizontal',
            readout=True,
            readout_format='d'
        )
    )
    def run(n, interval, batch): 
        print('run', n, interval, batch)
    
        # set up figure and subplots
        fig, ((ax1,ax2)) =  plt.subplots(1, 2, sharex=False, sharey=False)

        # I have tried these commands below in this space.
        # fig.clf(), fig.clear(), ax1.clear()

        fig.suptitle('Working with subplots', fontsize=15)
        fig.text(0.5, 0.04, 'Value', ha='center', fontsize=13)
        fig.text(0.04, 0.5, 'Frequency', va='center', rotation='vertical', fontsize=13)
    
        # adjust spacing
        plt.subplots_adjust(left=0.15, top=0.85, bottom=0.15, wspace=0.4, hspace=0.4)
        
        # bind data and axis to the update function
        (x1,x2) = sample(n)
        my_update = bind_update(x1, x2, ax1, ax2, batch=batch)
        
        # test the update function
        # my_update(n)
        
        # kick off animation
        return animation.FuncAnimation(
            fig, 
            my_update, 
            frames=n+1,
            interval=interval, 
            repeat=False);

It looks as though a solution is to move this line outside of the function definition:

# set up figure and subplots
fig, ((ax1,ax2)) =  plt.subplots(1, 2, sharex=False, sharey=False)

why is that a solution?

0

There are 0 answers