72135


python3.5を使っています。matplotlibを使ってベクトルのアニメーションを作成したいです。下のコードではTimerを使って一定時間ごとに描写しなおしています。しかし、アニメーションの負担を小さくするために、軸の設定をいちいち再設定し直さずに、ベクトルの値のみを更新したいです。どのようにコードを直せばよいのでしょうか。

* * *

**表示されるGUI**  
[![画像](https://i.stack.imgur.com/Qhvh7.png)](https://i.stack.imgur.com/Qhvh7.png)

**ソースコード**

[code]

    import sys
    from PyQt5.QtWidgets import QDialog, QApplication, QVBoxLayout
    from PyQt5.QtCore import QTimer
    from PyQt5 import QtGui,QtCore, QtWidgets
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    import matplotlib.pyplot as plt
    
    from matplotlib.backends.backend_qt5agg \
        import FigureCanvasQTAgg as FigureCanvas
    from matplotlib.figure import Figure
    import numpy as np
    
    
    class Main(QDialog):
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.t=0
            self.angle=30
            self.delta1=0
            self.delta2=0
    
            self.figure=plt.figure(figsize=(6, 6), dpi=80)
            self.axes = self.figure.add_subplot(111)
            self.canvas = FigureCanvas(self.figure)
            self.axes.set_aspect("equal")
            
            layout = QVBoxLayout()
            layout.addWidget(self.canvas)
    
            self.setLayout(layout)
    
            self.timer = QTimer(self)
            self.timer.timeout.connect(self.updatePlot)
            self.timer.start(10) # msec
    
            self.setWindowTitle("Plot")
            self.show()
    
        def updatePlot(self):
            w=1
            self.t = self.t+0.05
            self.axes.clear()        
            phi=self.angle*np.pi/180
            
            X1=0
            Y1=0
            delta1=self.delta1*np.pi/180
            d1=np.sin(w*self.t-delta1)
            U1=d1*np.cos(phi)*np.sin(phi)
            V1=d1*np.cos(phi)*np.cos(phi)
            
            X2=0
            Y2=0
            delta2=self.delta2*np.pi/180
            d2=np.sin(w*self.t-delta2)
            U2=d2*np.cos(np.pi/2-phi)*np.cos(np.pi-phi)
            V2=d2*np.cos(np.pi/2-phi)*np.sin(np.pi-phi)
    
            X3=0
            Y3=0
            U3=U1+U2
            V3=V1+V2
            
            self.axes.quiver(X1,Y1,U1,V1,angles="xy",scale_units="xy",scale=1,color="r")
            self.axes.quiver(X2,Y2,U2,V2,angles="xy",scale_units="xy",scale=1,color="b") 
            self.axes.quiver(X3,Y3,U3,V3,angles="xy",scale_units="xy",scale=1,color="m")
            
            self.axes.set_xlim(-1.2,1.2)
            self.axes.set_ylim(-1.2,1.2)
            self.axes.grid("on")
            self.axes.set_title("Plot",fontsize=12)
            self.axes.set_xlabel("x",size=15)        
            self.axes.set_ylabel("y",size=15)
    
            self.canvas.draw() 
    
    if __name__ == "__main__":
        font=QtGui.QFont("00コミック7",15) 
        app = QApplication(sys.argv)
        win = Main()
        #sys.exit(app.exec_())
        app.exec_()
    
[/code]


CC BY-SA 4.0
2020-11-22T00:43:32.593
72134
2020-11-23T03:33:52.603
26529
question
python matplotlib
pythonのmatplotlibでベクトルの描写を更新する際、軸の設定はそのままにデータだけを更新したい


こちらの記事を参考に、グラフ領域を描く処理とベクトル描画の処理を分離し、ベクトルデータ設定の前に、以前に描いたデータを全て削除して常に1組のデータしか存在しないようにすることで実現できます。  
[In Matplotlib, how can I clear an axes' contents without erasing its axis
labels?](https://stackoverflow.com/q/43075614/9014308)  
回答のオプション2をそのまま使います。

>
[code]

>     # option 2, remove all lines and collections
>     for artist in plt.gca().lines + plt.gca().collections:
>         artist.remove()
>  
[/code]

全体はこうなります。`####`でコメントした部分が変更点です。

[code]

    import sys
    from PyQt5.QtWidgets import QDialog, QApplication, QVBoxLayout
    from PyQt5.QtCore import QTimer
    from PyQt5 import QtGui,QtCore, QtWidgets
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    import matplotlib.pyplot as plt
    
    from matplotlib.backends.backend_qt5agg \
        import FigureCanvasQTAgg as FigureCanvas
    from matplotlib.figure import Figure
    import numpy as np
    
    
    class Main(QDialog):
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.t=0
            self.angle=30
            self.delta1=0
            self.delta2=0
    
            self.figure=plt.figure(figsize=(6, 6), dpi=80)
            self.axes = self.figure.add_subplot(111)
            self.canvas = FigureCanvas(self.figure)
            self.axes.set_aspect("equal")
            
            layout = QVBoxLayout()
            layout.addWidget(self.canvas)
    
            self.setLayout(layout)
    
            self.drawGrid() #### グラフ領域を描く処理を呼び出し
    
            self.timer = QTimer(self)
            self.timer.timeout.connect(self.updatePlot)
            self.timer.start(10) # msec
    
            self.setWindowTitle("Plot")
            self.show()
    
        def updatePlot(self):
            w=1
            self.t = self.t+0.05
            #### self.axes.clear() # 削除してdrawGrid()に移動
            phi=self.angle*np.pi/180
            
            X1=0
            Y1=0
            delta1=self.delta1*np.pi/180
            d1=np.sin(w*self.t-delta1)
            U1=d1*np.cos(phi)*np.sin(phi)
            V1=d1*np.cos(phi)*np.cos(phi)
            
            X2=0
            Y2=0
            delta2=self.delta2*np.pi/180
            d2=np.sin(w*self.t-delta2)
            U2=d2*np.cos(np.pi/2-phi)*np.cos(np.pi-phi)
            V2=d2*np.cos(np.pi/2-phi)*np.sin(np.pi-phi)
    
            X3=0
            Y3=0
            U3=U1+U2
            V3=V1+V2
    
            #### 描かれている内容のデータを削除することで再描画させない
            for artist in plt.gca().lines + plt.gca().collections:
                artist.remove()
    
            self.axes.quiver(X1,Y1,U1,V1,angles="xy",scale_units="xy",scale=1,color="r")
            self.axes.quiver(X2,Y2,U2,V2,angles="xy",scale_units="xy",scale=1,color="b") 
            self.axes.quiver(X3,Y3,U3,V3,angles="xy",scale_units="xy",scale=1,color="m")
    
            #### グラフ領域を描いている部分を削除してdrawGrid()に移動
    
            self.canvas.draw() 
    
        #### グラフ領域を描く処理を定義
        def drawGrid(self):
            self.axes.clear()
            self.axes.set_xlim(-1.2,1.2)
            self.axes.set_ylim(-1.2,1.2)
            self.axes.grid("on")
            self.axes.set_title("Plot",fontsize=12)
            self.axes.set_xlabel("x",size=15)
            self.axes.set_ylabel("y",size=15)
    
            self.canvas.draw() 
    
    if __name__ == "__main__":
        font=QtGui.QFont("00コミック7",15) 
        app = QApplication(sys.argv)
        win = Main()
        #sys.exit(app.exec_())
        app.exec_()
    
[/code]


CC BY-SA 4.0
2020-11-22T01:50:09.790
72135
2020-11-23T03:33:52.603
2020-11-23T03:33:52.603
26370
26370
72134
answer