Python file generates points to plot - RuntimeError - python

UPDATED:
I would like to plot real time y values generated randomly from Random_Generation_List.py. I have imported the python file and have them in the same folder. The points are only being printed and show only a vertical line on the graph. How do I fix this to make the points plot onto the graph in real time? Like a point every 0.001?
Random_Generation_List:
import random
import threading
def main():
for count in range(12000):
y = random.randint(0,1000)
print(y)
def getvalues():
return [random.randint(0,1000) for count in range(12000)]
def coordinate():
threading.Timer(0.0001, coordinate).start ()
coordinate()
main()
Real_Time_Graph
import time
from collections import deque
from matplotlib import pyplot as plt
from matplotlib import style
import Random_Generation_List
start = time.time()
class RealtimePlot:
def __init__(self, axes, max_entries = 100):
self.axis_x = deque(maxlen=max_entries)
self.axis_y = deque(maxlen=max_entries)
self.axes = axes
self.max_entries = max_entries
self.lineplot, = axes.plot([], [], "g-")
self.axes.set_autoscaley_on(True)
def add(self, x, y):
self.axis_x.append(x)
self.axis_y.append(y)
self.lineplot.set_data(self.axis_x, self.axis_y)
self.axes.set_xlim(self.axis_x[0], self.axis_x[-1] + 1e-15)
self.axes.relim(); self.axes.autoscale_view() # rescale the y-axis
def animate(self, figure, callback, interval = 50):
def wrapper(frame_index):
self.add(*callback(frame_index))
self.axes.relim(); self.axes.autoscale_view() # rescale the y-axis
return self.lineplot
def main():
style.use('dark_background')
fig, axes = plt.subplots()
display = RealtimePlot(axes)
axes.set_xlabel("Seconds")
axes.set_ylabel("Amplitude")
values = Random_Generation_List.getvalues()
print(values)
while True:
display.add(time.time() - start, values)
plt.pause(0.001)
display.animate(fig, lambda frame_index: (time.time() - start, values))
plt.show()
if __name__ == "__main__": main()
Error Message:
raise RuntimeError('xdata and ydata must be the same length')
RuntimeError: xdata and ydata must be the same length

Related

Is there a way to change the x ticks to strings (say time) on pyqtgraph and keep the autoformat so the tick dont bunch up

The end goal would be to run this for a while with a 1 second pause and show the last hour (if it can handle that),so n = 3600 and t something higher . It plots well with line 37 (ax.setTicks(dx)) commented out, but I would like to display the time on the x-axis. If I uncomment that line, the xticks have the time, but they dont autoformat and bunch up on each other. Is setTickSpacing the right way to fix this? I've tried it and I couldn't get it to work in this case.
import sys
from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import pyqtgraph as pg
import time
import datetime as dt
x = []
y = []
timelist = []
pw = pg.plot(x, y)
n = 25
i = 0
t = 500
while i < t:
if i < n:
xdata = i
x.append(xdata)
currentTime = (dt.datetime.now()).strftime("%M:%S")
timelist.append(currentTime)
timelist = timelist[-n:]
ticks = [list(zip(range(n), timelist))]
ydata = np.random.randint(0,9)
y.append(ydata)
y = y[-n:]
pw.plot(x, y, pen = 'y', clear=True)
ax = pw.getAxis('bottom')
dx = [value for value in ticks]
#ax.setTicks(dx)
#ax.setTickSpacing(0,0,0)
pg.QtGui.QApplication.processEvents()
time.sleep(.01)
i = i + 1
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
You have to correctly build the information of the ticks, also you should not use an infinite loop or sleep(), instead use QTimer.
import datetime as dt
import sys
import numpy as np
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
x, y, timelist = [], [], []
n, i, t = 25, 0, 500
pw = pg.plot(x, y)
def on_timeout():
global i, x, y, timelist
if i < n:
x.append(i)
i += 1
ydata = np.random.randint(0, 9)
y.append(ydata)
y = y[-n:]
pw.plot(x, y, pen="y", clear=True)
currentTime = dt.datetime.now().strftime("%M:%S")
timelist.append(currentTime)
timelist = timelist[-n:]
ticks = list(enumerate(timelist))
ax = pw.getAxis("bottom")
ax.setTicks([ticks])
timer = QtCore.QTimer(timeout=on_timeout, interval=100)
timer.start()
pw.win.showMaximized()
if __name__ == "__main__":
if (sys.flags.interactive != 1) or not hasattr(QtCore, "PYQT_VERSION"):
QtGui.QApplication.instance().exec_()
I struggled with this for a long time but it's relatively straightforward in the end. You cannot use setTicks with autoformattingb but you can create a list or a dict of axis values in your plotting class and access it in AxisItem class. It's not exactly a pretty solution but it does work.
Subclass AxisItem for X axis:
class customAxisItem(pg.AxisItem):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def tickStrings(self, values, scale, spacing):
return [Plotter.timeValues[int(v)-1] for v in values]
Then tell the plotter to use the axis and create the list of tickvalues:
class Plotter():
(...)
self.chartWidget = pg.PlotWidget(axisItems={'bottom': CustomAxisItem(orientation='bottom')})
self.timeValues = [0.25, 0.50, 0.759]
(...)

How to run a python program 10 times in a loop and plot the rsults in each time

I am trying to run this code. We run the EM for 10 loops and plot the result in each loop. You want to observe the progress for each EM loop below.
X = np.linspace(-5,5,num=20)
X0 = X*np.random.rand(len(X))+10 # Create data cluster 1
X1 = X*np.random.rand(len(X))-10 # Create data cluster 2
X2 = X*np.random.rand(len(X)) # Create data cluster 3
X_tot = np.stack((X0,X1,X2)).flatten() # Combine the clusters to get the random datapoints from above
class GMD:
def __init__(self,X,iterations):
self.iterations = iterations
self.X = X
self.mu = None
self.pi = None
self.var = None
def run(self):
self.mu = [-8,8,5]
self.pi = [1/3,1/3,1/3]
self.var = [5,3,1]
for iter in range(self.iterations):
r = np.zeros((len(X_tot),3))
for c,g,p in zip(range(3),[norm(loc=self.mu[0],scale=self.var[0]),
norm(loc=self.mu[1],scale=self.var[1]),
norm(loc=self.mu[2],scale=self.var[2])],self.pi):
r[:,c] = p*g.pdf(X_tot)
for i in range(len(r)):
r[i] = r[i]/(np.sum(pi)*np.sum(r,axis=1)[i])
"""Plot the data"""
fig = plt.figure(figsize=(10,10))
ax0 = fig.add_subplot(111)
for i in range(len(r)):
ax0.scatter(self.X[i],0,c=np.array([r[i][0],r[i][1],r[i][2]]),s=100)
"""Plot the gaussians"""
for g,c in zip([norm(loc=self.mu[0],scale=self.var[0]).pdf(np.linspace(-20,20,num=60)),
norm(loc=self.mu[1],scale=self.var[1]).pdf(np.linspace(-20,20,num=60)),
norm(loc=self.mu[2],scale=self.var[2]).pdf(np.linspace(-20,20,num=60))],['r','g','b']):
ax0.plot(np.linspace(-20,20,num=60),g,c=c)
var_c.append((1/m_c[c])*np.dot(((np.array(r[:,c]).reshape(60,1))*(self.X.reshape(len(self.X),1)-self.mu[c])).T,(self.X.reshape(len(self.X),1)-self.mu[c])))
plt.show()
GMD = GMD(X_tot,10)
GMD.run()
But after running this code it's showing this below error as a output
this message showing when I am going to run this code
You could make another file and import your class and do:
for x in range(0,9):
class.function()
I'm unable to reply to Klaus' answer but as he pointed out, you might have missed self while calling the pi value on one occasion:
for i in range(len(r)):
r[i] = r[i]/(np.sum(pi)*np.sum(r,axis=1)[i]) # Here the pi should be self.pi

Scale which is logarithmic to other point than zero [duplicate]

I'm trying to scale the x axis of a plot with math.log(1+x) instead of the usual 'log' scale option, and I've looked over some of the custom scaling examples but I can't get mine to work! Here's my MWE:
import matplotlib.pyplot as plt
import numpy as np
import math
from matplotlib.ticker import FormatStrFormatter
from matplotlib import scale as mscale
from matplotlib import transforms as mtransforms
class CustomScale(mscale.ScaleBase):
name = 'custom'
def __init__(self, axis, **kwargs):
mscale.ScaleBase.__init__(self)
self.thresh = None #thresh
def get_transform(self):
return self.CustomTransform(self.thresh)
def set_default_locators_and_formatters(self, axis):
pass
class CustomTransform(mtransforms.Transform):
input_dims = 1
output_dims = 1
is_separable = True
def __init__(self, thresh):
mtransforms.Transform.__init__(self)
self.thresh = thresh
def transform_non_affine(self, a):
return math.log(1+a)
def inverted(self):
return CustomScale.InvertedCustomTransform(self.thresh)
class InvertedCustomTransform(mtransforms.Transform):
input_dims = 1
output_dims = 1
is_separable = True
def __init__(self, thresh):
mtransforms.Transform.__init__(self)
self.thresh = thresh
def transform_non_affine(self, a):
return math.log(1+a)
def inverted(self):
return CustomScale.CustomTransform(self.thresh)
# Now that the Scale class has been defined, it must be registered so
# that ``matplotlib`` can find it.
mscale.register_scale(CustomScale)
z = [0,0.1,0.3,0.9,1,2,5]
thick = [20,40,20,60,37,32,21]
fig = plt.figure(figsize=(8,5))
ax1 = fig.add_subplot(111)
ax1.plot(z, thick, marker='o', linewidth=2, c='k')
plt.xlabel(r'$\rm{redshift}$', size=16)
plt.ylabel(r'$\rm{thickness\ (kpc)}$', size=16)
plt.gca().set_xscale('custom')
plt.show()
The scale consists of two Transform classes, each of which needs to provide a transform_non_affine method. One class needs to transform from data to display coordinates, which would be log(a+1), the other is the inverse and needs to transform from display to data coordinates, which would in this case be exp(a)-1.
Those methods need to handle numpy arrays, so they should use the respective numpy functions instead of those from the math package.
class CustomTransform(mtransforms.Transform):
....
def transform_non_affine(self, a):
return np.log(1+a)
class InvertedCustomTransform(mtransforms.Transform):
....
def transform_non_affine(self, a):
return np.exp(a)-1
There's no need to define classes yourself even the answer from #ImportanceOfBeingErnest does work.
You can use either FunctionScale or FunctionScaleLog to do this in one line. Take the FunctionScaleLog as example:
plt.gca().set_xscale("functionlog", functions=[lambda x: x + 1, lambda x: x - 1])
And with your full code:
import matplotlib.pyplot as plt
import numpy as np
z = [0, 0.1, 0.3, 0.9, 1, 2, 5]
thick = [20, 40, 20, 60, 37, 32, 21]
fig = plt.figure(figsize=(8, 5))
ax1 = fig.add_subplot(111)
ax1.plot(z, thick, marker="o", linewidth=2, c="k")
plt.xlabel(r"$\rm{redshift}$", size=16)
plt.ylabel(r"$\rm{thickness\ (kpc)}$", size=16)
# Below is my code
plt.gca().set_xscale("functionlog", functions=[lambda x: x + 1, lambda x: x - 1])
plt.gca().set_xticks(np.arange(0, 6))
plt.gca().set_xticklabels(np.arange(0, 6))
And the result is:

Animate scatter plot

I'm building a Python tool for visualizing data structures in 3D. The code below is the full program, it's even set up to run a default test model with some random data; you just need numpy and matplotlib. Basically, you declare a Node, connect it to other Nodes, and it makes pretty 3D networks. I'd like to be able to call switchNode() and have it flip the color of a node between black and white. With the way it works right now, every time a Node is instantiated, the plot is added to with another data point. I'm not familiar enough with matplotlib's animation tools to know the best way of doing this (my attempt at following the example from another post is commented out on line 83, and hoped someone could offer me some tips. Thanks!!
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.animation as anim
# user-defined variables
debug = False
axisOn = False
labelsOn = True
maxNodes = 20
edgeColor = 'b'
dottedLine = ':'
darkGrey = '#191919'
lightGrey = '#a3a3a3'
plotBackgroundColor = lightGrey
fontColor = darkGrey
gridColor = 'k'
numFrames = 200
# global variables
fig = None
hTable = []
ax = None
numNodes = 0
# initialize plot
def initPlot():
global ax, fontColor, fig
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d', axisbg=plotBackgroundColor)
if axisOn == False:
ax.set_axis_off()
else:
ax.set_axis_on()
fontColor = darkGrey
# gives n random float values between vmin and vmax
def randrange(n, vmin, vmax):
return (vmax - vmin) * np.random.rand(n) + vmin
# builds an empty node with a given value, helper method for makeNode
def makeNodeS(value):
global hTable, numNodes
n = Node(value)
hTable.append(n)
numNodes = len(hTable)
return n
# builds a node with given parameters
def makeNode(value, location, color, marker):
n = makeNodeS(value)
n.setLoc(location)
n.setStyle(color, marker)
if debug:
print("Building node {} at {} with color = {}, marker = {}, and associations = {}.".format(value, location, color, marker, n.assocs))
return n
# aggregate nodes in hTable and plot them in 3D
def plotNodes():
global hTable
if debug:
print("Plotting Graph...")
for elem in hTable:
if debug:
print(" Plotting node {}...".format(elem.value))
global fig, numFrames
scat = ax.scatter(elem.location[0], elem.location[1], elem.location[2], c=elem.color, marker=elem.marker)
for c in elem.assocs:
if (getNode(c).value != elem.value):
if elem.count in getNode(c).assocs: # if the two nodes are associated to each other, draw solid line
ax.plot([elem.location[0], getNode(c).location[0]], [elem.location[1], getNode(c).location[1]], [elem.location[2], getNode(c).location[2]], edgeColor)
if debug:
print(" Plotting double edge between {} and {}...".format(elem.value, getNode(c).value))
else:
ax.plot([elem.location[0], getNode(c).location[0]], [elem.location[1], getNode(c).location[1]], [elem.location[2], getNode(c).location[2]], edgeColor + dottedLine)
if debug:
print(" Plotting single edge from {} to {}...".format(elem.value, getNode(c).value))
#ani = anim.FuncAnimation(fig, update_plot, frames=xrange(numFrames), fargs=(['b', 'w'], scat))
# build single connection from node A to node B
def sConnect(nodeA, nodeB):
nodeA.addAssoc(nodeB)
if debug:
print(" Drawing single connection from node {} to node {}...".format(nodeA.value, nodeB.value))
# build double connection from node A to node B, and from node B to node A
def dConnect(nodeA, nodeB):
if debug:
print("\nDouble node connection steps:")
sConnect(nodeA, nodeB)
sConnect(nodeB, nodeA)
# update scatter with new color data
def update_plot(i, data, scat):
scat.set_array(data[i])
return scat
# returns the node with given count
def getNode(count):
global hTable
n = hTable[count-1]
return n
# set up axis info
def defineAxis():
ax.set_xlabel('X Label')
ax.xaxis.label.set_color(lightGrey)
ax.tick_params(axis='x', colors=lightGrey)
ax.set_ylabel('Y Label')
ax.yaxis.label.set_color(lightGrey)
ax.tick_params(axis='y', colors=lightGrey)
ax.set_zlabel('Z Label')
ax.zaxis.label.set_color(lightGrey)
ax.tick_params(axis='z', colors=lightGrey)
# randomly populate nodes and connect them
def test():
for i in range (0, maxNodes):
rand = np.random.rand(2)
if (0 <= rand[0] <= 0.25):
q = makeNode(i, np.random.rand(3), 'r', '^')
elif (0.25 < rand[0] <= 0.5):
q = makeNode(i, np.random.rand(3), 'b', 'o')
elif (0.5 < rand[0] <= 0.75):
q = makeNode(i, np.random.rand(3), 'g', 'v')
elif (0.75 < rand[0]):
q = makeNode(i, np.random.rand(3), 'w', 'o')
if (0 < i < maxNodes-1):
if (rand[1] <= 0.2):
dConnect(q, getNode(q.count-1))
elif (rand[1] < 0.5):
sConnect(q, getNode(q.count-1))
# randomly populate binary nodes and connect them
def test2():
for i in range (0, maxNodes):
rand = np.random.rand(2)
if (0 <= rand[0] <= 0.80):
q = makeNode(i, np.random.rand(3), 'k', 'o')
else:
q = makeNode(i, np.random.rand(3), 'w', 'o')
if (i > 0):
if (rand[1] <= 0.2):
dConnect(q, getNode(q.count-1))
elif (rand[1] > 0.2):
sConnect(q, getNode(q.count-1))
# switches a binary node between black and white
def switchNode(count):
q = getNode(count)
if (q.color == 'b'):
q.color = 'w'
else:
q.color = 'b'
# main program
def main():
## MAIN PROGRAM
initPlot()
test2()
plotNodes()
defineAxis()
plt.show()
# class structure for Node class
class Node(str):
value = None
location = None
assocs = None
count = 0
color = None
marker = None
# initiate node
def __init__(self, val):
self.value = val
global numNodes
numNodes += 1
self.count = numNodes
self.assocs = []
self.color = 'b'
self.marker = '^'
# set node location and setup 3D text label
def setLoc(self, coords):
self.location = coords
global labelsOn
if labelsOn:
ax.text(self.location[0], self.location[1], self.location[2], self.value, color=fontColor)
# define node style
def setStyle(self, color, marker):
self.color = color
self.marker = marker
# define new association
def addAssoc(self, newAssociation):
self.assocs.append(newAssociation.count)
if debug:
print(" Informing node association: Node {} -> Node {}".format(self.value, newAssociation.value))
main()
Scatter returns a collection and you can change the colors of the points in a collection with set_facecolor. Here's an example you can adapt for your code:
plt.figure()
n = 3
# Plot 3 white points.
c = [(1,1,1), (1,1,1), (1,1,1)]
p = plt.scatter(np.random.rand(n), np.random.rand(n), c = c, s = 100)
# Change the color of the second point to black.
c[1] = (0,0,0)
p.set_facecolor(c)
plt.show()

Matplotlib scatter plot animation keeps crashing Python

I've found some flaky resources online about what to do when a matplotlib animation crashes Python.
Here is the code. I know that certain changes to the number of points or smallness of the dt variable might cause some overwhelming computation, but I could really use some help. Overall it behaves extremely slowly and I need to have this running smoothly. The code is for a physics class and it is not an optimization problem - the goal of the project is not to optimize matplotlib's animation facilities but to model a system in phase space. I could use any help I can get.
import matplotlib
#matplotlib.use("TkAgg")
from matplotlib import animation
import matplotlib.pyplot as plt
import matplotlib.pylab as pl
import numpy as np
import math
# Create the window and the plot.
fig = plt.figure()
fig.canvas.set_window_title("Modelling Non-Linear Chaotic Systems in Phase ")
ax = fig.add_subplot(111)
##### CONSTANTS #####
NUM_POINTS = 40 # The number of points to discretize.
AUTOSCALE = False # Sets autoscale to true or false. If true, there will be odd (expected to a degree) behavior as time goes on.
NO_TRAIL = False # Adds a trail.
##### CONSTANTS #####
##### Cool Settings #####
# Double tail swirl.
# k = .2
# alpha = .4
# dt = .1
##### #####
##### VARIABLES #####
m = 1 # mass constant
k = 5 # spring constant
alpha = .3 # stretch/deformation constant
dt = .01 # change in time
interval = 100 # interval in milliseconds between each animation
##### VARIABLES #####
class Point():
def x():
return self.x
def y():
return self.y
def pos(xy):
self.x=xy[0]
self.y=xy[1]
# initial_pos is a tuple
def __init__(self, initial_pos):
self.initial_position = initial_pos
self._x = initial_pos[0]
self._y = initial_pos[1]
self.x = self._x
self.y = self._y
def evolve(x_map, y_map, l):
return [Point([x_map(el), y_map(el)]) for el in l]
"""
Lagrangian
L = T - V = .5dq^2 - .5kq^2 - .333alpha*q^3
p = mdq; dx = p/m
Hamiltonian
H = p^2/m - L
H = p^2/m - p^2/2m + .5kq^2 + .333alpha*q^3
dp = -partial(H)/partial(q) = -kq - alpha*q^2
dx = partial(H)/partial(p) = p/m
"""
def time_dependent_funcs(name, dt):
### This is the adjustment of p over time. ###
def p_map(point):
p = point.y
q = point.x
try:
dp = -1*k*q-alpha*q**2
ddp = -k*p/m-alpha*q*p/m
return p+dp*dt+ddp*dt**2
except:
return p
### End adjustment of p. ###
### This is the adjustment of q over time. ###
def q_map(point):
q = point.x
p = point.y
try:
dq = p/m
dp = -1*k*q-alpha*q**2
ddp = -k*p/m-alpha*q*p/m
return q+dq*dt+ddp*dt**2/m
except:
return q
### End adjustment of q. ###
if name == "p_map":
return p_map
elif name == "q_map":
return q_map
# Used this post to help create this function: http://stackoverflow.com/questions/14619876/how-do-i-generate-pair-of-random-points-in-a-circle-using-matlab
def circle(r, n):
l = []
for i in range(n):
x=r+1 # necessary to enter loop
y=r+1 # necessary to enter loop
while (x**2 + y**2) > r**2:
x = 2*r*np.random.randn()
y = 2*r*np.random.randn()
l.append(Point([x,y]))
return l
### DOESN'T CURRENTLY WORK
def square(h, n):
l = []
for i in range(n):
x=h+1 # necessary to enter loop
y=h+1 # necessary to enter loop
while x < h and y < h:
x = np.random.randn()
y = np.random.randn()
l.append(Point([x,y]))
return l
def rand(n):
return [Point([np.random.randn(),np.random.randn()]) for i in range(n)]
def x(l):
return [el.x for el in l]
def y(l):
return [el.y for el in l]
#list_of_points = rand(NUM_POINTS) # works
#list_of_points = square(.2, 400) # doesn't currently work
list_of_points = circle(20,NUM_POINTS) # need this to be a global
def init():
global list_of_points, dt
scat = ax.scatter(x(list_of_points), y(list_of_points),color="blue", animated=NO_TRAIL)
if NO_TRAIL:
return scat,
def animate(i):
global list_of_points, dt
map_p = time_dependent_funcs("p_map", dt)
map_q = time_dependent_funcs("q_map", dt)
### evolve the points ###
list_of_points = evolve(map_q, map_p, list_of_points)
scat = ax.scatter(x(list_of_points), y(list_of_points), color="blue",lw=2, animated=NO_TRAIL)
if NO_TRAIL:
return scat,
### Animates the figure fig by executing init_func init (initially) followed by animation function
### animate for 10 frames at an interval of 100ms all the while erasing the last animation (blit=True).
ani = animation.FuncAnimation(fig, animate, init_func=init, frames = 100, interval=interval,blit=NO_TRAIL,save_count=0)
if not AUTOSCALE:
plt.autoscale(enable=False)
plt.show()

Categories