Python: Animating a vector using mplot3d and animation
<p>I'm trying to make a 3d plot with Matplotlib and the animation package from matplotlib. In addition, the animation should be a part of a Gui generated using PyQt and Qt-Designer. Currently I'm stuck on using the "animation.Funcnimation()" correctly, at least i think so...
So here is my code:</p>

<pre><code>import sys
from PyQt4.uic import loadUiType
from PyQt4 import QtGui

from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib import animation

import numpy as np
import Quaternion as qt

Ui_MainWindow, QMainWindow = loadUiType('Newsphere.ui')

class Kinematic(Ui_MainWindow, QMainWindow):
    def __init__(self):
        super(Kinematic, self).__init__()
        self.setupUi(self)

        self.fig = plt.figure()
        self.ax = self.fig.add_subplot(111,projection = '3d')
        self.fig.tight_layout()

        self.ani = animation.FuncAnimation(self.fig, self.update,
                                       init_func=self.setup_plot, blit=True)

        self.canvas = FigureCanvas(self.fig)
        self.mplvl.addWidget(self.canvas)
        self.canvas.draw()

    def setup_plot(self):
        self.ax.view_init(40, 45)

        self.ax.set_xlabel('X')
        self.ax.set_ylabel('Y')
        self.ax.set_zlabel('Z')

        self.ax.set_xlim3d(-1,1)
        self.ax.set_ylim3d(-1,1)
        self.ax.set_zlim3d(-1,1)

        g_x = np.matrix([[1.0],[0.0],[0.0]])
        g_y = np.matrix([[0.0],[1.0],[0.0]])
        g_z = np.matrix([[0.0],[0.0],[1.0]])

        self.ax.plot([0,g_x[0]], [0,g_x[1]], [0,g_x[2]], label='$X_0$')
        self.ax.plot([0,g_y[0]], [0,g_y[1]], [0,g_y[2]], label='$Y_0$')
        self.ax.plot([0,g_z[0]], [0,g_z[1]], [0,g_z[2]], label='$Z_0$')

        self.vek, = self.ax.plot([0,-1], [0,0], [0,0], label='$g \cdot R$', animated=True)

        self.ax.legend(loc='best')
        self.ax.scatter(0,0,0, color='k')

        return self.vek,

    def update(self, i):
        b = self.bslider.value() / 100

        g = np.matrix([[1.0],[0.0],[0.0]])
        q = np.array([0,b,0.5,0])

        R = qt.QtoR(q)
        x, y, z = R*g

        self.vek, = self.ax.plot([0,x], [0,y], [0,z], label='$g \cdot R$', animated=True) #the rotated vector
        return self.vek,

if __name__ == '__main__':

app = QtGui.QApplication(sys.argv)

main = Kinematic()
main.show()

sys.exit(app.exec_())
</code></pre>

<p>You won't be able to run it by just copy-paste because you don't have the file "Newsphere.ui" (Line 13) and the Quaternion.py (Line 11). So when I run it, I get the following (actually like I wish!):
<a href="http://i.stack.imgur.com/yavp5.png" rel="nofollow">Coordinate system</a> </p>

<p>My goal is now to draw a vector (Line 50) and animate it (Line 66) using data which I get from the Gui-slider (Line 58). Can anyone help me with this? I'm stuck with this for days!</p>

<p>So if someone is interested in a solution of the mentioned problem, here we go: (again it is not a code for copy-paste because of the missing 'Newsphere.ui', but I try to explain the important snippets)</p>

<pre><code>import sys
from PyQt4.uic import loadUiType
from PyQt4 import QtGui

from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib import animation

import numpy as np

Ui_MainWindow, QMainWindow = loadUiType('Newsphere.ui')

class Kinematic(Ui_MainWindow, QMainWindow):

    def __init__(self):
        super(Kinematic, self).__init__()
        self.setupUi(self)

        self.fig = plt.figure()
        self.ax = self.fig.add_subplot(111,projection = '3d')
        self.fig.tight_layout()
        self.ax.view_init(40, -45)

        # dashed coordinate system
        self.ax.plot([0,1], [0,0], [0,0], label='$X_0$', linestyle="dashed")
        self.ax.plot([0,0], [0,-1], [0,0], label='$Y_0$', linestyle="dashed")
        self.ax.plot([0,0], [0,0], [0,1], label='$Z_0$', linestyle="dashed")

        self.ax.set_xlim3d(-1,1)
        self.ax.set_ylim3d(-1,1)
        self.ax.set_zlim3d(-1,1)

        self.ax.set_xlabel('X')
        self.ax.set_ylabel('Y')
        self.ax.set_zlabel('Z')

        self.ax.scatter(0,0,0, color='k') # black origin dot

        self.canvas = FigureCanvas(self.fig)
        self.mplvl.addWidget(self.canvas)

        self.ani = animation.FuncAnimation(self.fig, self.data_gen, init_func=self.setup_plot, blit=True)

    def setup_plot(self):

        self.ax.legend(loc='best')

        self.vek = self.ax.quiver(0, 0, 0, 0, 0, 0, label='$g \cdot R$', pivot="tail", color="black")

        return self.vek,

    def data_gen(self, i):

        b = self.bslider.value() / 100

        vx, vy, vz = np.cos(b), np.sin(b), 0

        self.vek = self.ax.quiver(0, 0, 0, vx, vy, vz, label='$g \cdot R$', pivot="tail", color="black")

        self.canvas.draw()

        return self.vek,

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)

    main = Kinematic()
    main.show()

    sys.exit(app.exec_())
</code></pre>

<p>By running the code I get </p>

<p><a href="http://i.stack.imgur.com/kGb5J.png" rel="nofollow"><img src="http://i.stack.imgur.com/kGb5J.png" alt="enter image description here"></a></p>

<p>(These are two pictures combined in one showing the same process) </p>

<p>I generated a GUI file named <code>Newsphere.ui</code> following <a href="http://blog.rcnelson.com/building-a-matplotlib-gui-with-qt-designer-part-1/" rel="nofollow">this tutorial</a>. Basically it contains just a Widget, a QSlider and a QSpinBox. The Widget has the layout-name "mplvl", which occures in line 41. This adds the generated figure to the widget (I think so...). The QSlider is connected with the QSpinBox (done in QtDesigner) and has the name "bslider", line 55. So in this line the slider-value gets divided by 100 because I didn't found a slider that generates me a float-value. The key-line for me was line 61, where the canvas is drawn. Now the <code>animation.FuncAnimation</code> (line 43) draws a new vector when I change the slider value, compare the pics. Also it is important to draw the changing vector as a <code>ax.quiver</code> and not as a <code>ax.plot</code> like in my previous attempt.</p>

<p>If there are questions or suggestions for improvement please ask/post.</p>

python qt animation matplotlib