I have a list of points; after I convert it to an array, I want to display the point with the marker 'o', but if the distance between the point and a mobile point is more than 10, for example, the marker of the point should change from 'o' to '*'. I trid to do this, but all the marker points changed not just the markers that satisfy the if
condition.
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def createList(r1, r2):
return [item for item in range(r1, r2+1)]
r1, r2 = 1, 50
mialistax=createList(r1, r2)
mialistay=createList(r1, r2)
fig, ax = plt.subplots()
import numpy as np
x_l=np.array(mialistax)
y_l = np.array(mialistay)
def animate(i):
max_x= max(mialistax)
max_y=max(mialistay)
ax.clear()
if (x_l[i]>10):
mark='*'
else:
mark='o'
ax.plot(x_l[i],y_l[i],marker=mark)
ax.set_xlim([0,max_x])
ax.set_ylim([0,max_y])
plt.plot(x_l,y_l,marker=mark)
ani = FuncAnimation(fig, animate, frames=200, interval=500, repeat=False)
plt.show()
In this code, the marker changes for all the points, but I want that the marker changed for only the points that satisfy the if
condition.
If I understand the problem correctly, you want an animation that shows all the points, but the point at index i
, which is the frame number, should be converted to a "*"
marker if its x
value is greater than 10.
To start, you have three issues. The first is the order of your plots.
ax.plot(x_l[i], y_l[i], marker=mark)
ax.plot(x_l, y_l, marker=mark)
This means that you first plot your individual point and then the rest of the points on top. So you won't see your "special" point because it is covered up by the other points.
The second issue is that you're setting the same marker for both of the plots (the individual point and the rest of them). I would create a list of all the markers and update the marker at index i
if it meets the condition. Then, loop through all the points and plot them individually (since you cannot pass a marker list). You probably want to have your "special" point stand out, so we can show it as a different color.
markers = ["o"]*len(x_l)
def animate(i):
max_x = max(x_l)
max_y = max(y_l)
ax.clear()
if x_l[i] > 10:
markers[i] = '*'
ax.set_xlim([0, max_x])
ax.set_ylim([0, max_y])
for indx, (x, y, marker) in enumerate(zip(x_l, y_l, markers)):
color = "tab:orange" if indx == i else "tab:blue"
ax.plot(x, y, marker=marker, color=color)
Lastly, you only have 50 points, but have frames=200
, so you need to either increase your points or decrease the number of frames to match.
ani = FuncAnimation(fig, animate, frames=len(x_l), interval=5, repeat=False)
I assume you're new to Python, so I'll also make other suggestions to improve your code.
range
by using the list
function: list(range(start, stop))
. Since you are converting it to a numpy array, there is a numpy function for this: np.arange(start, stop)
.max
method: x_l.max()
, though this change isn't as important.import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation
plt.close("all")
r1 = 1
r2 = 50
x_l = np.arange(r1, r2+1)
y_l = np.arange(r1, r2+1)
fig, ax = plt.subplots()
markers = ["o"]*x_l.shape[0]
def animate(i):
max_x = x_l.max()
max_y = y_l.max()
ax.cla()
if x_l[i] > 10:
markers[i] = '*'
for indx, (x, y, marker) in enumerate(zip(x_l, y_l, markers)):
color = "tab:orange" if indx == i else "tab:blue"
ax.plot(x, y, marker=marker, color=color)
ax.set_xlim([0, max_x])
ax.set_ylim([0, max_y])
ani = FuncAnimation(fig, animate, frames=x_l.shape[0], interval=500, repeat=False)
fig.show()