I used threading library to plot 2 real-time diagrams using matplotlib.
from fbm import MBM
import matplotlib.pyplot as plt
import threading
plt.style.use('ggplot')
fig, ax = plt.subplots(nrows=2, ncols=1)
def h_90(t):
return 0.9
def h_75(t):
return 0.75
def thread_fgn_9():
x_vec = []
y_vec = []
i = 1
while True:
f = MBM(n=1, hurst=h_90, length=1, method='riemannliouville')
fgn_sample = f.mgn()
x_vec.append(i)
y_vec.append(fgn_sample[0])
i += 1
ax[0].plot(x_vec, y_vec, "g-o")
plt.pause(0.1)
plt.show()
def thread_fgn_75():
x_vec_ = []
y_vec_ = []
i = 1
while True:
f = MBM(n=1, hurst=h_75, length=1, method='riemannliouville')
fgn_sample = f.mgn()
x_vec_.append(i)
y_vec_.append(fgn_sample[0])
i += 1
ax[1].plot(x_vec_, y_vec_, "r-o")
plt.pause(0.2)
plt.show()
if __name__ == "__main__":
plt.ion()
x2 = threading.Thread(target=thread_fgn_75(), name="H_75")
x2.daemon = True
x2.start()
x1 = threading.Thread(target=thread_fgn_9(), name="H_90")
x1.daemon = True
x1.start()
I expect to see to plots being plotted real-time but I see something like below:
can anybody understand what is wrong in my code ?? The code is completed and you can simply just copy/paste in your IDE to run it.
Thanks
================= New change ================
I just changed the main section as below:
if __name__ == "__main__":
x1 = threading.Thread(target=thread_fgn_9(), name="H_90").start()
x2 = threading.Thread(target=thread_fgn_75(), name="H_75").start()
plt.show()
but still the result is the same as before.
======New New change ===============
if __name__ == "__main__":
x1 = threading.Thread(target=thread_fgn_9, name="H_90").start()
x2 = threading.Thread(target=thread_fgn_75, name="H_75").start()
#plt.pause(0.2)
plt.show()
I just erased the parentheses in target=function_name
it seems it is correct but the plot is not showing smoothly. Also I see an error in console like this:
File "/usr/local/lib/python3.9/site-packages/matplotlib/transforms.py", line 312, in xmin
return np.min(self.get_points()[:, 0])
File "<__array_function__ internals>", line 5, in amin
RecursionError: maximum recursion depth exceeded
-------Final Change-----------------------
The best way to do this in matplotlib is below code:
plt.style.use('ggplot')
fig, ax = plt.subplots(nrows=2, ncols=1)
mutex = Lock()
def thread_fgn_9():
print(threading.current_thread().getName())
x_vec = []
y_vec = []
i = 1
while True:
#mutex.acquire()
f = MBM(n=1, hurst=h_90, length=1, method='riemannliouville')
fgn_sample = f.mgn()
x_vec.append(i)
y_vec.append(fgn_sample[0])
i += 1
ax[0].plot(x_vec, y_vec, "g-o")
plt.pause(0.01)
#mutex.release()
def thread_fgn_75():
print(threading.current_thread().getName())
x_vec_ = []
y_vec_ = []
i = 1
while True:
#mutex.acquire()
f = MBM(n=1, hurst=h_75, length=1, method='riemannliouville')
fgn_sample = f.mgn()
x_vec_.append(i)
y_vec_.append(fgn_sample[0])
i += 1
ax[1].plot(x_vec_, y_vec_, "r-o")
plt.pause(0.01)
#mutex.release()
if __name__ == "__main__":
x1 = multiprocessing.Process(target=thread_fgn_9, name="H_90").start()
x2 = multiprocessing.Process(target=thread_fgn_75, name="H_75").start()
plt.show()
I believe the reason is because both processes try to write in one single main plot. In order to have a multiple smooth plot changing over time, we need to take another technique.
thread_fgn_9 is being called and blocking even before it is sent to the thread. Be sure to send the function itself.
plt.pause or plt.show need to be called from the main thread. Additionally, Matplotlib makes no thread safety guarantees in general, so you should avoid this concept entirely unless you know exactly what you are doing. Consider the techniques in this question instead: Fast Live Plotting in Matplotlib / PyPlot
I am trying to animate a plot of two distinct points (blue and green points) moving about the complex unit circle using Python's Matplotlib library. The problem I am having is that the animation does not remove and update the previous data points but rather sequentially smears it on the unit sphere as in the accompanying image. Hence the animation is just a smudging of the various data points as shown in the image. What I am trying to achieve is two distinct points moving about the unit circle as a function of time.
The following is the part of my code where I call 'animation.FuncAnimation' using data in arrays which I call 'A' and 'B'.
##Python Code for Executing Animation##
import matplotlib.animation as animation
import matplotlib.pyplot as plt
import numpy as np
from pylab import *
#Example Data
A = array([0., 0.03435915, 0.06328989, 0.0880305, 0.14199928, 0.2044361, 0.26287941, 0.32484623])
B = array([ 1.75, 1.71564086, 1.69358362, 1.68499179, 1.68255084, 1.67808712, 1.66169597, 1.64407287])
# Total time.
T = 1.0
# Number of steps.
NS = 100
# Time step size
dt = T/NS
t = np.linspace(0.0, NS*dt, NS+1)
# So here are a few utility functions for multiplying scalars and vectors.
# a scalar times a vector returns a vector
def scale_vector(scale, vector):
result = [0]*len(vector)
for i in range(len(result)):
result[i] = scale * vector[i]
return result
# dot product of two vectors = sum(x[0]*y[0] + ... + x[n-1]*y[n-1])
def vector_dot(vector1, vector2):
result = 0
for i in range(len(vector1)):
result += vector1[i] * vector2[i]
return result
# return real part of a vector
def real_vector(vector):
return map(lambda x: x.real, vector)
# return imaginary part of a vector
def imag_vector(vector):
return map(lambda x: x.imag, vector)
## Creating complex unit circle
r = []
im = []
def main():
# Generate numbers around the complex unit circle.
N = 128
theta = scale_vector(2*pi/N, range(N))
exp_theta = map(lambda x: exp(1j * x), theta)
real_part = real_vector(exp_theta)
imag_part = imag_vector(exp_theta)
r.append(real_part)
im.append(imag_part)
# And wait until the user is done with it.
done = raw_input("done? ")
if __name__ == "__main__":
main()
#Form two arrays which have the real and imaginary components of the unit circle
r2 = r[0][:]
im2 = im[0][:]
##Code for Animation##
Aan = np.zeros([len(A),2], float)
for i in range(2):
for j in range(len(A)):
if i == 0:
Aan[j][i] = math.cos(A[j])
elif i == 1:
Aan[j][i] = math.sin(A[j])
Ban = np.zeros([len(B),2], float)
for i in range(2):
for j in range(len(B)):
if i == 0:
Ban[j][i] = math.cos(B[j])
elif i == 1:
Ban[j][i] = math.sin(B[j])
##Plots and animation
fig = figure()
plt.title('Phase Space')
plt.xlabel('Re')
plt.ylabel('Im')
#Plots complex unit circle
plot1 = plt.plot(r2,im2, color = 'g',alpha = 0.4)
#Animation functions
def animate(i):
plot(Aan[i, 0], Aan[i, 1], color='blue', marker= 'o')
plot(Ban[i, 0], Ban[i, 1], color='orange', marker= 'o')
ani = animation.FuncAnimation(fig, animate, interval=101)
show()
Can anyone advise on how this problem could be solved?
Plot creates a new object on the canvas which is not cleared automatically at the next plot.
If you would like to redraw the figure, you can call the cla method and plot the data again.
Or you can update the previously plotted data as it is described in the last example of animation API documentation.
Explanation:
I have two numpy arrays: dataX and dataY, and I am trying to filter each array to reduce the noise. The image shown below shows the actual input data (blue dots) and an example of what I want it to be like(red dots). I do not need the filtered data to be as perfect as in the example but I do want it to be as straight as possible. I have provided sample data in the code.
What I have tried:
Firstly, you can see that the data isn't 'continuous', so I first divided them into individual 'segments' ( 4 of them in this example), and then applied a filter to each 'segment'. Someone suggested that I use a Savitzky-Golay filter. The full, run-able code is below:
import scipy as sc
import scipy.signal
import numpy as np
import matplotlib.pyplot as plt
# Sample Data
ydata = np.array([1,0,1,2,1,2,1,0,1,1,2,2,0,0,1,0,1,0,1,2,7,6,8,6,8,6,6,8,6,6,8,6,6,7,6,5,5,6,6, 10,11,12,13,12,11,10,10,11,10,12,11,10,10,10,10,12,12,10,10,17,16,15,17,16, 17,16,18,19,18,17,16,16,16,16,16,15,16])
xdata = np.array([1,2,3,1,5,4,7,8,6,10,11,12,13,10,12,13,17,16,19,18,21,19,23,21,25,20,26,27,28,26,26,26,29,30,30,29,30,32,33, 1,2,3,1,5,4,7,8,6,10,11,12,13,10,12,13,17,16,19,18,21,19,23,21,25,20,26,27,28,26,26,26,29,30,30,29,30,32])
# Used a diff array to find where there is a big change in Y.
# If there's a big change in Y, then there must be a change of 'segment'.
diffy = np.diff(ydata)
# Create empty numpy arrays to append values into
filteredX = np.array([])
filteredY = np.array([])
# Chose 3 to be the value indicating the change in Y
index = np.where(diffy >3)
# Loop through the array
start = 0
for i in range (0, (index[0].size +1) ):
# Check if last segment is reached
if i == index[0].size:
print xdata[start:]
partSize = xdata[start:].size
# Window length must be an odd integer
if partSize % 2 == 0:
partSize = partSize - 1
filteredDataX = sc.signal.savgol_filter(xdata[start:], partSize, 3)
filteredDataY = sc.signal.savgol_filter(ydata[start:], partSize, 3)
filteredX = np.append(filteredX, filteredDataX)
filteredY = np.append(filteredY, filteredDataY)
else:
print xdata[start:index[0][i]]
partSize = xdata[start:index[0][i]].size
if partSize % 2 == 0:
partSize = partSize - 1
filteredDataX = sc.signal.savgol_filter(xdata[start:index[0][i]], partSize, 3)
filteredDataY = sc.signal.savgol_filter(ydata[start:index[0][i]], partSize, 3)
start = index[0][i]
filteredX = np.append(filteredX, filteredDataX)
filteredY = np.append(filteredY, filteredDataY)
# Plots
plt.plot(xdata,ydata, 'bo', label = 'Input Data')
plt.plot(filteredX, filteredY, 'ro', label = 'Filtered Data')
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Result')
plt.legend()
plt.show()
This is my result:
When each point is connected, the result looks as follows.
I have played around with the order, but it seems like a third order gave the best result.
I have also tried these filters, among a few others:
scipy.signal.medfilt
scipy.ndimage.filters.uniform_filter1d
But so far none of the filters I have tried were close to what I really wanted. What is the best way to filter data such as this? Looking forward to your help.
One way to get something looking close to your ideal would be clustering + linear regression.
Note that you have to provide the number of clusters and I also cheated a bit in scaling up y before clustering.
import numpy as np
from scipy import cluster, stats
ydata = np.array([1,0,1,2,1,2,1,0,1,1,2,2,0,0,1,0,1,0,1,2,7,6,8,6,8,6,6,8,6,6,8,6,6,7,6,5,5,6,6, 10,11,12,13,12,11,10,10,11,10,12,11,10,10,10,10,12,12,10,10,17,16,15,17,16, 17,16,18,19,18,17,16,16,16,16,16,15,16])
xdata = np.array([1,2,3,1,5,4,7,8,6,10,11,12,13,10,12,13,17,16,19,18,21,19,23,21,25,20,26,27,28,26,26,26,29,30,30,29,30,32,33, 1,2,3,1,5,4,7,8,6,10,11,12,13,10,12,13,17,16,19,18,21,19,23,21,25,20,26,27,28,26,26,26,29,30,30,29,30,32])
def split_to_lines(x, y, k):
yo = np.empty_like(y, dtype=float)
# get the cluster centers and the labels for each point
centers, map_ = cluster.vq.kmeans2(np.array((x, y * 2)).T.astype(float), k)
# for each cluster, use the labels to select the points belonging to
# the cluster and do a linear regression
for i in range(k):
slope, interc, *_ = stats.linregress(x[map_==i], y[map_==i])
# use the regression parameters to construct y values on the
# best fit line
yo[map_==i] = x[map_==i] * slope + interc
return yo
import pylab
pylab.plot(xdata, ydata, 'or')
pylab.plot(xdata, split_to_lines(xdata, ydata, 4), 'ob')
pylab.show()
I want to visualise conversion of filters. I would like to plot a scatter plot, where every half second the next filter's values are plotted.
My objectives are:
Plot all values up to point (k) but to have values(k) indicated on the plot.
Pause between plotting values for (k) and (k+1)
Plot at full screen
Have the plot after finishing all iteration
I did a function but it is very inefficient and everything slows down after plotting some values.
The only way I found is to use interactive plot ion() and every step plot all points again with updated marker. For each step (k) I would like to rather remove previous points (k-1) and add them in them with different marker and add current points (k)
import pylab as pl
import time
xPos1 = pl.arange(100)
m1 = [pl.sin(pl.pi*x/10) for x in xPos1]
m2 = [pl.cos(pl.pi*x/30) for x in xPos1]
m3 = [pl.sin(pl.pi*x/20) for x in xPos1]
trueVal1 = [0 for real in xPos1]
def conversionAnim(xPos, trueVal, *args):
mTuple = [arg for arg in args]
colorList = ['Green','Blue','Orchid','Cyan','Goldenrod','Salmon','Orange','Violet','Magenta']
f = pl.figure(figsize =(17,8))
pl.ion()
pl.xlim(min(xPos)-1, max(xPos)+1)
pl.ylim(min(j for i in mTuple for j in i)-.5, max(j for i in mTuple for j in i)+.5)
for i in range(len(xPos)):
print '\ni = %i' % i
for j in range(len(mTuple)):
m = mTuple[j]
mVal = [element for element in m]
print 'Value%i is %s' %(j,mVal[i])
if i == 0:
pl.hold(True)
pl.scatter(xPos[i],mVal[i],s=50, marker = 'o', color = 'Dark'+colorList[j])
pl.plot(xPos[i],trueVal[i])
else:
pl.scatter(xPos[i],mVal[i],s=50, marker = 'o',color = 'Dark'+colorList[j])
pl.scatter(xPos[i-1], mVal[i-1],s=50, marker = 'o', color = 'white')
pl.scatter(xPos[i-1], mVal[i-1],s=50, marker = 'x', color = colorList[j])
pl.plot(xPos[i-1:i+1],trueVal[i-1:i+1], color = 'red')
pl.draw()
time.sleep(.01)
time.sleep(3) # to hold figure after its shown
if __name__ == '__main__':
conversionAnim(xPos1, trueVal1, m1, m2, m3)
I don't know how to get around ion() and make this function efficient.
The simplest way to make this more efficent is to use 2N line plots instead of a huge number of scatter plots. (It looks like you end up with three scatter plot for every data point!)
As a side note, you have several lines ( mTuple = [arg for arg in args]) that turn tuples in to lists. It is clearer to write mTuple = list(args), but I don't think you actually need to do those conversions, as you just need an iterable for everything you do.
import itertools
def covnersion_Anim(xPos,trueVal,*args):
mTuple = args
plt_bulk_lst = []
plt_head_lst = []
color_list = ['Green','Blue','Orchid','Cyan','Goldenrod','Salmon','Orange','Violet','Magenta']
f = plt.figure(figsize =(17,8))
ax = plt.gca()
ax.set_xlim([min(xPos),max(xPos)])
ax.set_ylim([0,1])
ms = 5
for j,c in zip(range(len(mTuple)),itertools.cycle(color_list)):
plt_bulk_lst.append(ax.plot([],[],color=c,ms=ms,marker='x',linestyle='none')[0])
plt_head_lst.append(ax.plot([xPos[0]],[mTuple[j][0]],color='Dark'+c,ms=ms,marker='o',linestyle='none')[0])
real_plt, = plot([],[],color='red')
for j in range(1,len(xPos)):
print j
for hd_plt,blk_plt,m in zip(plt_head_lst,plt_bulk_lst,mTuple):
hd_plt.set_xdata([xPos[j]])
hd_plt.set_ydata([m[j]])
blk_plt.set_ydata(m[:j])
blk_plt.set_xdata(xPos[:j])
real_plt.set_xdata(xPos[:j])
real_plt.set_ydata(trueVal[:j])
plt.pause(1)
return f
covnersion_Anim(range(12),rand(12),rand(12),rand(12),rand(12))