Scatter plot distance in matplotlib python - python

I've recently been using Python. I made a plot with matplotlib and I can see my values. The problem is that they are too far apart. This does not change if x increases by 1 or if x increases by 0.1. I wish the scatters were closer together. This is my code:
x = [0]
y = [0]
plt.plot(x,y)
Class Graph(Screen):
def __init__(self,**kw):
super().__init__(**kw)
self.app = App.get_running_app()
self.i = 0
self.ids.graph.add_widget(FigureCanvasKivyAgg(plt.gcf()))
def update_graph(self):
self.i += 1
x.append(self.i)
y.append(self.app.value())
plt.plot(x,y)
plt.draw
I've tried with self.i += 0.1 but it's the same of self.i += 1. Is it possible to view the value near?

Related

Integrate Class

So I have been trying to create an integrate class for an assignment and while I have gotten a simple skeletal structure for the functions within said class, I keep on getting a None result, which really bugs me. The code that I have written down though is written below.
What do I do to make this code work?
import math
class Integrator():
def __init__(self, xMin, xMax, N):
x = []
self.xMin = min(x)
self.xMax = max(x)
self.N = N
def I(self, x):
(x**2)*np.exp(-x)*np.sin(x)
def integrate(self):
y = list(np.arange(self.xMin, self.xMax, self.N))
tot = 0
i = 0
while i < self.xMax:
tot += y [i]
i += self.N
np.sum(tot)*(self.xMax-self.xMin)/self.N
examp = Integrator(1,3,20000)
examp.integrate()
You're missing a return statement on the integrate and I methods. That is why they both exclusively return None.
Beyond that, there are some other issues. For example, the min and max statements here will not work. These operators do not work on an empty sequence (which is what x is). Perhaps you meant self.xMin = xMin?
class Integrator():
def __init__(self, xMin, xMax, N):
x = []
self.xMin = min(x)
self.xMax = max(x)
Beyond that, there are some curiosities with the integrate method. For example, the while loop will only do one iteration, because i < self.xMax (which is 3 in your example), but every iteration i gets incremented by self.N (which is 20000 in your example).
np.sum(tot) is also illogical, as that only works when tot is "array-like", but tot is just a float (or int). No need to sum one of those.
Then, list(np.arange(self.xMin, self.xMax, self.N)) likely does not do what you're expecting. np.arange is given a start, stop and step parameter. That means that it starts at 1 (self.xMin), then sets a step of 20000 (self.N), and then because that is larger than stop of 3 (self.xMax), it will not include that one. So, y = [1]. Maybe you'd want y = list(np.arange(self.xMin, self.xMax, 1 / self.N)), so that the step is such that y has a length of 40000.
That said, I have no idea what you're expecting to get returned from this method. Perhaps it's along the lines of this though:
import math
import numpy as np
class Integrator():
def __init__(self, xMin, xMax, N):
x = []
self.xMin = xMin
self.xMax = xMax
self.N = N
def I(self, x):
return (x**2)*np.exp(-x)*np.sin(x)
def integrate(self):
y = list(np.arange(self.xMin, self.xMax, 1 / self.N))
tot = 0
i = 0
while i < len(y):
tot += y[i]
i += 1
return tot*(self.xMax-self.xMin)/self.N
examp = Integrator(1,3,20000)
print(examp.integrate())
Which returns 7.999900000008443.

Animate the evolution of a Markov Chain on a 2 dimensional array with python matplotlib imshow

I am trying to write the Metropolis Algorithm for the Hardcore Model on the 2 dimensional lattice. The algorithm I wrote so far seems to work and is as follows:
-Pick a vertex of the 2-d lattice
-Toss a fair coin
-If the coin comes up heads and all neighbors of the vertex take value 0 then set the vertex to 1 otherwise to 0.
I try to animate the evolution of the lattice. Here is what I wrote so far:
The Algorithm to simulate works. The animation not as I want.
Here is the algorithm:
import random
from matplotlib import animation
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def Nachbarn(x0,x1,B): #test neighbours
if x1 +1 < len(B) and B[x0][x1+1] == 1 : #top
return True
elif x0 + 1 < len(B) and B[x0+1][x1] == 1 : #right
return True
elif x1 -1 >= 0 and B[x0][x1 -1] == 1 : #down
return True
elif x0 -1 >= 0 and B[x0-1][x1] == 1 : #left
return True
else:
return False
def Eckenwahl(B):
Länge = len(B)
x = random.choices(range(Länge),k=2) #choose a vertex
x0 = x[0]
x1 = x[1]
return x0,x1
def Münzwurf():
value = random.randint(0,1) #Toss a coin
return value
def MCMC(Array): #MCMC i-te Iteration
Ecke = Eckenwahl(Array)
if Münzwurf() == 1 and Nachbarn(Ecke[0],Ecke[1],Array) == False:
Array[Ecke[0]][Ecke[1]] = 1
else:
Array[Ecke[0]][Ecke[1]] = 0
return Array
Now, initialize the lattice:
N = 10 #Initialisierung of empty lattice
A = [[0] * N for i in range(N)]
If I apply the function MCMC on the array "A" a few times and start the animation with a non-empty lattice:
for i in range(5):
A = MCMC(A)
the animation seems to run, otherwise its stuck in the empty lattice and does not move forward. But I want to start it with an empty lattice. Here are two solutions that have these constraints so far:
Solution 1:
fig = plt.figure()
im = plt.imshow(A, animated = True)
def update_fig(*args):
global A
B = MCMC(A)
im.set_data(B)
return im
ani = animation.FuncAnimation(fig, update_fig, interval = 1)
plt.show()
Solution 2:
fps = 300
nSeconds = 10
fig = plt.figure( figsize=(8,8) )
a = A
im = plt.imshow(A)
def animate_func(i):
im.set_array(MCMC(A))
return [im]
anim = animation.FuncAnimation(fig, animate_func, frames = nSeconds *
fps,interval = 1000 / fps,)
The issue is, everything is ready. I want to start with a 2-d array/lattice that is full with 0`s called the empty configuration then, at time t=1 apply the function MCMC on the array, next display it in the animation and so on for t=2,3,...
Thanks for the help!

Plotting a function in python matplotlib

Here is my code:
import random
import numpy as np
import matplotlib.pyplot as plt
import agent
deer = agent.Agent()
print(deer.x,deer.y)
deer.step()
print(deer.x,deer.y)
def walk(length):
for i in range(length):
#while deer.x <= i:
deer.step()
countx= deer.x + 1
county=deer.y +1
#print(countx,county)
x= countx
y= county
return deer.step()
walk(100)
walker = walk(100)
plt.plot(walk[0],walk[1],label= 'Random walk')
plt.scatter(walk[0],walk[1],s=50,c=range(101))
plt.show()
I'm trying to get the count step of x and y to be graphed.But I don't understand why it wont recognize the x and y values within the function. The goal is to plot the 100 random steps taken.
After there is a plot from the 100 steps taken, I'm trying to create a second Method for taking a step. Instead of choosing a random new angle and moving, the current orientation of the agent should change by a random amount chosen from a normal distribution with mean 0 and standard deviation Sigma=1 (self.orientation = self.orientation + np.random.normal(0,Sigma)).
It's also suppose to walk 100 steps, and show the trajectory using matplolib, and show the distance between the agent and it's starting point.
I used the class Agent:
class Agent:
# initializer with default argument value
def __init__(self,sigma=0.5):
self.x = 0.0 # agent's x position
self.y = 0.0 # agent's y position
self.o = 0.0 # agent's orientation
self.v = 1.0 # agent's velocity
self.sigma = sigma
def step(self):
self.o = random.random()*2*np.pi
self.x +=self.v*np.cos(self.o)
self.y += self.v*np.sin(self.o)
def turn(self):
self.o += np.random.normal(0,self.sigma)
self.x += self.v*np.cos(self.o)
self.y += self.v*np.sin(self.o)
def distance(self):
return np.sqrt(self.x**2 + self.y**2)

How to resize graph to fixed dimensions in matplotlib animation

I am wanting to plot two list in real time using matplotlib animation, with the help of the community I was able to plot my graph. I am now wanting to simplify my real time animation a bit as well as re-structure my graph.
Here are my objectives:
Plot x-axis: length of list "my_average"
Plot y-axis: elements in list "my_average"
y-axis limit -1 to 1 (all my elements in list "my_average" are between -1 and 1)
I do not know what I am doing wrong with my code thus far:
class StdOutListener(StreamListener):
def on_data(self, data):
json_load = json.loads(data)
texts = json_load['text'] # string
#print(texts)
#drop zero in list
if 0 in my_list: my_list.remove(0)
#print
#calculate average
average = numpy.mean(my_list)
b = my_average.append(average)
print "average =", my_average
def __init__(self):
self.start_time = time.time()
self.x = [len(my_average)]
self.y = [my_average]
self.my_average = []
self.line_actual, = plot(self.x, self.y) # line stores a Line2D we can update
self.line_average, = plot(self.x, self.my_average) # line stores a Line2D we can update
def on_data(self, new_value):
time_delta = time.time() - self.start_time # on our x axis we store time since start
self.x.append(time_delta)
self.y.append(new_value)
self.my_average.append(numpy.mean(self.y))
self.line_actual.set_data(self.x, self.y)
self.line_average.set_data(self.x, self.my_average)
ylim([min(self.y), max(self.y)]) # update axes to fit the data
xlim([0, max(self.x)])
draw() # redraw the plot
ion() # ion() allows matplotlib to update animations.
out_listener = StdOutListener()
for i in range(10000):
out_listener.on_data(i + numpy.random.randint(-5,5))
Thank you in Advance
So:
I'm not sure what you mean by plot length of the list. But I assume you want to create an index array with indices from 0 to len(my_average). That is what range is for:
self.x = range(len(my_average))
You already use the ylim function, which does exactly what you want. But instead of passing the min/max of your data you just have to pass your desired static values:
ylim(-1, 1)

Animated scatterplot of data with Matplotlib

I tried to adapt animated scatter plot-example in such a way, so it shows real-time the results of an agent based-model I developed. However, the result shown in the graph are not that what I except them to be.
It goes wrong when updating the values, and strange patterns appear where the agents tend to cluster in a diagonal line.
I added some simple code that illustrates this problem. Does anyone has an idea what goes wrong?
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
import os
n = 25 ## nr of agents
x,y = 10, 10 ## matrix of x by y dimension
dataX, dataY, binaryRaster = [],[],[]
class AnimatedScatter(object):
"""An animated scatter plot using matplotlib.animations.FuncAnimation."""
def __init__(self):
global n
self.numpoints = n
self.stream = self.data_stream()
self.fig, self.ax = plt.subplots()
self.ax.set_title("My first Agent Based Model (ABM)",fontsize=14)
self.ax.grid(True,linestyle='-',color='0.75')
self.ani = animation.FuncAnimation(self.fig, self.update, interval=100,
init_func=self.setup_plot, blit=True,
repeat=False)
def setup_plot(self):
"""Initial drawing of the scatter plot."""
global x,y
dataX,dataY = next(self.stream)
self.scat = self.ax.scatter(dataY, dataX, c="tomato", s=20, animated=True)
self.ax.axis([0, y, x, 0])
return self.scat,
def data_stream(self):
"""Generate a random walk (brownian motion). Data is scaled to produce
a soft "flickering" effect."""
global x,y, n
dataX,dataY = self.createRandomData()
#printing results to ascii for validation
lines = []
binaryData = np.zeros((x,y), dtype=np.int)
for i in range(n):
binaryData[dataX,dataY] =1
for i in range(x):
line = ""
for j in range(y):
line += str(binaryData[i,j])+ ","
line= line[:-1]+ "\n"
lines.append(line)
lines.append("\n")
yx = np.array([dataY,dataX])
cnt = 0
while cnt < 10:
dataX,dataY = self.createRandomData()
yx = np.array([dataY,dataX])
#printing results to ascii for validation
binaryData = np.zeros((x,y), dtype=np.int)
for i in range(n):
binaryData[dataX,dataY] =1
for i in range(x):
line = ""
for j in range(y):
line += str(binaryData[i,j])+ ","
line= line[:-1]+ "\n"
lines.append(line)
lines.append("\n")
cnt+=1
yield yx
#printing results to ascii for validation
outNm = os.getcwd()+"\\ScatterValidation.txt"
outfile = open(outNm, "w")
outfile.writelines(lines)
outfile.close()
return
def update(self, i):
"""Update the scatter plot."""
data = next(self.stream)
self.scat.set_offsets(data[:2, :])
return self.scat,
def show(self):
plt.show()
def createRandomData(self):
"""Positions n agents randomly on a raster of x by y cells.
Each cell can only hold a single agent."""
global x,y,n
binaryData = np.zeros((x,y), dtype=np.int)
newAgents = 0
dataX,dataY = [],[]
while newAgents < n:
row = np.random.randint(0,x,1)[0]
col = np.random.randint(0,y,1)[0]
if binaryData[row][col] != 1:
binaryData[row][col] = 1
newAgents+=1
for row in range(x):
for col in range(y):
if binaryData[row][col] == 1:
dataX.append(row)
dataY.append(col)
return dataX, dataY
def main():
global n, x, y, dataX, dataY, binaryRaster
a = AnimatedScatter()
a.show()
return
if __name__ == "__main__":
main()
You can fix your script in 2 ways, both involve changing the update function:
Using a scatter call in the update function, is clearer I think
Transposing the data array before calling set_offsets in update
Using a scatter call is the clearest fix, and you could increase the agents during your run:
def update(self, i):
"""Update the scatter plot."""
dataX, dataY = next(self.stream)
self.scat = self.ax.scatter(dataX, dataY, c="tomato", s=20, animated=True)
return self.scat,
Transposing the offsets array will also work:
def update(self, i):
"""Update the scatter plot."""
data = next(self.stream)
self.scat.set_offsets(data.transpose())
return self.scat,
Offsets are given as a N tuples of 2 items each while the data array is given as 2 tuples with N items each, transposing the data array will fix your problem.
Note: If you do not change the global variables, you do not need to specify the globals with a global statement, so in setup_plot, __init__ etc. you can remove the global n,x,y lines.
I would put n,x and y as instance variables of your class, plus there is no need for dataX, dataY and binaryRasted to be defined at the top of your script.

Categories