Python course Wintersemester 2016/17 University of Heidelberg
Revisions: * 15.10.2016: Exercise 16.02 damped oscillation: \(g=\sqrt{k}\) corrected
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from scipy.optimize import curve_fit
from scipy.stats import chi2
15.01
x = np.random.uniform(0., 10., 100)
y = np.polyval([1, 2, -3], x) + np.random.normal(0., 10., 100)
e = np.random.uniform(5, 10, 100)
def poly1 (x,a0,a1):
return a0*x+a1
def poly2 (x,a0,a1,a2):
return a0*x**2+a1*x+a2
xp=np.linspace(0,10,100)
plt.errorbar(x,y,yerr=e,fmt="none")
popt,pcov = curve_fit (poly1,x,y,sigma=e)
plt.plot(xp,poly1(xp,popt[0],popt[1]))
popt,pcov = curve_fit (poly2,x,y,sigma=e)
plt.plot(xp,poly2(xp,*popt))
15.02
def temp_seasonal(x,a0,a1,a2):
return a0*np.cos(2*np.pi*x+a1)+a2
# The following code reads in the file and removes bad values
import numpy as np
date, temperature = np.loadtxt('data/munich_temperatures_average_with_bad_data.txt', unpack=True)
keep = np.abs(temperature) < 90
date = date[keep]
temperature = temperature[keep]
popt,pconv = curve_fit(temp_seasonal,date,temperature)
plt.plot(date,temperature)
plt.plot(date,temp_seasonal(date,*popt),color='red',lw=3)
plt.xlim(2008,2012)
print ("temp=",popt[0],"*cos(2*pi*x+",popt[1],")+",popt[2],")")
The average temperature is 9.0 degrees, the minimum/maximum are -3.3/21.4 degrees.
The meaning of popt[1]:
diff=(4*np.pi-popt[1])
print (365*diff/(2*np.pi))
This means that according to this model the coldest time of year is about 15 days after New Year.
16.01
from scipy.integrate import quad
from scipy.integrate import simps
def gaussian(x,mu,sig):
return (1/(np.sqrt(2*np.pi)*sig))*np.exp(-(x-mu)**2/(2*sig**2))
quad(gaussian,-10,10,args=(0,1))
x=np.linspace(-10,10,100)
y=gaussian(x,0,1)
simps(y,x=x)
16.02
from scipy.integrate import odeint
#critical damping
def diffeq(x, t, k, g):
#define/clear derivative
dxdt = np.zeros(2)
dxdt[0] = x[1]
dxdt[1] = -k*x[0] - 2 * g * x[1]
return dxdt
k=0.1
g=np.sqrt(k)
x = np.array([2.0,-8.2]) # initial position as before
time = np.linspace(0.0,100.0,100) # evaluation times
""" calling the solver """
solution = odeint(diffeq, x, time, args=(k,g))
"""plotting the result"""
plt.plot(time,solution[:,0])
from scipy.integrate import odeint
# forced oscillation
def diffeq(x, t, k, g, a0, om0):
#define/clear derivative
dxdt = np.zeros(2)
dxdt[0] = x[1]
dxdt[1] = -k*x[0] - 2* g*x[1] + a0*np.cos(om0*t)
return dxdt
""" constants """
k=0.1
g=0.025
a0=2.0
om0=0.1
x = np.array([2.0,-0.8]) # initial position as before
time = np.linspace(0.0,300.0,100) # evaluation times
""" calling the solver """
solution = odeint(diffeq, x, time, args=(k,g,a0,om0))
"""plotting the result"""
plt.plot(time,solution[:,0])
t,counts,err=np.loadtxt('data/new_decay_data.txt',unpack=True)
def chisquare(data,sigma,model):
return ((data-model)**2/sigma**2).sum()
plt.errorbar(t,counts,yerr=err)
plt.xlabel('time [d]')
plt.ylabel('counts / sec')
Define a function that calculates the probability to obtain a greater value for chisquare:
""" arguments are: chisquare, number of constraints, number of parameters """
def prob(xsq,n,p):
return 1-chi2.cdf(xsq,n-p)
""" exponential decay """
def decay(x,a,tau):
return a*np.exp(-x/tau)
popt, pcov = curve_fit(decay,t,counts,sigma=err)
xsq=chisquare(counts,err,decay(t,*popt))
print('reduced chisquare={0:5.2f} probability={1:8.6f}\n'.format(
xsq/(len(counts)-len(popt)), prob(xsq,len(t),len(popt))))
reduced chisquare is pretty high! probability < 1e-6
plt.errorbar(t,counts,yerr=err)
plt.plot(t,decay(t,*popt),lw=3,color='red')
plt.xlabel('time [d]')
plt.ylabel('counts / sec')
""" now with background """
def decay_w_background(x,a,tau,bg):
return a*np.exp(-x/tau)+bg
popt, pcov = curve_fit(decay_w_background,t,counts,sigma=err)
xsq=chisquare(counts,err,decay_w_background(t,*popt))
print('reduced chisquare={0:5.2f} probability={1:8.6f}\n'.format(
xsq/(len(counts)-len(popt)), prob(xsq,len(t),len(popt))))
reduced chisquare is about one!
plt.errorbar(t,counts,yerr=err)
plt.plot(t,decay_w_background(t,*popt),lw=3,color='red')
plt.xlabel('time [d]')
plt.ylabel('counts / sec')