I have a class in which I used one of the codes in StackOverflow, this link :Managing dynamic plotting in matplotlib Animation module
Now I want to edit this class and add some parameters to the class, for example data and add update function in a class, at the end I would like only call the class in another script and see the result.
I tried this:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import mpl_toolkits.axes_grid1
import matplotlib.widgets
from matplotlib.animation import PillowWriter
import itertools
from collections import defaultdict
file = "/Users/hadis/Documents/data_preparation/new_dataset/tracks_08.csv"
data = np.genfromtxt(file, delimiter=",", dtype=None)
path = "/Users/hadis/Desktop/project/5_Data/08_background.png"
class visualizer(FuncAnimation):
def __init__(self,fig, data,frames=None,
init_func=None, fargs=None,
save_count=None,background_path=None, mini=0,
maxi=100, pos= (0.75, 0.04), **kwargs):
self.i = 0
self.min=mini
self.max=maxi
self.data = data
self.background_path = background_path
self.runs = True
self.forwards = True
self.fig = fig
self.ax = self.fig.gca()
plt.xlabel("X-Position [m]", fontsize=12)
plt.ylabel("Y-Position [m]", fontsize=12)
img = plt.imread(self.background_path)
plt.imshow(img,extent=[0,1170,-780,0])
number = self.background_path.split("/")[-1].split("_")[0]
plt.title("Track " + number)
self.setup(pos)
if fig is None:
self.fig, self.ax = plt.subplots(1,1)
else:
self.fig = fig
self.ax = self.fig.gca()
self.lines = []
for i in range(3):
self.line, = plt.plot([], [])
self.lines.append(self.line)
#self.func = update
FuncAnimation.__init__(self,self.fig, self.update, frames=self.play(),
init_func=init_func, fargs=fargs,
save_count=save_count, **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):
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 setup(self,pos):
playerax = self.fig.add_axes([pos[0],pos[1], 0.15, 0.05])
divider = mpl_toolkits.axes_grid1.make_axes_locatable(playerax)
sax = divider.append_axes("right", size="100%", pad=0.06)
fax = divider.append_axes("right", size="100%", pad=0.06)
self.button_back = matplotlib.widgets.Button(playerax, 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_back.on_clicked(self.backward)
self.button_stop.on_clicked(self.stop)
self.button_forward.on_clicked(self.forward)
self.button_forward.label.set_fontsize(15)
self.button_back.label.set_fontsize(15)
self.button_stop.label.set_fontsize(14)
self.ax.set_xticklabels([0,20,40,60,80,100,120])
self.ax.set_yticklabels([0,10,20,30,40,50,60,70,80])
self.ax.xaxis.set_tick_params(labelsize=12)
self.ax.yaxis.set_tick_params(labelsize=12)
self.ax.set_xlim(0,1170)
self.ax.set_ylim(-780,0)
def set_data(self,data):
groups = itertools.groupby(self.data, key=lambda x: x[0])
lst = [[[item[2], item[3]] for item in group] for _, group in groups]
d = defaultdict(list)
for i in self.data:
d[i[0]].append((i[1]))
self.start_frames = [i[0] for i in d.values()]
# For visualisation we should convert positions from meter to pixel
self.new_list = [[[z/(0.008146*12) for z in y] for y in x] for x in lst]
return self.new_list, self.start_frames
def update(self,frame):
for i in range(len(self.new_list)):
if frame > self.start_frames[i] and frame < self.start_frames[i] + len(self.new_list[i]):
x = [self.new_list[i][j-self.start_frames[i]][0] for j in range(max(self.start_frames[i],frame-9), frame+1)]
y = [self.new_list[i][j-self.start_frames[i]][1] for j in range(max(self.start_frames[i],frame-9), frame+1)]
self.lines[i].set_data(x, y)
else:
self.lines[i].set_data([], [])
return self.lines
fig, ax = plt.subplots()
ani = visualizer(fig,data,background_path=
path,maxi=10000,interval=40,blit= False)
plt.show()
In the end, it gives me an empty figure, with no animation. can anyone give me advise on how can I restructure my code? Is it possible to do this?
Yes, you could create a class for that, you gonna have to modify your code this way:
edit: we added buttons
your class:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import mpl_toolkits.axes_grid1
import matplotlib.widgets
from collections import defaultdict
import itertools
class Visualizer:
def __init__(self, data, background_path, mini=0, maxi=10000, interval=40, blit=False):
self.fig, self.ax = plt.subplots()
self.data = data
self.background_path = background_path
self.mini = mini
self.maxi = maxi
self.interval = interval
self.blit = blit
self.paused = False
self.new_list, self.start_frames = self.set_data(self.data)
self.lines = []
for i in range(3):
line, = self.ax.plot([], [])
self.lines.append(line)
self.setup((0.75, 0.04))
self.ani = FuncAnimation(self.fig, self.update, frames=range(self.mini, self.maxi),
init_func=self.init, interval=self.interval, blit=self.blit)
self.add_buttons()
# ... (other methods remain unchanged) ...
def add_buttons(self):
ax_play = plt.axes([0.7, 0.025, 0.1, 0.04])
ax_stop = plt.axes([0.81, 0.025, 0.1, 0.04])
ax_reset = plt.axes([0.92, 0.025, 0.1, 0.04])
self.button_play = matplotlib.widgets.Button(ax_play, 'Play')
self.button_stop = matplotlib.widgets.Button(ax_stop, 'Stop')
self.button_reset = matplotlib.widgets.Button(ax_reset, 'Reset')
self.button_play.on_clicked(self.play)
self.button_stop.on_clicked(self.stop)
self.button_reset.on_clicked(self.reset)
def play(self, event):
if self.paused:
self.ani.event_source.start()
self.paused = False
def stop(self, event):
if not self.paused:
self.ani.event_source.stop()
self.paused = True
def reset(self, event):
self.ani.frame_seq = self.ani.new_frame_seq()
self.ani.event_source.start()
self.paused = False
def show(self):
plt.show()
then if you want to use it in your script:
file = "/Users/hadis/Documents/data_preparation/new_dataset/tracks_08.csv"
data = np.genfromtxt(file, delimiter=",", dtype=None)
path = "/Users/hadis/Desktop/project/5_Data/08_background.png"
vis = Visualizer(data=data, background_path=path, mini=0, maxi=10000, interval=40, blit=False)
vis.show()