0

I'm using the Player class as found at Managing dynamic plotting in matplotlib Animation module to create an animation and can't figure out how to modify the initial values to prevent the animation from starting automatically. Below is the code for Player, along with a simple example, where I graph the unit circle and have arrows tracing out the unit circle as the frames advance:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from mpl_toolkits.axes_grid1 import make_axes_locatable
import mpl_toolkits
import matplotlib.widgets
from matplotlib.figure import Figure

class Player(FuncAnimation):
    def __init__(self, fig, func, frames=None, init_func=None, 
    fargs=None,save_count=None, mini=0, maxi=100, pos=(0.125, 0.92), **kwargs):
    self.i = 0
    self.min=mini
    self.max=maxi
    self.runs = True
    self.forwards = True

    self.fig = fig
    self.func = func
    self.setup(pos)
    FuncAnimation.__init__(self,self.fig, self.func, frames=self.play(),
                                       init_func=init_func, fargs=fargs,
                                       save_count=save_count,interval=500, **kwargs )


    def play(self):
        while self.runs:
            self.i = self.i+self.forwards-(not self.forwards)
            if self.i > self.min and self.i < self.max:
                yield self.i
            else:
                self.stop()
                yield self.i

    def start(self):
        if self.i==self.max:
            self.i=0
        self.runs=True
        self.event_source.start()

    def stop(self, event=None):
        self.runs = False
        self.event_source.stop()

    def forward(self, event=None):
        self.forwards = True
        self.start()

    def backward(self, event=None):
        self.forwards = False
        self.start()

    def oneforward(self, event=None):
        if self.i==self.max:
            self.i=0
        self.forwards = True
        self.onestep()
    def onebackward(self, event=None):
        self.forwards = False
        self.onestep()

    def onestep(self):
        if self.i > self.min and self.i < self.max:
            self.i = self.i+self.forwards-(not self.forwards)
        elif self.i == self.min and self.forwards:
            self.i+=1
        elif self.i == self.max and not self.forwards:
            self.i-=1
        self.func(self.i)
        self.fig.canvas.draw_idle()

    def setup(self, pos):
        playerax = self.fig.add_axes([0.4, 0.92, 0.22, 0.03])

        divider = mpl_toolkits.axes_grid1.make_axes_locatable(playerax)
        bax = divider.append_axes("right", size="80%", pad=0.05)
        sax = divider.append_axes("right", size="80%", pad=0.05)
        fax = divider.append_axes("right", size="80%", pad=0.05)
        ofax = divider.append_axes("right", size="100%", pad=0.05)
        self.button_oneback = matplotlib.widgets.Button(playerax , label=u'$\u29CF$')
        self.button_back = matplotlib.widgets.Button(bax, label=u'$\u25C0$')
        self.button_stop = matplotlib.widgets.Button(sax, label=u'$\u25A0$')
        self.button_forward = matplotlib.widgets.Button(fax, label=u'$\u25B6$')
        self.button_oneforward = matplotlib.widgets.Button(ofax, label=u'$\u29D0$')
        self.button_oneback.on_clicked(self.onebackward)
        self.button_back.on_clicked(self.backward)
        self.button_stop.on_clicked(self.stop)
        self.button_forward.on_clicked(self.forward)
        self.button_oneforward.on_clicked(self.oneforward)


######## EXAMPLE ##################
#######################################

fig, ax = plt.subplots()

t=np.linspace(0,1, num=100)
unit_circle_x=np.cos(2*np.pi*t)
unit_circle_y=np.sin(2*np.pi*t)
ax.plot(unit_circle_x,unit_circle_y)
ax.set_xlim(-1.2, 1.2)
ax.set_ylim(-1.2,1.2)

# arrow tracing out unit circle
n=3
unit_vector_x=np.cos(2*np.pi*n*t)
unit_vector_y=np.sin(2*np.pi*n*t)


unit_circle_vector=ax.quiver(0, 0, unit_vector_x[0], unit_vector_y[0], angles='xy', scale_units='xy', scale=1,headwidth=10)
ax.set_aspect("equal")

def update(i):

    unit_circle_vector.set_UVC(unit_vector_x[i],unit_vector_y[i])
    ax.set_xlabel(r'$i= $'+str(i),rotation=0,labelpad=10)

ani = Player(fig, update, maxi=len(t)-1)

plt.show()
fishbacp
  • 1,123
  • 3
  • 14
  • 29

1 Answers1

1

You could initiate your self.runs variable to False and modify the play methods such that it yields the current position when self.runs=False:

def play(self):
    while not self.runs:
        yield self.i
    while self.runs:
        self.i = self.i+self.forwards-(not self.forwards)
        if self.i > self.min and self.i < self.max:
            yield self.i
        else:
            self.stop()
            yield self.i

See full code below:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from mpl_toolkits.axes_grid1 import make_axes_locatable
import mpl_toolkits
import matplotlib.widgets
from matplotlib.figure import Figure

class Player(FuncAnimation):
    def __init__(self, fig, func, frames=None, init_func=None, 
        fargs=None,save_count=None, mini=0, maxi=100, pos=(0.125, 0.92), **kwargs):
        self.i = 0
        self.min=mini
        self.max=maxi
        self.runs = False
        self.forwards = True

        self.fig = fig
        self.func = func
        self.setup(pos)
        FuncAnimation.__init__(self,self.fig, self.func, frames=self.play(),
                                           init_func=init_func, fargs=fargs,
                                           save_count=save_count,interval=500, **kwargs )

    def play(self):
        while not self.runs:
            yield self.i
        while self.runs:
            self.i = self.i+self.forwards-(not self.forwards)
            if self.i > self.min and self.i < self.max:
                yield self.i
            else:
                self.stop()
                yield self.i

    def start(self):
        if self.i==self.max:
            self.i=0
        self.runs=True
        self.event_source.start()

    def stop(self, event=None):
        self.runs = False
        self.event_source.stop()

    def forward(self, event=None):
        self.forwards = True
        self.start()

    def backward(self, event=None):
        self.forwards = False
        self.start()

    def oneforward(self, event=None):
        if self.i==self.max:
            self.i=0
        self.forwards = True
        self.onestep()
    def onebackward(self, event=None):
        self.forwards = False
        self.onestep()

    def onestep(self):
        if self.i > self.min and self.i < self.max:
            self.i = self.i+self.forwards-(not self.forwards)
        elif self.i == self.min and self.forwards:
            self.i+=1
        elif self.i == self.max and not self.forwards:
            self.i-=1
        self.func(self.i)
        self.fig.canvas.draw_idle()

    def setup(self, pos):
        playerax = self.fig.add_axes([0.4, 0.92, 0.22, 0.03])

        divider = mpl_toolkits.axes_grid1.make_axes_locatable(playerax)
        bax = divider.append_axes("right", size="80%", pad=0.05)
        sax = divider.append_axes("right", size="80%", pad=0.05)
        fax = divider.append_axes("right", size="80%", pad=0.05)
        ofax = divider.append_axes("right", size="100%", pad=0.05)
        self.button_oneback = matplotlib.widgets.Button(playerax , label=u'$\u29CF$')
        self.button_back = matplotlib.widgets.Button(bax, label=u'$\u25C0$')
        self.button_stop = matplotlib.widgets.Button(sax, label=u'$\u25A0$')
        self.button_forward = matplotlib.widgets.Button(fax, label=u'$\u25B6$')
        self.button_oneforward = matplotlib.widgets.Button(ofax, label=u'$\u29D0$')
        self.button_oneback.on_clicked(self.onebackward)
        self.button_back.on_clicked(self.backward)
        self.button_stop.on_clicked(self.stop)
        self.button_forward.on_clicked(self.forward)
        self.button_oneforward.on_clicked(self.oneforward)


######## EXAMPLE ##################
#######################################

fig, ax = plt.subplots()

t=np.linspace(0,1, num=100)
unit_circle_x=np.cos(2*np.pi*t)
unit_circle_y=np.sin(2*np.pi*t)
ax.plot(unit_circle_x,unit_circle_y)
ax.set_xlim(-1.2, 1.2)
ax.set_ylim(-1.2,1.2)

# arrow tracing out unit circle
n=3
unit_vector_x=np.cos(2*np.pi*n*t)
unit_vector_y=np.sin(2*np.pi*n*t)


unit_circle_vector=ax.quiver(0, 0, unit_vector_x[0], unit_vector_y[0], angles='xy', scale_units='xy', scale=1,headwidth=10)
ax.set_aspect("equal")

def update(i):

    unit_circle_vector.set_UVC(unit_vector_x[i],unit_vector_y[i])
    ax.set_xlabel(r'$i= $'+str(i),rotation=0,labelpad=10)

ani = Player(fig, update, maxi=len(t)-1)

plt.show()

And here is the result:

enter image description here

jylls
  • 4,395
  • 2
  • 10
  • 21