I am trying to customize my x-axis with minor ticks but I want to bolden or lengthen the middle minor tick. So basically I want a major, middle, and minor tick for my subplot. I tried using tick_params but that overwrites the previous modifications to the ticks. Is there another way to achieve this?
The end result should have 4 minor ticks and 2 semi-minor ticks between the labeled numbers.
Bonus points if there is a way to label the semi-minor ticks.
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import (MultipleLocator, FormatStrFormatter,
AutoMinorLocator)
t = np.arange(0.0, 100.0, 0.1)
s = np.sin(0.1 * np.pi * t) * np.exp(-t * 0.01)
fig, ax = plt.subplots()
ax.plot(t, s)
#Try to set 4 minor ticks
ax.xaxis.set_minor_locator(AutoMinorLocator(4))
ax.tick_params(which='minor', length=2, color='k')
#Set 2 minor ticks that are larger
ax.xaxis.set_minor_locator(AutoMinorLocator(2))
ax.tick_params(which='minor', length=6, color='k')
#Make major ticks even larger
ax.tick_params(which='major', length=12, color='k')
plt.show()
Two ways. The first one is messy and it's probably better to avoid it, but it doesn't hurt to include it here. The second one, as suggested by ImportanceOfBeingErnest and is based on How to add third level of ticks in python matplotlib
fig, ax = plt.subplots()
ax.plot(t, s)
ax.xaxis.set_minor_locator(AutoMinorLocator(9))
ax.tick_params(which='major', length=12, color='k')
minor_labels = list()
i = 0
l = -2
sum_l = 1.125
for line in ax.xaxis.get_ticklines(minor=True):
if i == 0:
line.set_markersize(4)
minor_labels.append('')
i += 1
l += sum_l
elif i == 2:
line.set_markersize(4)
minor_labels.append('')
i += 1
l += sum_l
elif i == 4 or i == 6 or i == 10 or i == 12 or i == 16:
line.set_markersize(4)
minor_labels.append('')
i += 1
l += sum_l
elif i == 18:
line.set_markersize(4)
minor_labels.append('')
i -= 15
l += sum_l
elif i == 8 or i == 14:
line.set_markersize(8)
minor_labels.append(l)
i += 1
l += sum_l
else:
i += 1
l += sum_l
print(minor_labels)
ax.set_xticklabels(minor_labels,minor=True)
plt.setp(ax.xaxis.get_minorticklabels(), rotation=45)
plt.setp(ax.xaxis.get_ticklabels(), rotation=45)
plt.show()
ImportanceOfBeingErnest's solution seems to follow this logic — maybe he had something else in mind —It looks nicer, but I haven't been able to reproduce the minor / semi-minor tick combination. Perhaps with some more time you will be able to do what you intend by tweaking it.
t = np.arange(0.0, 100.0, 0.1)
s = np.sin(0.1 * np.pi * t) * np.exp(-t * 0.01)
fig, ax = plt.subplots()
plt.plot(t, s)
ax2 = ax.twiny()
ax2.plot(t, s)
ax2.xaxis.set_ticks_position('bottom')
ax.xaxis.set_minor_locator(ticker.FixedLocator(np.arange(5, 100.01, 5)))
ax.tick_params(which='minor', length=8, color='k')
ax2.xaxis.set_major_locator(ticker.FixedLocator([]))
ax2.xaxis.set_minor_locator(ticker.FixedLocator(np.arange(1.25, 100.01,1.25)))
ax2.tick_params(which='minor', length=4, color='k')
ax.tick_params(which='major', length=12, color='k')
ax.set_xticklabels(np.arange(5, 100.01, 5),minor=True)
plt.setp(ax.xaxis.get_minorticklabels(), rotation=45)
plt.setp(ax.xaxis.get_ticklabels(), rotation=45)
plt.show()
Related
I'm attempting to plot 2 pairs of (x,y) data and show how much distance is between them.
I have 2 issues with the plot it stands:
When the data points fall on the axis they are being draw behind them, I'd prefer them in front (red data point above).
The text annotation is fixed where it's drawn, this means either the data or the legend can cover it when data points are in the top right or top left quadrants.
The desired output would be a draw order of Axes -> Scatter -> Quiver and then for the text annotation to be drawn in whichever quadrant is not occupied by a data point or the legend.
For issue 1 I've tried combinations of clipon=True and zorder= for all the plot elements but can't seem to bring them in front.
For issue 2 I've considered checking which quadrants the data points are in, draw the legend and check which quadrant that is in and then finally draw the annotation in the remaining unoccupied quadrant(s). However I've struggled to get the correct legend position with legend.get_window_extent() and was hoping there was an easier method of moving the annotation, similar to rcParams["legend.loc"]='Best'. I can't see anything obvious at https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.text.html
Any help would be greatly appreciated, below is the code used to produce the plot. Thanks!
#!/usr/bin/env python3
import matplotlib
matplotlib.use('qt5agg')
import matplotlib.pyplot as plt
data = [[-0.4, 0.4], [0.2, -0.01]]
#data = [[0.4, 0.4], [0.2, -0.01]]
fig, ax = plt.subplots(figsize=(4.5, 3.25), num="Stack Example")
x, y = (zip(*data))
dx = x[1]-x[0]
dy = y[1]-y[0]
c = [0, 1]
scatter = ax.scatter(x, y, c=c, cmap='rainbow', s=250, marker="o")
legend = ax.legend(*scatter.legend_elements(),
title="Legend", fontsize=8, title_fontsize=8)
ax.add_artist(legend)
ax.quiver(x[0], y[0], dx, dy, angles='xy', scale_units='xy', scale=1, headwidth=3)
textstr = '\n'.join((
r'$dx$=%.2f mm' % (dx),
r'$dy$=%.2f mm' % (dy)))
ax.text(0.04, 0.95, textstr, transform=ax.transAxes, fontsize=9, verticalalignment='top')
ax.spines[['left', 'bottom']].set_position('zero')
ax.spines[['top', 'right']].set_visible(False)
ax.set_xlim([-0.5, 0.5])
ax.set_ylim([-0.5, 0.5])
ax.set_xticks([-0.5, -0.25, 0.25, 0.5])
ax.set_yticks([-0.5, -0.25, 0.25, 0.5])
ax.set_xlabel('$x$ $/$ $mm$', fontsize=9)
ax.xaxis.set_label_coords(1.0, 0.4)
ax.set_ylabel('$y$ $/$ $mm$', fontsize=9)
ax.yaxis.set_label_coords(0.57, 1.0)
plt.xticks(fontsize=9)
plt.yticks(fontsize=9)
plt.tight_layout()
fig.canvas.toolbar.setVisible(False)
plt.show()
UPDATE
I've fixed issue 2 as I mentioned above, it's not pretty but works for each of the usage cases I've tried so far.
def get_quadrants(data):
quadrants = []
for datapoint in data:
x = datapoint[0]
y = datapoint[1]
if x < 0 and y < 0:
quadrants.append(2)
elif x < 0 and y > 0:
quadrants.append(0)
elif x > 0 and y < 0:
quadrants.append(3)
else:
quadrants.append(1)
text_quadrant = max(sorted(set((range(4))) - set(quadrants)))
if len(set([2, 3]) - set(quadrants)) == 0:
text_quadrant = 0
if text_quadrant == 0:
x, y = 0.0, 0.95
elif text_quadrant == 1:
x, y = 0.75, 0.95
elif text_quadrant == 2:
x, y = 0.0, 0.15
else:
x, y = 0.75, 0.15
return x, y
Recently I have been developing a code to create a function approximation through Bernstein's polynomial.
The problem i have is that I want to represent the Bernstein's polynomial for different values for 'n'. I found an example on Matplotlib how to make sliders so I copied to see if it worked with my function. The result is that for a starting 'n' value it works but as soon as I change it, it stops working because the slider is only using integers but if you move it the function changes as if 'n' could have any value for an interval. The code:
import sympy as sy
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button, RadioButtons
def f(x):
return np.abs(x)
def fac(x):
return np.math.factorial(x)
def ecuacion(n,k):
result = ((fac(n)) / (fac(k) * fac(n - k))) * ((x + 1) ** k * (1 - x) ** (n - k)) / (2 ** n) * f(2 * k / n - 1)
return result
def bernstein(x, k, n):
#p = ((fac(n)) / (fac(k) * fac(n - k))) * ((x + 1) ** k * (1 - x) ** (n - k)) / (2 ** n) * f(2 * k / n - 1)
resultado = 0
for k in range(0,n+1):
resultado = ecuacion(n,k) + resultado
return resultado
axis_color = 'lightgoldenrodyellow'
fig = plt.figure()
ax = fig.add_subplot(111)
fig.subplots_adjust(left=0.25, bottom=0.25)
x = np.arange(-1, 1, 0.001)
freq_0 = 3
# Draw the initial plot
# The 'line' variable is used for modifying the line later
[line] = ax.plot(x, bernstein(x,0,2), linewidth=2, color='red')
ax.set_xlim([-1, 1])
ax.set_ylim([0, 1])
# Add two sliders for tweaking the parameters
# Define an axes area and draw a slider in it
amp_slider_ax = fig.add_axes([0.25, 0.15, 0.65, 0.03])
amp_slider = Slider(amp_slider_ax, 'n', 2, 50, valinit=2)
# Draw another slider
freq_slider_ax = fig.add_axes([0.25, 0.1, 0.65, 0.03])
freq_slider = Slider(freq_slider_ax, 'Freq', 3, 30.0, valinit=6)
# Define an action for modifying the line when any slider's value changes
def sliders_on_changed(val):
line.set_ydata(bernstein(x,amp_slider.val, freq_slider.val))
fig.canvas.draw_idle()
amp_slider.on_changed(sliders_on_changed)
freq_slider.on_changed(sliders_on_changed)
# Add a button for resetting the parameters
reset_button_ax = fig.add_axes([0.8, 0.025, 0.1, 0.04])
reset_button = Button(reset_button_ax, 'Reset', color=axis_color, hovercolor='0.975')
def reset_button_on_clicked(mouse_event):
freq_slider.reset()
amp_slider.reset()
reset_button.on_clicked(reset_button_on_clicked)
#Add a set of radio buttons for changing color
# color_radios_ax = fig.add_axes([0.025, 0.5, 0.15, 0.15])
# color_radios = RadioButtons(color_radios_ax, ('red', 'blue', 'green'), active=0)
# def color_radios_on_clicked(label):
# line.set_color(label)
# fig.canvas.draw_idle()
# color_radios.on_clicked(color_radios_on_clicked)
plt.show()
I am visualizing four classes of the spectrogram. For a single class, My spectrogram code looks like this
Considering this as one image.
And the code to produce this, is
def spec(filename):
time_period = 0.5 # FFT time period (in seconds). Can comfortably process time frames from 0.05 seconds - 10 seconds
# ==============================================
fs_rate, signal_original = wavfile.read(filename)
total_time = int(np.floor(len(signal_original)/fs_rate))
sample_range = np.arange(0,total_time,time_period)
total_samples = len(sample_range)
print ("Frequency sampling", fs_rate)
print ("total time: ", total_time)
print ("sample time period: ", time_period)
print ("total samples: ", total_samples)
output_array = []
for i in sample_range:
# print ("Processing: %d / %d (%d%%)" % (i/time_period + 1, total_samples, (i/time_period + 1)*100/total_samples))
sample_start = int(i*fs_rate)
sample_end = int((i+time_period)*fs_rate)
signal = signal_original[sample_start:sample_end]
l_audio = len(signal.shape)
#print ("Channels", l_audio)
if l_audio == 2:
signal = signal.sum(axis=1) / 2
N = signal.shape[0]
#print ("Complete Samplings N", N)
secs = N / float(fs_rate)
# print ("secs", secs)
Ts = 1.0/fs_rate # sampling interval in time
#print ("Timestep between samples Ts", Ts)
t = scipy.arange(0, secs, Ts) # time vector as scipy arange field / numpy.ndarray
FFT = abs(scipy.fft(signal))
FFT_side = FFT[range(int(N/2))] # one side FFT range
freqs = scipy.fftpack.fftfreq(signal.size, t[1]-t[0])
fft_freqs = np.array(freqs)
freqs_side = freqs[range(int(N/2))] # one side frequency range
fft_freqs_side = np.array(freqs_side)
# Reduce to 0-5000 Hz
bucket_size = 5
buckets = 16
FFT_side = FFT_side[0:bucket_size*buckets]
fft_freqs_side = fft_freqs_side[0:bucket_size*buckets]
# Combine frequencies into buckets
FFT_side = np.array([int(sum(FFT_side[current: current+bucket_size])) for current in range(0, len(FFT_side), bucket_size)])
fft_freqs_side = np.array([int(sum(fft_freqs_side[current: current+bucket_size])) for current in range(0, len(fft_freqs_side), bucket_size)])
# FFT_side: Normalize (0-1)
max_value = max(FFT_side)
if (max_value != 0):
FFT_side_norm = FFT_side / max_value
# Append to output array
output_array.append(FFT_side_norm)
# ============================================
# Plotting
plt.figure(figsize=(4,7))
plt.subplot(411)
plt.subplots_adjust(hspace = 0.5)
plt.plot(t, signal, "g") # plotting the signal
plt.xlabel('Time')
plt.ylabel('Amplitude')
plt.subplot(412)
diff = np.diff(fft_freqs_side)
widths = np.hstack([diff, diff[-1]])
plt.bar(fft_freqs_side, abs(FFT_side_norm), width=widths) # plotting the positive fft spectrum
plt.xticks(fft_freqs_side, fft_freqs_side, rotation='vertical')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Count single-sided')
FFT_side_norm_line = FFT_side_norm.copy()
FFT_side_norm_line.resize( (1,buckets) )
plt.subplot(413)
plt.imshow(FFT_side_norm_line)
plt.xlabel('Image Representation 1D')
plt.show()
print("\n\n\n\n\n\n")
How can I combine four images plot like this, and make a single output image. Something like this
I'd suggest using fig.subfigures and plt.subplot_mosaic.
The plot above was obtained using this simple script:
import matplotlib.pyplot as plt
fig = plt.figure(figsize = (8, 10), layout='constrained')
# next two lines make the trick
sfigs = fig.subfigures(2,2)
mosaics = [f.subplot_mosaic('t;t;t;f;f;f;i;.') for f in sfigs.flat]
# next, "how to" reference the subplots in subfigures
mosaics[0]['t'].plot(range(5), color='b')
mosaics[1]['t'].plot(range(5), color='k')
mosaics[2]['t'].plot(range(5), color='r')
mosaics[3]['t'].plot(range(5), color='g')
mosaics[0]['f'].plot(range(3), color='b')
mosaics[1]['f'].plot(range(3), color='k')
mosaics[2]['f'].plot(range(3), color='r')
mosaics[3]['f'].plot(range(3), color='g')
mosaics[0]['i'].imshow([range(10)]*2)
plt.show()
You can do it this way:
fig, axs = plt.subplots(2, 2)
axs[0, 0].plot(x, y)
axs[0, 0].set_title('Axis [0, 0]')
axs[0, 1].plot(x, y, 'tab:orange')
axs[0, 1].set_title('Axis [0, 1]')
axs[1, 0].plot(x, -y, 'tab:green')
axs[1, 0].set_title('Axis [1, 0]')
axs[1, 1].plot(x, -y, 'tab:red')
axs[1, 1].set_title('Axis [1, 1]')
for ax in axs.flat:
ax.set(xlabel='x-label', ylabel='y-label')
# Hide x labels and tick labels for top plots and y ticks for right plots.
for ax in axs.flat:
ax.label_outer()
The result will be like this:
Taken from https://matplotlib.org/stable/gallery/subplots_axes_and_figures/subplots_demo.html
Hello Matplotlib Experts,
How do I curve text in a matplotlib polar plot? In my attempt below, my code rotates each char individually, but doing so would remove the natural spacing of each font. Can somebody describe a solution for passing ax.text in matplotlib?
import numpy as np
import matplotlib as mpl
import matplotlib.pylab as plt
def curveText(text, height, minTheta, maxTheta, ax):
interval = np.arange(minTheta, maxTheta, .022)
if( maxTheta <= np.pi):
progression = interval[::-1]
rotation = interval[::-1] - np.arctan(np.tan(np.pi/2))
else:
progression = interval
rotation = interval - np.arctan(np.tan(np.pi/2)) - np.pi
## Render each letter individually
for i, rot, t in zip(progression, rotation, text):
ax.text(i, height, t, fontsize=11,rotation=np.degrees(rot), ha='center', va='center')
def buildCircularHeatMap( data=None, label=None, cmaps=None, categorymap=None, vmin=0, vmax=None ):
(xDim, yDim) = data.shape
if cmaps == None:
cmaps = [mpl.cm.get_cmap()] * yDim
BOTTOM = xDim / 100 * 120
#FONTSIZE = 1 if xDim/100*8 < 1 else xDim/100*8
theta = np.linspace(0.0, 2 * np.pi - 5 * np.pi/180, xDim, endpoint=False)
width = (2*np.pi - 5 * np.pi/180)/xDim
ax = plt.subplot(111, polar=True)
ax.grid(False)
ax.set_yticklabels([])
ax.set_xticklabels([])
categorysum = np.zeros(len(categorymap))
for x in label:
categorysum[int(float( x )) - 1] += 1
categorysum = categorysum/np.sum(categorysum)*2*np.pi
## Build Face Color Values
for i in range(yDim):
cmap_scalar = mpl.cm.ScalarMappable(cmap=cmaps[i])
cmap_scalar.set_clim(vmin=vmin, vmax=vmax)
facecolor = cmap_scalar.to_rgba(data[:,i])
_ = ax.text(2 * np.pi - 5 * np.pi/180, BOTTOM+i*10, str(i), fontsize=11, rotation=np.degrees(270))
bars = ax.bar(theta, np.ones(xDim)*10, width=width, bottom=BOTTOM+i*10)
for j, b in enumerate(bars):
b.set_facecolor( facecolor[j] )
## Build CCS Label
for th, l, bar in zip(theta, label, bars):
rot = np.arctan(np.tan(th))
ax.text(th,BOTTOM+yDim*10+bar.get_height()+5, l, rotation_mode='anchor',
rotation=np.degrees(rot), fontsize=11, ha='center', va='center')
## Build Category Label
categoryColor = np.asarray([int(float(c)) for c in label])
bars = ax.bar(theta, np.ones(xDim)*20, width=width, bottom=BOTTOM+yDim*10 + 30)
for j, b in enumerate(bars):
b.set_facecolor(np.asarray([0.0,0.0,0.0]))
if categoryColor[j] % 2 == 0:
b.set_alpha(0.07)
else:
b.set_alpha(0.0)
for i in range(len(categorymap)):
c = i + 1
t = theta[categoryColor==c]
mi = np.min(t)
ma = np.max(t)
rad = (ma-mi)/2+mi
curveText(categorymap[c], BOTTOM+yDim*10+40, mi, ma, ax)
if __name__ == "__main__":
categorymap={
1: "Infectious & parasitic dieases",
2: "Neoplasms",
3: "Endocrine; nutritional; and metabolic diseases and immunity disorders",
4: "Diseases of the blood and blood-forming organs",
5: "Mental Illness",
6: "Nervous system disorders",
7: "Circulatory disorders",
8: "Respiratory disorders",
9: "Digestive disorders",
10: "Genitourinary disorders",
11: "Complications of pregnancy; childbirth; and the puerperium",
12: "Skin and subcutaneous tissue disorder",
13: "Musculoskeletal system and connective tissue disorder",
14: "Congenital anomalies",
15: "Certain conditions originating in the perinatal period",
16: "Injury and poisoning",
17: "Ill-defined status",
18: "Unclassified"
}
data = np.random.standard_normal((180, 3))
colormaps = [mpl.cm.get_cmap("Reds"), mpl.cm.get_cmap("Oranges"), mpl.cm.get_cmap("Greens"), mpl.cm.get_cmap("Blues")]
labels = sorted([ '{:.2f}'.format(np.abs(i)) for i in np.random.random_sample(180) * 18 + 1 ])
fig = plt.figure(figsize=(11,11))
buildCircularHeatMap(data=data, label=labels, cmaps=colormaps, categorymap=categorymap)
plt.show()
In the link below, Thomas's answer seems only applicable for cartesian coordinates and my current attempt should be similar to Daan.
Curved text rendering in matplotlib
As #Makdous suggested above, Curved text rendering in matplotlib is a nice implementation of the problem. I read through the code, and you're right, it is in cartesian coordinates, but I think you could just modify it a bit and get it working using these formulas:
You can also use this one line function I wrote:
from typing import Tuple
from math import sqrt, degrees, atan2
def cartesian_to_polar(x: float, y: float)-> Tuple[float, float]:
return sqrt(x**2 + y ** 2), degrees(atan2(y,x))
Or, if you have polar coordinates and want to make it work with the script linked in the other response, you can use this:
from math import cos, sin, radians
def polar_to_cartesian(r: float, theta: float)-> Tuple[float, float]:
return r * cos(radians(theta)), r * sin(radians(theta))
Depending on how you implemented it, you could feed it in the coordinates you have, then convert it appropriately to arrive at cartesian coordinates and run the linked script, then convert the points back to polar coordinates and plot it.
I am trying to create the animation in this video using Python. But I stuck on the very first step. Till now I've created a Circle and a point rotating around its circumference. My code is given below. Now I want to plot the y values corresponding to x=np.arange(0, I*np.pi, 0.01) along the x-axis (as shown in update() function in the code). For this I have to define another function to plot these x and y and pass that function inside a new animation.FuncAnimation().
Is there any way to plot everything using only the update() function?
Note I have found a code of this animation in here. But it is written in Java!
My Code
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np
W = 6.5
H = 2
radius = 1
I = 2
T = 3
N = 2
plt.style.use(['ggplot', 'dark_background'])
def create_circle(x, y, r):
circle = plt.Circle((x, y), radius=r, fill=False, alpha=0.7, color='w')
return circle
def create_animation():
fig = plt.figure()
ax = plt.axes(xlim=(-2, W + 2), ylim=(-H, H))
circle = create_circle(0, 0, radius)
ax.add_patch(circle)
line1, = ax.plot(0, 1, marker='o', markersize=3, color='pink', alpha=0.7)
def update(theta):
x = radius * np.cos(theta)
y = radius * np.sin(theta)
line1.set_data([0, x], [0, y])
return line1,
anim = []
anim.append(animation.FuncAnimation(fig, update,
frames=np.arange(0, I * np.pi, 0.01),
interval=10, repeat=True))
# anim.append(animation.FuncAnimation(fig, update_line, len(x),
# fargs=[x, y, line, line1], interval=10))
plt.grid(False)
plt.gca().set_aspect('equal')
plt.gca().spines['left'].set_visible(False)
plt.gca().spines['top'].set_visible(False)
plt.gca().spines['right'].set_visible(False)
plt.gca().spines['bottom'].set_visible(False)
plt.gca().set_xticks([])
plt.gca().set_yticks([])
plt.show()
if __name__ == '__main__':
create_animation()
Edit. I've improved the task by defining a global variable pos and changing the update() function in the following manner ...The animation now looks better but still having bugs!
Improved Portion
plot, = ax.plot([], [], color='w', alpha=0.7)
level = np.arange(0, I * np.pi, 0.01)
num = []
frames = []
for key, v in enumerate(level):
num.append(key)
frames.append(v)
def update(theta):
global pos
x = radius * np.cos(theta)
y = radius * np.sin(theta)
wave.append(y)
plot.set_data(np.flip(level[:pos] + T), wave[:pos])
line1.set_data([0, x], [0, y])
pos += 1
return line1, plot,
Edit Till now I've done the following:
def update(theta):
global pos
x, y = 0, 0
for i in range(N):
prev_x = x
prev_y = y
n = 2 * i + 1
rad = radius * (4 / (n * np.pi))
x += rad * np.cos(n * theta)
y += rad * np.sin(n * theta)
wave.append(y)
circle = create_circle(prev_x, prev_y, rad)
ax.add_patch(circle)
plot.set_data(np.flip(level[:pos] + T), wave[:pos])
line2.set_data([x, T], [y, y])
line1.set_data([prev_x, x], [prev_y, y])
pos += 1
return line1, plot, line2,
Output
Please help to correct this animation. Or, is there any efficient way to do this animation?
Edit Well, now the animation is partially working. But there is a little issue: In my code (inside the definition of update()) I have to add circles centered at (prev_x, prev_y) of radius defined as rad for each frame. For this reason I try to use a for loop in the definition of update() but then all the circles remains in the figure (see the output below). But I want one circle in each frame with the centre and radius as mentioned above. Also the same problem is with the plot. I try to use ax.clear() inside the for loop but it didn't work.