I am trying to calculate one of the basic decay simulation and plot the results as animation. Without animation results fine but when i try to create animation both line appears fully developed at the first time step. The change over time is not as it should be. What am I doing wrong? I'm open to suggestions.
Original plot:
plot
Here the code:
# I135 Xe135 decay.
"""
EQUATIONS:
dIdt = (-Lambda_I * N_I)
dXedt = ((-Lambda_Xe * N_Xe) + (Lambda_I * N_I))
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from scipy.integrate import odeint
def model(z,t):
"""
INITIAL CONDITIONS:
I(0) = 1e8 atoms
Xe(0) = 0 atom
PARAMETERS:
Lambda_I
Lambda_Xe
"""
Lambda_I = (np.log(2) / 6.57)
Lambda_Xe = (np.log(2) / 9.2)
N_I = z[0]
N_Xe = z[1]
dIdt = (-Lambda_I * N_I)
dXedt = ((-Lambda_Xe * N_Xe) + (Lambda_I * N_I))
return [dIdt,dXedt]
z0 = [1e8, 0.0] # initial conditions for N_Xe and N_I
n = 10000
max_time = 100
t = np.linspace(0,max_time,n)
N_I = np.zeros(n)
N_Xe = np.zeros(n)
# Solution
for i in range(n):
z = odeint(model,z0,t)
z0 = z[1]
N_I[i] = z0[0]
N_Xe[i] = z0[1]
# Graph and animation
fig, ax = plt.subplots(figsize=(8,8))
ax.set_ylim(0, 1e8)
ax.set_xlim(0, max_time)
line1, = ax.plot(N_I, 'b-', linewidth=2)
line2, = ax.plot(N_Xe,'g-.', linewidth=2)
plt.rcParams['font.size'] = '14'
plt.minorticks_on()
plt.tick_params(axis="both", which="major", length=12, labelsize=12, width=1, color="black")
plt.tick_params(axis="both", which="minor", length=6, labelsize=10, width=0.8, color="black")
plt.title('I-135 Xe-135 Decay Sim.', fontsize=18)
plt.xlabel('Time (h)', fontsize=16)
plt.ylabel('N', fontsize=16)
plt.legend(['I-135','Xe-135'],prop={'size': 12})
plt.grid(color = 'black', linestyle = '--', linewidth = 0.6)
def animate(j):
line1.set_xdata(np.linspace(0,j,n))
line2.set_xdata(np.linspace(0,j,n))
return [line1,line2,]
ani = animation.FuncAnimation(fig, animate, frames=max_time, blit=True, interval=10, save_count=10)
plt.show()
f = r"C://Users/USER_NAME/Desktop/animation.gif"
writergif = animation.PillowWriter(fps=30)
ani.save(f, writer=writergif)
Related
I have the following code that should draw a cycloid with animation and save it to a gif
but after running the program, a white square appears that covers everything, I can't find the reason cycloid_animation
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.animation import FuncAnimation, PillowWriter
plt.rcParams['animation.html'] = 'html5'
R = 1
def circle(a, b, r):
# (a,b): the center of the circle
# r: the radius of the circle
# T: The number of the segments
T = 100
x, y = [0]*T, [0]*T
for i,theta in enumerate(np.linspace(0,2*np.pi,T)):
x[i] = a + r*np.cos(theta)
y[i] = b + r*np.sin(theta)
return x, y
# Calculate the cycloid line
thetas = np.linspace(0,4*np.pi,100)
cycloid_x = R*(thetas-np.sin(thetas))
cycloid_y = R*(1-np.cos(thetas))
cycloid_c = R*thetas
fig = plt.figure()
lns = []
trans = plt.axes().transAxes
for i in range(len(thetas)):
x,y = circle(cycloid_c[i], R, R)
ln1, = plt.plot(x, y, 'g-', lw=2)
ln2, = plt.plot(cycloid_x[:i+1] ,cycloid_y[:i+1], 'r-', lw=2)
ln3, = plt.plot(cycloid_x[i], cycloid_y[i], 'bo', markersize=4)
ln4, = plt.plot([cycloid_c[i], cycloid_x[i]], [R,cycloid_y[i]], 'y-', lw=2)
tx1 = plt.text(0.05, 0.8, r'$\theta$ = %.2f $\pi$' % (thetas[i]/np.pi), transform=trans)
lns.append([ln1,ln2,ln3,ln4,tx1])
plt.xlim(0,15)
plt.ylim(0,3)
plt.xlabel('x')
plt.ylabel('y')
plt.grid()
plt.axes().set_aspect('equal')
ani = animation.ArtistAnimation(fig, lns, interval=50)
#ani.save('cycloid_ArtistAnimation.mp4',writer='ffmpeg')
ani.save('cycloid_ArtistAnimation.gif',writer='pillow')
ani
Each time you call plt.axis() you are creating a new axis on top of the figure. Since what you want is to get the current axis and then apply the transformations, after creating the figure you should call plt.gca() to get the current axis and use that instead.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.animation import FuncAnimation, PillowWriter
plt.rcParams['animation.html'] = 'html5'
R = 1
def circle(a, b, r):
# (a,b): the center of the circle
# r: the radius of the circle
# T: The number of the segments
T = 100
x, y = [0]*T, [0]*T
for i,theta in enumerate(np.linspace(0,2*np.pi,T)):
x[i] = a + r*np.cos(theta)
y[i] = b + r*np.sin(theta)
return x, y
# Calculate the cycloid line
thetas = np.linspace(0,4*np.pi,100)
cycloid_x = R*(thetas-np.sin(thetas))
cycloid_y = R*(1-np.cos(thetas))
cycloid_c = R*thetas
fig = plt.figure()
lns = []
trans = plt.gca().transAxes #<=== HERE
for i in range(len(thetas)):
x,y = circle(cycloid_c[i], R, R)
ln1, = plt.plot(x, y, 'g-', lw=2)
ln2, = plt.plot(cycloid_x[:i+1] ,cycloid_y[:i+1], 'r-', lw=2)
ln3, = plt.plot(cycloid_x[i], cycloid_y[i], 'bo', markersize=4)
ln4, = plt.plot([cycloid_c[i], cycloid_x[i]], [R,cycloid_y[i]], 'y-', lw=2)
tx1 = plt.text(0.05, 0.8, r'$\theta$ = %.2f $\pi$' % (thetas[i]/np.pi), transform=trans)
lns.append([ln1,ln2,ln3,ln4,tx1])
plt.xlim(0,15)
plt.ylim(0,3)
plt.xlabel('x')
plt.ylabel('y')
plt.grid()
plt.gca().set_aspect('equal') #<=== And HERE
ani = animation.ArtistAnimation(fig, lns, interval=50)
#ani.save('cycloid_ArtistAnimation.mp4',writer='ffmpeg')
ani.save('cycloid_ArtistAnimation.gif',writer='pillow')
I have 3 known positions onto a map using X, Y matplotlib using subplots, I need to plot a bearing from one of the towers and place a line onto the map.
I am currently using X, Y for start position and arrow/line for the end position. But would like to know how to use a bearing in place of the end of the line instead of x, y. I'm currently looking into Vectors but having no luck.
My code is below any help would be great
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import math
df = pd.read_csv("Book1.csv")
df.head()
tower1x = [51.69557]
tower1y = [-3.34197]
tower2x = [51.69673]
tower2y = [-3.34235]
tower3x = [51.69630]
tower3y = [-3.34090]
BBox = (df.longitude.min(), df.longitude.max(),
df.latitude.min(), df.latitude.max())
print (BBox)
ruh_m = plt.imread('map.png')
fig, ax = plt.subplots(figsize = (12,12))
ax.scatter(tower1x, tower1y, zorder=1, alpha= 0.5, c='red', s=50, label="Tower 1")
ax.scatter(tower2x, tower2y, zorder=1, alpha= 0.5, c='blue', s=50, label="Tower 2")
ax.scatter(tower3x, tower3y, zorder=1, alpha= 0.5, c='green', s=50, label="Tower 3")
ax.annotate("",xy=(51.69557,-3.34197), xytext=**(51.69799, -3.34155)**, textcoords='data',
arrowprops=dict(arrowstyle="<-", connectionstyle="arc3"),) # point from tower 1 using X,Y
ax.set_title('Plotting Towers in Aberfan')
ax.set_xlim(BBox[0],BBox[1])
ax.set_ylim(BBox[2],BBox[3])
ax.imshow(ruh_m, zorder=0, extent = BBox, aspect= 'equal')
plt.legend()
plt.show()
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import math
df = pd.read_csv("Grids.csv")
df.head()
##
###X and Y Coordinates using www.openstreetmap.org
BBox = (df.longitude.min(), df.longitude.max(),
df.latitude.min(), df.latitude.max())
#Signal power
s1 = int(input("Enter power from tower 1: "))
s2 = int(input("Enter power from tower 2: "))
s3 = int(input("Enter power from tower 3: "))
#weight of signal
w1 = [s1 / ( s1 + s2 + s3 )]
w2 = [s2 / ( s1 + s2 + s3 )]
w3 = [s3 / ( s1 + s2 + s3 )]
#Tower locations
tower1_lat = np.array ([51.6985630])
tower1_lon = np.array ([-3.3410239])
##
tower2_lat = np.array ([51.6984699])
tower2_lon = np.array ([-3.3400422])
##
tower3_lat = np.array([51.6980743])
tower3_lon = np.array([-3.3406511])
#Your location using the above values
Locaion_Longitude = [tower1_lat * w1 + tower2_lat * w2 + tower3_lat * w3 ]
Locaion_Latitude = [tower1_lon * w1 + tower2_lon * w2 + tower3_lon* w3 ]
print (Locaion_Longitude)
print (Locaion_Latitude)
map_fig = plt.imread('map.png')
fig, ax = plt.subplots(dpi=150,figsize = (12,7))
ax.scatter(tower1_lon, tower1_lat, zorder=1, alpha= 0.5, c='red', s=50, label="Tower 1")
ax.scatter(tower2_lon, tower2_lat, zorder=1, alpha= 0.5, c='blue', s=50, label="Tower 2")
ax.scatter(tower3_lon, tower3_lat, zorder=1, alpha= 0.5, c='green', s=50, label="Tower 3")
ax.scatter(Locaion_Longitude, Locaion_Latitude, zorder=1, c='yellow', s=50, label="Your location")
ax.tick_params (axis='y', which='major', labelsize=5)
ax.tick_params (axis='x', which='major', labelsize=5)#axis settings
ax.set_title('Plotting Towers in Aberfan')
ax.set_xlim(BBox[0],BBox[1])
ax.set_ylim(BBox[2],BBox[3])
ax.imshow(map_fig, zorder=0, extent = BBox, aspect= "auto")
mng = plt.get_current_fig_manager() #full screen
mng.window.state("zoomed")
plt.legend()
plt.show()
enter code here
I am simulating a set of ODEs in Python, but I am getting this error:
x = odeint(model,x0,t,args=(rim,))
File "C:\Python\anaconda3\lib\site-packages\scipy\integrate\odepack.py", line 244, in odeint
int(bool(tfirst)))
ValueError: setting an array element with a sequence.
Here is my code:
import sklearn
import pandas as pd
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
#from gekko import GEKKO
Kg=0.1
Kd=1.1
kg=0.05
kd=0.05
ka=0.0455
Kr=4.5
Kd=1
alpha=0.026
beta=0.00075
n=4
l=4
m0= 2.5
f0= 2.5
p0= 2.5
g0= 2.5
x0 = [m0,f0,p0,g0]
ds = pd.read_csv('dataset.csv')
ds.columns
rim = ds[1:]
def model(x,t,rim):
m,f,p,g = x
m = x[0]
f = x[1]
p = x[2]
g = x[3]
dmdt = ((kg*(f*g))/(Kg+f))-((m*p)/(1+m))+ rim
dfdt = -kg*(f*g)/(Kg+f)+(m*p)/(1+m)-(f*p)/(1+f)
dpdt = (alpha*(f**n)/(Kr**n+f**n)-ka*p**2)
dgdt = beta*(f**l)/(Kd**l+f**l)-kd*(g*p)/(Kd+g)
dxdt = [dmdt, dfdt, dpdt, dgdt]
return dxdt
t = np.linspace(0,90000000,20000000)
x = odeint(model,x0,t,args=(rim,))
m = x[:,0]
f = x[:,1]
p = x[:,2]
g = x[:,3]
plt.figure(figsize=(10,10))
plt.subplot(3,1,1)
plt.plot(t,f, color='blue', lw=3, label='M')
plt.plot(t,m, color='red', lw=3, label='F')
plt.xlabel('Time (s)')
plt.ylabel('F and M')
plt.legend()
plt.xlim(0, 1000)
plt.ylim(0, 20)
plt.subplot(3,1,2)
plt.plot(t,p, color='green', lw=3, label='P')
plt.plot(t,g, color='yellow', lw=3, label='G')
plt.xlabel('Time (s)')
plt.ylabel('P and G')
plt.legend()
plt.xlim(0, 1000)
plt.ylim(0, 2.5)
plt.subplot(3 ,1,3)
plt.plot(f,m, color='blue', lw=3, label='P')
plt.xlabel('F')
plt.ylabel('M')
plt.show()
Can you kindly please help me with solving this error? Thanks in advance!
I need to plot a hist with bot logarithmic y and x-axis, but I'd like also to have hist's bins displayed of same size.
How can I achieve this result with the following code (the x used is very long so I have intentionally avoided to insert it):
import matplotlib as plt
import numpy as np
fig, ax1 = plt.subplots()
hist, bins, _ = ax1.hist(x, log=True, color="red", rwidth=0.5)
plt.xscale("log")
np_x = np.array(x)
print("np_x.mean() = " + str(np_x.mean()))
plt.axvline(np_x.mean() * 1.1, color='lime', linestyle='dashed', linewidth=3,
label='Mean: {:.2f}'.format(np_x.mean()))
handles, labels = ax1.get_legend_handles_labels()
binwidth = math.floor(bins[1] - bins[0])
mylabel = "Binwidth: {}".format(binwidth) + ", Bins: {}".format(len(hist))
red_patch = mpatches.Patch(color='red', label=mylabel)
handles = [red_patch] + handles
labels = [mylabel] + labels
ax1.legend(handles, labels)
plt.xlabel(x_label)
plt.ylabel(y_label)
plt.show()
I want to pick (add) marker to the curve. The marker may change the position many times, however eventually I need to plot only the newest (updated) marker and remove the old.
Any ideas?
import matplotlib.pyplot as plt
import numpy as np
fig, ax1 = plt.subplots()
t = np.arange(0.0, 1.0, 0.01)
s = np.sin(2 * 2 * np.pi * t)for i in range(10):
pt, = ax1.plot(t, s, picker=5)
def onpick(event):
if event.artist != pt:
return True
if not len(event.ind):
return True
ind = event.ind[0]
ax1.plot(t[ind], s[ind], '|r', markersize='20')
fig.canvas.draw()
return True
fig.canvas.mpl_connect('pick_event', onpick)
plt.show()
Instead of calling a new plot() and creating a new artist at every click, simply create an empty artist at initialization stage, and update its coordinates in onpick():
import matplotlib.pyplot as plt
import numpy as np
fig, ax1 = plt.subplots()
t = np.arange(0.0, 1.0, 0.01)
s = np.sin(2 * 2 * np.pi * t)
pt, = ax1.plot(t, s, picker=5)
mark, = ax1.plot([], [], '|r', markersize='20')
def onpick(event):
if event.artist != pt:
return True
if not len(event.ind):
return True
ind = event.ind[0]
mark.set_data(t[ind], s[ind])
fig.canvas.draw()
return True
fig.canvas.mpl_connect('pick_event', onpick)
plt.show()
EDIT: same principle using N curves and N markers
import matplotlib.pyplot as plt
import numpy as np
fig, ax1 = plt.subplots()
t = np.arange(0.0, 1.0, 0.01)
ss = [np.sin(2 * 2 * np.pi * t),
np.cos(3 * 2 * np.pi * t),
np.sin(0.5 * 2 * np.pi * t)]
cs = ['b','r', 'g']
ms = ['|','o','D']
lines = [ax1.plot(t,s,'-',color=c, picker=5)[0] for s,c in zip(ss,cs)]
markers = [ax1.plot([],[],lw=0, marker=m, ms=20, color=c)[0] for m,c in zip(ms,cs)]
def onpick(event):
point_idx = event.ind[0]
art_idx = None
for i,l in enumerate(lines):
if event.artist == l:
art_idx = i
break
if art_idx is not None:
markers[art_idx].set_data(t[point_idx], ss[art_idx][point_idx])
fig.canvas.draw()
return True
fig.canvas.mpl_connect('pick_event', onpick)
plt.show()