Below is the code from a work-in-progress script that I am writing. When the script is run I get a "python.exe is stopped working" pop-up. I have managed to locate the problem down to the animation which I have included. By removing the following line the program doesn't crash...
self.anim = animation.FuncAnimation(self.fig, self.animate, init_func = self.anim_init, frames = int(100/self.freq), interval = 20, blit = True)
How would I go about including animation without causing python to crash? Am I missing something that needs to be included?
import wx, sys
import numpy as np
from scipy import signal
from matplotlib import pyplot as plt
from matplotlib import animation
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
class Waveform(wx.Panel):
"""Template of the animation waveform in a panel"""
def __init__(self, parent):
super(Waveform, self).__init__(parent)
self.ud = 4 # Maximum voltage
self.num_mod = 4.0 # Number of submodules
self.freq = 1 # Frequency of the switching (Hz)
self.fig = plt.figure() # Create a waveform figure
self.ax = self.fig.add_subplot(111) # Split the figure into subplots (1x1 grid, first plot)
self.ax.set_xlim(0, 1) # Define the scale of the x axis
self.ax.set_ylim(0, self.ud + 0.8) # Define the scale of the y axis
self.ax.get_xaxis().set_visible(False) # Hide axis
self.ax.text(-0.10, self.ud, r'$U_d$') # Add the label for the ud reference line
self.ax.axhline(y = self.ud, color = 'black', linestyle = '--') # Add the ud reference line
self.ax.set_ylabel('$Voltage$') # Label the y Axis
self.ax.set_title(r'Upper Valve Voltage') # Add the title to the subplot
self.upper_value, = self.ax.plot([], [], label=r'Upper Total', linewidth = '2')
self.upper_value.set_data([], [])
self.canv = FigureCanvas(self, wx.ID_ANY, self.fig)
self.anim = animation.FuncAnimation(self.fig, self.animate, init_func = self.anim_init, frames = int(100/self.freq), interval = 20, blit = True) # Divide by frequency to ensure smooth animation
def anim_init(self):
self.upper_value.set_data([], [])
return self.upper_value,
def animate(self, i):
x = np.linspace(0, 1, 1000)
amplitude = self.ud/self.num_mod
y = amplitude * signal.square(2 * np.pi * self.freq * (x + 0.01 * i)) + self.ud
for num in range(1, int(self.num_mod)):
phase = np.pi/self.num_mod * num
z = amplitude * signal.square(2 * np.pi * self.freq * (x + 0.01 * i) + phase)
y = y + z
self.upper_value.set_data(x, y/2)
return self.upper_value,
class Window(wx.Frame):
"""Template of the top-level (parent) widget called Frame"""
def __init__(self, parent, title):
c_x, c_y, c_w, c_h = wx.ClientDisplayRect() # Finds the size of the screen (Removing the Taskbar)
super(Window, self).__init__(parent, pos=(c_x, c_y), size=(c_w, c_h), title=title, style=wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX)
def main():
app = wx.App(False) # Create a new instance of a wxpython app (don't redirect stdout/stderr)
frame = Window(None, title='Multi-level Converter Animation') # Create a new frame object
panel = Waveform(frame) # Create an instance of the waveform panel
frame.Show() # Display the complete window
app.MainLoop() # Enter a endless cycle that handles the events of the application
# Command-line interface.
import os, argparse
if __name__ == "__main__":
# Included to allow realtime output to the console
# Re-opens stdout file descriptor with write mode and 0 as the buffer size (unbuffered)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
parser = argparse.ArgumentParser(description='Animation of a Multilevel Converter')
args = parser.parse_args()
main()