Drawing a Nyquist diagram animation on python

660 Views Asked by At

I am currently trying to create a python code that is supposed to draw an animated nyquist diagram and save it as a gif file.

The problem is, I don't know how to make the animate function work. Here is a code I found on the internet that works:

def animate(i):
    x = np.linspace(0, 2, 1000)
    y = np.sin(2 * np.pi * (x - 0.01 * i))
    line.set_data(x, y)
    return line,

As you may know, linspace and sin are functions that returns arrays with the sequential values. The real and imag variables on my code are also arrays with sequential values. w variable is an array too, corresponding to the values of real and imag. I wanted real and imag to be drawn for every w value, thus being the "step" of the animation. What is wrong with my code?

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation as an
import control

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(-2, 2), ylim=(-2, 2))
line, = ax.plot([], [], lw=2)

# initialization function: plot the background of each frame
def init():
    line.set_data([], [])
    return line,

# animation function.  This is called sequentially
def animate(i):
    G = control.TransferFunction((1),(1,0))
    real, imag, w = control.nyquist(G)
    line.set_data(real, imag)
    return line,**

# call the animator.  blit=True means only re-draw the parts that have     changed.
anim = an.FuncAnimation(fig, animate, init_func=init,
                               frames=200, interval=200, blit=True)

#anim.save('GIF.gif', dpi=100, writer='imagemagick')
plt.title('Nyquist Diagram of 1/s')
plt.ylabel('Imaginary')
plt.xlabel('Real')
plt.grid(True)
plt.show()
1

There are 1 best solutions below

1
Alexander Silva On

In your code you are always ploting the current data (real and imag), but according to matplotlib you need to use a list of data which is updated in every iteration. Matplotlib - Animation

In the code below I have created the lists realData and imagData, so in every iteration real and imag are appended to the list and these lists are used as line.set_data arguments.

I have also used the control package just in the begining because it already returns a list containing everything you need to plot.

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation as an
import control


# First set up the figure, the axis, and the plot element we want to animate
fig, ax = plt.subplots()
realData, imagData = [], []
line, = plt.plot([], [], 'rx', animated=True)
G = control.TransferFunction((1),(1,0))
real, imag, w = control.nyquist(G)
print(real)
print(imag)

def init():
    ax.set_xlim(-2, 2)
    ax.set_ylim(-10, 10)
    return line,

# animation function.  This is called sequentially
def animate(i):
    realData.append(real[i])
    imagData.append(imag[i])
    line.set_data(realData, imagData)
    return line,

# call the animator.  blit=True means only re-draw the parts that have     changed.
anim = an.FuncAnimation(fig, animate, init_func=init,
                               frames=range(len(real)), interval=2, blit=True)

#anim.save('GIF.gif', dpi=100, writer='imagemagick')
plt.title('Nyquist Diagram of 1/s')
plt.ylabel('Imaginary')
plt.xlabel('Real')
plt.grid(True)
plt.show()