Why am I getting NoneType? - python

I'm trying to write a piece of code that generates a random walk for a scatterplot in pyplot, but keeping getting error: TypeError: object of type 'NoneType' has no len()
from random import choice
class RandomWalk:
def __init__(self, num_points=5000):
self.num_points = num_points
self.x_values = [0]
self.y_values = [0]
def get_step(self):
step = (choice([x for x in range(20)])) * (choice([1, -1]))
return step
def fill_walk(self):
while len(self.x_values) < self.num_points:
x_step = self.get_step()
y_step = self.get_step()
if x_step == 0 and y_step == 0:
continue
self.x_values = self.x_values.append((self.x_values[-1] + x_step))
self.y_values = self.y_values.append((self.y_values[-1] + y_step))
And this is the plot code:
rw = RandomWalk(5_000)
rw.fill_walk()
plt.style.use('classic')
fix, ax = plt.subplots(figsize=(15, 9))
point_numbers = range(rw.num_points)
ax.scatter(rw.x_values, rw.y_values, c=point_numbers, cmap=plt.cm.rainbow, edgecolors='none', s=5)
ax.scatter(0, 0, c='green', edgecolors='none', s=100)
ax.scatter(rw.x_values[-1], rw.y_values[-1], c='red', edgecolors='none', s=100)
plt.show()
For some reason self.x_values is not being passed, and I get the TypeError for this line:
while len(self.x_values) < self.num_points:
Any idea why it's not being passed?

self.x_values = self.x_values.append(...)
The issue is in the line above - append just return None

Related

live graph with matplotlib report not defined error

I try to create a live graph with matplotlib animation. below code report error:
UnboundLocalError: local variable 'lines' referenced before assignment
lines is defined above!
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import random
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
queue = []
qSize = 20
N = 3
lines = []
xidx = list(range(0, qSize))
def init():
for i in range(qSize):
queue.append([0]*N)
for i in range(N):
xdata = []
ydata = []
line, = ax.plot(xdata, ydata,label=str(i))
lines.append([line,xdata,ydata])
ax.legend(loc=2)
plt.xticks(rotation=45, ha='right')
#plt.subplots_adjust(bottom=0.30)
plt.title('Demo')
plt.ylabel('x')
plt.ylabel('Value')
return
def tick():
arr = []
for i in range(N):
d = random.randint(i*10,i*10+5)
arr.append(d)
queue.append(arr)
lines = lines[-qSize:]
return
def animate(i):
tick()
df = pd.DataFrame(data)
ax.set_xlim(0,qSize)
ax.set_ylim(df.min().min(),df.max().max())
for i,colname in enumerate(df.columns):
line,xdata,ydata = lines[i]
xdata = xidx
ydata = df[colname]
line.set_xdata(xdata)
line.set_ydata(ydata)
plt.draw()
return
init()
ani = animation.FuncAnimation(fig, animate, fargs=(), interval=1000)
plt.show()

How to animate multiple points moving using funcanimation (not ax.scatter())?

I have the code below. If you run that program a scatter plot is created. The plot is very messy. I want every point to represent one car. I only want to see the point of the current position of each car in the animation. I am not very good at matplotlib, but how would I do that?
from matplotlib import pyplot as plt
import random
import math
from matplotlib import animation
import numpy as np
roadLength = 100
numFrames = 200
numCars = 60
velocities = []
positions = []
theta = []
r = []
color = []
probability = 0.5
vmax = 1
flowr = []
fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')
ax.axis('off')
for i in range(numCars):
positions.append(i * 2)
theta.append(0)
r.append(1)
color.append(i)
velocities.append(0)
def pos(k):
rand = random.uniform(0,1)
if velocities[k] < vmax:
velocities[k] += 1
if k < numCars-1 and (positions[k+1] - positions[k]) <= velocities[k]:
velocities[k] = positions[k+1] - positions[k] - 1
if k == numCars-1 and (roadLength - (positions[k] - positions[0])) <= velocities[k]:
velocities[k] = roadLength - (positions[k] - positions[0]) - 1
if rand < probability and velocities[k] > 0:
velocities[k] = velocities[k] - 1
positions[k] = positions[k] + velocities[k]
return positions[k]
def animate(frameNr):
for i in range(numCars):
theta[i] = pos(i) * 2 * math.pi / roadLength
flowr.append(velocities[i])
ax.scatter(theta, r, c=color)
return ax.scatter(theta, r, c=color),
def simulate():
anim = animation.FuncAnimation(fig, animate,
frames=numFrames, interval=10, blit=True, repeat=False)
plt.show()
simulate()
Thanks in advance!
Edit:
I fixed so that it became a point plot I am now storing velocity, position and lane in an object for a later problem. My question is:
How do I make the points have different colors?
from matplotlib import pyplot as plt
import random
import math
from matplotlib import animation
import numpy as np
from operator import attrgetter
roadLength = 100
numFrames = 200
nlanes = 1
numCars = 20
posss =[]
theta = []
r = []
color = []
probability = 0.5
vmax = 1
flowr = []
cars=[]
class Car:
def __init__(self, position, velocity, lane):
self.position = position
self.velocity = velocity
self.lane = lane
def pos(car,k):
rand = random.uniform(0,1)
if car[k].velocity < vmax:
car[k].velocity += 1
if k < numCars-1 and (car[k+1].position - car[k].position) <= car[k].velocity:
car[k].velocity = car[k+1].position - car[k].position - 1
if k == numCars-1 and (roadLength - (car[k].position - car[0].position)) <= car[k].velocity:
car[k].velocity = roadLength - (car[k].position - car[0].position) - 1
if rand < probability and car[k].velocity > 0:
car[k].velocity = car[k].velocity - 1
car[k].position = car[k].position + car[k].velocity
return car[k].position
for i in range(numCars):
cars.append(Car(i, 0, 1))
theta.append(0)
r.append(1)
color.append(i)
posss.append(i)
fig = plt.figure()
ax = fig.add_subplot(111)
point, = ax.plot(posss, r, 'o')
ax.set_xlim(-10, 1.2*numFrames)
ax.set_ylim(-2, nlanes + 3)
def animate(frameNr):
sort_cars = sorted(cars, key=attrgetter("position"))
for i in range(numCars):
pos(sort_cars,i)
for k in range(numCars):
theta[k]=cars[k].position
point.set_data(theta, r)
return point,
def simulate():
anim = animation.FuncAnimation(fig, animate,
frames=numFrames, interval=10, blit=True, repeat=False)
plt.show()
simulate()
plot() returns a Line2D object, in which all points have the same color.
If you want your points to have different colors, you should use scatter(). The logic is exactly the same, except you use set_offsets(<2D array>) instead of set_data().
See this question for more details

Python: Animating two lists of lines using matplotlib.animation but only shows one set of lines at a time

Trying to plot persuit curves with spiraling in lines and a shrinking, rotating polygon with corners at each of the current points
problem = can't get both line of sight lines and main lines to simultaneously plot
The figure flicks back and forth between the shrinking polygon(described by SightLine) and the main persuit curves (MainLines)
When individually animated one at a time, the polygon and pursuit curves plot fine but I just can't get them to work together on the same figure.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
%matplotlib notebook
plt.style.use('dark_background')
NumOfPoints = 6
deltaT = 0.005
duration = 50
steps = int(duration / deltaT)
speed = 0.2
num = 0
CurrentXPoints = []
CurrentYPoints = []
DeltaX = np.zeros(NumOfPoints)
DeltaY = np.zeros(NumOfPoints)
MagnitudeDelta = np.zeros(NumOfPoints)
VelocityX = np.zeros(NumOfPoints)
VelocityY = np.zeros(NumOfPoints)
#Creates Initial Points by equally spacing the points around a polygon inscribed around circle
for i in range(0,NumOfPoints):
x = np.cos(((i/NumOfPoints)*2)*np.pi)
y = np.sin(((i/NumOfPoints)*2)*np.pi)
CurrentXPoints.append(x)
CurrentYPoints.append(y)
AllXPoints = np.array([CurrentXPoints])
AllYPoints = np.array([CurrentYPoints])
#Fills out both AllXPoints and AllYPoints with all points in duration
for i in range(int(steps)):
for j in range(0,NumOfPoints-1): #Calculates deltaX and deltaY at this timestep
DeltaX[j] = CurrentXPoints[j+1] - CurrentXPoints[j]
DeltaY[j] = CurrentYPoints[j+1] - CurrentYPoints[j]
DeltaX[NumOfPoints-1] = CurrentXPoints[0] - CurrentXPoints[NumOfPoints-1]
DeltaY[NumOfPoints-1] = CurrentYPoints[0] - CurrentYPoints[NumOfPoints-1]
for j in range(0,NumOfPoints): # calculats new X and Y Points
MagnitudeDelta[j] = ((DeltaX[j])**2 + (DeltaY[j])**2)**(1/2)
VelocityX[j] = speed * (DeltaX[j]/MagnitudeDelta[j])
VelocityY[j] = speed * (DeltaY[j]/MagnitudeDelta[j])
CurrentXPoints[j] += deltaT * VelocityX[j]
CurrentYPoints[j] += deltaT * VelocityY[j]
CurrentXPointsArr = np.array(CurrentXPoints)
CurrentYPointsArr = np.array(CurrentYPoints)
AllXPoints = np.vstack((AllXPoints,CurrentXPointsArr))
AllYPoints = np.vstack((AllYPoints,CurrentYPointsArr))
fig = plt.figure(figsize=(5,5))
ax = plt.axes()
ax.set_xlim(-2,2)
ax.set_ylim(-2,2)
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
MainLines = []
SightLines= []
AllLines = MainLines + SightLines
for i in range(NumOfPoints):
line, = ax.plot([AllXPoints[j][i] for j in range(steps)], [AllYPoints[j][i] for j in range(steps)])
MainLines.append(line)
SightLines.append(line)
def UpdateMain(num, AllXPoints, AllYPoints, MainLines):
for line in MainLines:
position = MainLines.index(line)
line.set_data([AllXPoints[i][position] for i in range(num)], [AllYPoints[i][position] for i in range(num)])
def UpdateSight(num, AllXPoints, AllYPoints, SightLines):
for line in SightLines:
position = SightLines.index(line)
if position < (NumOfPoints-1):
line.set_data([AllXPoints[num][position],AllXPoints[num][position+1]],
[AllYPoints[num][position],AllYPoints[num][position+1]])
else:
line.set_data([AllXPoints[num][position],AllXPoints[num][0]],
[AllYPoints[num][position],AllYPoints[num][0]])
ani1 = animation.FuncAnimation(fig, UpdateMain,steps, fargs=[AllXPoints, AllYPoints, MainLines],
interval=1, blit=True)
ani2 = animation.FuncAnimation(fig, UpdateSight,steps, fargs=[AllXPoints, AllYPoints, SightLines],
interval=1, blit=True)
plt.show()
First, you should use only one FuncAnimation that updates all the artists.
The main problem of your code are the lines
for i in range(NumOfPoints):
line, = ax.plot([AllXPoints[j][i] for j in range(steps)], [AllYPoints[j][i] for j in range(steps)])
MainLines.append(line)
SightLines.append(line)
where you are creating one artist (line) and assign it to two different lists. If you create 2 different lines for each list, then the output is as expected.
Full working code:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
%matplotlib notebook
plt.style.use('dark_background')
NumOfPoints = 6
deltaT = 0.005
duration = 50
steps = int(duration / deltaT)
speed = 0.2
num = 0
CurrentXPoints = []
CurrentYPoints = []
DeltaX = np.zeros(NumOfPoints)
DeltaY = np.zeros(NumOfPoints)
MagnitudeDelta = np.zeros(NumOfPoints)
VelocityX = np.zeros(NumOfPoints)
VelocityY = np.zeros(NumOfPoints)
def update(num, AllXPoints, AllYPoints, MainLines, SightLines):
out = []
out.append(UpdateMain(num, AllXPoints, AllYPoints, MainLines))
out.append(UpdateSight(num, AllXPoints, AllYPoints, SightLines))
return out
def UpdateMain(num, AllXPoints, AllYPoints, MainLines):
for line in MainLines:
position = MainLines.index(line)
line.set_data([AllXPoints[i][position] for i in range(num)], [AllYPoints[i][position] for i in range(num)])
return MainLines
def UpdateSight(num, AllXPoints, AllYPoints, SightLines):
for line in SightLines:
position = SightLines.index(line)
if position < (NumOfPoints-1):
line.set_data([AllXPoints[num][position],AllXPoints[num][position+1]],
[AllYPoints[num][position],AllYPoints[num][position+1]])
else:
line.set_data([AllXPoints[num][position],AllXPoints[num][0]],
[AllYPoints[num][position],AllYPoints[num][0]])
return SightLines
#Creates Initial Points by equally spacing the points around a polygon inscribed around circle
for i in range(0,NumOfPoints):
x = np.cos(((i/NumOfPoints)*2)*np.pi)
y = np.sin(((i/NumOfPoints)*2)*np.pi)
CurrentXPoints.append(x)
CurrentYPoints.append(y)
AllXPoints = np.array([CurrentXPoints])
AllYPoints = np.array([CurrentYPoints])
#Fills out both AllXPoints and AllYPoints with all points in duration
for i in range(int(steps)):
for j in range(0,NumOfPoints-1): #Calculates deltaX and deltaY at this timestep
DeltaX[j] = CurrentXPoints[j+1] - CurrentXPoints[j]
DeltaY[j] = CurrentYPoints[j+1] - CurrentYPoints[j]
DeltaX[NumOfPoints-1] = CurrentXPoints[0] - CurrentXPoints[NumOfPoints-1]
DeltaY[NumOfPoints-1] = CurrentYPoints[0] - CurrentYPoints[NumOfPoints-1]
for j in range(0,NumOfPoints): # calculats new X and Y Points
MagnitudeDelta[j] = ((DeltaX[j])**2 + (DeltaY[j])**2)**(1/2)
VelocityX[j] = speed * (DeltaX[j]/MagnitudeDelta[j])
VelocityY[j] = speed * (DeltaY[j]/MagnitudeDelta[j])
CurrentXPoints[j] += deltaT * VelocityX[j]
CurrentYPoints[j] += deltaT * VelocityY[j]
CurrentXPointsArr = np.array(CurrentXPoints)
CurrentYPointsArr = np.array(CurrentYPoints)
AllXPoints = np.vstack((AllXPoints,CurrentXPointsArr))
AllYPoints = np.vstack((AllYPoints,CurrentYPointsArr))
fig = plt.figure(figsize=(5,5))
ax = plt.axes()
ax.set_xlim(-2,2)
ax.set_ylim(-2,2)
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
MainLines = []
SightLines= []
AllLines = MainLines + SightLines
for i in range(NumOfPoints):
line1, = ax.plot([AllXPoints[j][i] for j in range(steps)], [AllYPoints[j][i] for j in range(steps)])
line2, = ax.plot([AllXPoints[j][i] for j in range(steps)], [AllYPoints[j][i] for j in range(steps)])
MainLines.append(line1)
SightLines.append(line2)
ani = animation.FuncAnimation(fig, update, steps, fargs=[AllXPoints, AllYPoints, MainLines, SightLines], interval=1, blit=True)
plt.show()

Strange Behaviour of Matplotlib Animation

I'm working on an animation that involves two stages, a "rotate" phase and a "fade" phase. The initial graph looks like this:
What I want is to first rotate the graph so that the black line is on the horizontal. Once that's accomplished, I want to fade out the red lines and blue points, so only the red points and black line are visible. My code for attempting this is below (this is in a jupyter cell).
data = m
def init():
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
ax.set(xlim=(-1.2, 1.2), ylim=(-1.2, 1.2))
ax.axis('off')
# Calculate Projections
best_u = get_best_u(m)
projected_points = line_projection(best_u, m)
projection_main_line, = ax.plot(projected_points[0], projected_points[1], c='black')
projection_points, = ax.plot(projected_points[0], projected_points[1], 'or')
projection_lines = []
for i in range(projected_points.shape[1]):
temp_line = ax.plot([m[0, i], projected_points[0, i]], [m[1, i], projected_points[1, i]], '-r')
projection_lines.append(temp_line)
data_line, = ax.plot(m[0], m[1], linestyle='', marker='o')
proj_lines = update_helper(projection_lines, 0)
return [data_line, projection_main_line, projection_points, *proj_lines]
def update_helper(projection_lines, i):
return_list = []
if i < len(projection_lines):
line, = projection_lines[0]
return [line]
else:
line, = projection_lines[i]
return_list.append(line)
next_list = update_helper(projection_lines, i+1)
return return_list + next_list
def rotate_stage(deg, data):
data = rotate_matrix(data, -deg).T
best_u = get_best_u(data)
projected_points = line_projection(best_u, data)
projection_main_line.set_data(projected_points[0], projected_points[1])
projection_points.set_data(projected_points[0], projected_points[1])
for i in range(len(projection_lines)):
line, = projection_lines[i]
line.set_data(
[data[0, i], projected_points[0, i]],[data[1, i], projected_points[1, i]]
)
data_line.set_data(data[0], data[1])
proj_lines = update_helper(projection_lines, 0)
return [data_line, projection_main_line, projection_points, *proj_lines]
def fade_stage(i):
for i in range(len(projection_lines)):
line, = projection_lines[i]
line.set_alpha(max(1 - i*0.05, 0))
data_line.set_alpha(max(1 - i*0.05, 0))
proj_lines = update_helper(projection_lines, 0)
return [data_line, *proj_lines]
def update(i, data):
if i < 45:
return rotate_stage(i, data)
else:
return fade_stage(i - 44)
anim = FuncAnimation(fig, update, interval=1, init_func=init, fargs=[data],frames=64, blit=True)
HTML(anim.to_html5_video())
anim.save('test.mp4', fps=20, dpi=80)
The resulting output looks like this:
I don't quite understand why this is happening - I thought it would first cycle through the rotation and then cycle through the fade, but clearly that's not what's happening. Any insights would be appreciated.

Graph autoscale, python

I've made a graph and here is my code:
def graphdraw(self):
self.xaxis = []
self.yaxis = []
fig=plt.figure(1)
self.ax=fig.add_subplot(111)
plt.xlabel('Wavelenght[nm]')
plt.ylabel('Intensity[arb. unit]')
self.line, = self.ax.plot(self.xaxis,self.yaxis,'g-', linewidth=1.5, markersize=4)
self.ax.set_xlim(-250,250)
self.ax.set_ylim(0,40000)
def drawg(self):
self.graphdraw()
i = -200
while i <= 200:
self.xaxis.append(i)
self.yaxis.append(i*i)
self.line.set_data(self.xaxis,self.yaxis)
plt.draw()
plt.pause(0.1)
i = i + 1
But I'd like it to autoscale axis, and when i do something like this: self.ax.autoscale_view(True,True,True) instead of these lines: self.ax.set_lim... it does not work. I know it may be stupid and trivial question but can anyone help me please?
Ok, nevermind. I've made my own autoscale.
def graphdraw(self):
self.xaxis = []
self.yaxis = []
fig=plt.figure(1)
self.ax=fig.add_subplot(111)
plt.xlabel('Wavelenght[nm]')
plt.ylabel('Intensity[arb. unit]')
self.line, = self.ax.plot(self.xaxis,self.yaxis,'g-', linewidth=1.5, markersize=4)
self.ax.set_xlim(-250,250)
def drawg(self):
self.graphdraw()
i = -200
start = 50
while i <= 200:
z = random.randint(0,450)
self.ax.set_ylim(0,start)
self.xaxis.append(i)
self.yaxis.append(z)
if z > start:
start= z
self.ax.set_ylim(0,start + 50)
self.line.set_data(self.xaxis,self.yaxis)
plt.draw()
plt.pause(0.1)
i = i + 1

Categories

Resources