Utförd av: L., H.
Datum: 2013-01-11
Handledare: Taha Ahmed
Syftet med laborationen är att ...
[Co(NH3)5H2O]3++NO−2→−H2O[Co(NH3)5NO2]2+→[Co(NH3)5ONO]2+ (mekanism 1)
[Co(NH3)5H2O]3++NO−2→−H2O[Co(NH3)5ONO]2+→[Co(NH3)5NO2]2+ (mekanism 2)
Vi följer ligandutbytet spektrofotometriskt
Där k′1=k1[HNO2][NO−2].
Jämvikt inställer sig mellan de två isomererna. Den observerade hastighetskonstanten är av första ordningen, k2=k++k−.
Bestäm våglängden vid absorptionsmaxima för de tre koboltkomplexen (aqua, nitro, nitrito). Vilken färg har ljus med motsvarande våglängd? Vilken färg har lösningar som absorberar vid respektive våglängd?
Skissa absorbansen, Abs
, vid 510 nm mot tiden, t
, för de två föreslagna reaktionsmekanismerna.
Vilken eller vilka av följande våglängder kan användas för att urskilja mellan de två föreslagna reaktionsmekanismerna?
Antag att mekanism 1 är korrekt. Vilken eller vilka av de ovanstående våglängderna skulle vara bra för att använda för att bestämma hastighetskonstanten för
Går det att använda resonemanget från fråga 4 (ovan) om vi istället antar att mekanism 2 är korrekt? Vilka skillnader kan förutses?
Vilka är de önskvärda reaktionsförhållandena för att ligandutbytesreaktionen ska bli en pseudo-första ordningens reaktion?
Nämn två parametrar som är viktiga att kontrollera under ett kinetikexperiment.
Spektrofotometer (fabrikat, modell), termostat (fabrikat, modell), pH-meter, etc.
Co-lösningar (koncentrationer, och dylikt).
Tillredde reaktionslösningar
Lösning av Co-komplex vatten.
Lösning av NaNO2 i vatten, med tillsats av stark syra.
Startade upp termostaten
Tillverkade lösning för mätning av "slutproduktens" absorbans
Förvärmde lösningarna (temperatur?)
Kalibrerade spektrofotometerns baslinje med avjonat vatten
Kinetikstudier vid 510 nm och 45∘C
Bestämde [HNO2] och [NO−2]
Mätte absorbans för startmaterialet
Mätte absorbans för "slutprodukten"
Vi börjar med att plotta den uppmätta absorbanskurvan. För att kunna göra det behöver vi importera den funktion som vi vill använda för plottning (vi använder matplotlib
). Detta gäller för resten av dokumentet.
import matplotlib.pyplot as plt
# Öka bredden på text-output till 140 kolumner
numpy.set_printoptions(linewidth = 140)
# Gör plottar lite större än annars
figsize(14, 8.75)
Nedan plottar vi vår experimentellt uppmätta absorbanskurva, Abs mot tid i sekunder.
Det är tydligt att isomeriseringsreaktionen följer reaktionsmekanism 2 (Abs ökar först, sjunker sedan).
filnamn = "data-Lindgren-Holm.csv"
# perhaps we could use scipy.loadtxt() instead? More pedagogical if it avoids the "unpack" parameter
# from scipy import loadtxt
# loadtxt("TEK0006.CSV", delimiter=",", usecols=(0,1)) # load cols number 0 and 1
x_data, y_data = numpy.loadtxt(filnamn, delimiter=",", unpack=True)
plt.plot(x_data, y_data)
plt.xlabel("Tid/sekunder")
plt.ylabel("Abs")
plt.title(filnamn)
plt.yscale("linear")
plt.show()
Här har vi vissa saker som förmodligen bör lösas:
Vi importerar två funktioner som vi kommer att använda för kurvanpassningen (curve_fit
) och för annan beräkning (chdtrc
).
# fit with arbitrary function
# från modulen scipy.optimize importerar vi funktionen curve_fit, som optimiserar anpassningen baserat på non-linear least squares
from scipy.optimize import curve_fit
# något obskyr funktion, källa http://docs.scipy.org/doc/scipy/reference/generated/scipy.special.chdtrc.html
from scipy.special import chdtrc
# uncertainties för att enklare utföra beräkningar med osäkerheter
from uncertainties import unumpy
De fyra följande rutorna med kod är viktiga, och bör skrivas för hand av studenten.
# Definiera den kinetiska modellen
def kinetic_model(t, abs0, abs1, abs2, tau1, tau2):
return abs0 + abs1 * exp(-t/tau1) + abs2 * exp(-t/tau2)
# Namngivning i strängen p_names av rent kosmetiska skäl (används senare...)
p_names = ("abs0", "abs1", "abs2", "tau1", "tau2")
# Initialvärden för parametrarna till vår kinetiska modell (gissningar)
p_guess = (2.0E-1, # abs0 = p_guess[0]
-5.0E-2, # abs1 = p_guess[1]
2.0E-1, # abs2 = p_guess[2]
250, # tau1 = p_guess[3]
900) # tau2 = p_guess[4]
# Beräkna absorbansvärden baserat på initialvärdena ovan (för senare jämförelse med anpassade parametrar)
y_initial = kinetic_model(x_data, *p_guess)
# Använd den kinetiska modellen för att anpassa parametrarna
# popt: anpassade parametrar, pcov: deras kovariansmatris (statistik)
popt, pcov = curve_fit(kinetic_model,
x_data,
y_data,
p0 = p_guess,
maxfev = int(1E2))
# maxfev is the maximum number of iterations tried; you
# can try increasing this value if the fit fails.
# Stoppa in de anpassade parametrarna i den kinetiska modellen och beräkna anpassad absorbans-kurva
y_fit = kinetic_model(x_data, *popt)
# Beräkna residualer (skillnad mellan experimentell absorbans och anpassad absorbans-kurva)
y_residual = y_data - y_fit
# Calculate degrees of freedom of fit
DoF = len(x_data) - len(p_guess)
# Calculate Chi-Squared
chisq = sum((y_residual)**2)
Resterande rutor med kod i denna sektion ("Analys av kinetikdata") kan med fördel kopieras och klistras in verbatim, ingen anledning att knappa in rad-för-rad.
plot_exp, = plt.plot(x_data, y_data, "k:", linewidth = 2, label = "Experimental")
plot_init, = plt.plot(x_data, y_initial, "c-", linewidth = 2, label = "Initial fit")
plot_final, = plt.plot(x_data, y_fit, "r--", linewidth = 2, label = "Optimized fit")
# Skapa en legend
legend(loc = 1, ncol = 1)
# Skapa titel och benämning på axlarna
plt.title("Comparing experimental data, initial fit, and optimized fit")
plt.xlabel("Time/seconds")
plt.ylabel("Abs")
plt.show()
# Show residual: difference between data and optimized fit
plt.plot(x_data, y_residual, "r-")
plt.title("Residual")
# Draw horizontal line at 0
plt.axhline(y = 0)
# Label axes
plt.xlabel("Time/seconds")
plt.ylabel("Abs")
plt.show()
print "Antal datapunkter =", len(x_data)
print "Antal parametrar =", len(p_guess)
print "Degrees of freedom =", DoF
Antal datapunkter = 1601 Antal parametrar = 5 Degrees of freedom = 1596
print "Kovariansmatris : \n", pcov, "\n"
Kovariansmatris : [[ 6.10020726e-09 -4.71160660e-08 4.24484128e-08 1.13179885e-04 -2.72915619e-04] [ -4.71160660e-08 4.31034079e-07 -3.98674727e-07 -1.09888474e-03 2.34604279e-03] [ 4.24484128e-08 -3.98674727e-07 3.72520016e-07 1.04321100e-03 -2.15564451e-03] [ 1.13179885e-04 -1.09888474e-03 1.04321100e-03 3.04216653e+00 -5.87442427e+00] [ -2.72915619e-04 2.34604279e-03 -2.15564451e-03 -5.87442427e+00 1.31057966e+01]]
# Göm undan i en funktion?
print "Correlation Matrix :"
for i,row in enumerate(pcov):
for j in range(len(popt)) :
print "%10f"%(pcov[i, j]/sqrt(pcov[i, i]*pcov[j, j])), # note: comma at end of print statement suppresses new line
print # required for proper formatting of matrix
Correlation Matrix : 1.000000 -0.918842 0.890460 0.830817 -0.965216 -0.918842 1.000000 -0.994920 -0.959632 0.987071 0.890460 -0.994920 1.000000 0.979954 -0.975597 0.830817 -0.959632 0.979954 1.000000 -0.930341 -0.965216 0.987071 -0.975597 -0.930341 1.000000
print "Estimated parameters with uncertainties (initial guess in parentheses)"
poptwerr = range(len(popt))
for i in range(len(popt)):
# Here (inside the for-loop) we should build up a unumpy array (arrary with uncertainty values) for each parameter
poptwerr[i] = unumpy.uarray([popt[i], pcov[i,i]**0.5*max(1, sqrt(chisq/DoF))])
print (" %s = %10.5f +/- %10.8f (%9.5f)" %(p_names[i], unumpy.nominal_values(poptwerr[i]), unumpy.std_devs(poptwerr[i]), p_guess[i]))
Estimated parameters with uncertainties (initial guess in parentheses) abs0 = 0.15877 +/- 0.00007810 ( 0.20000) abs1 = -0.10565 +/- 0.00065653 ( -0.05000) abs2 = 0.22035 +/- 0.00061034 ( 0.20000) tau1 = 408.55501 +/- 1.74418076 (250.00000) tau2 = 1358.81341 +/- 3.62019289 (900.00000)
print "Curve fit converged with:"
print " ChiSq = %1.5E" %(chisq)
print " DoF = %4g" %(DoF)
print " ChiSq/DoF = %1.5E" %(chisq/DoF)
print " CDF = %4.2f%%" %(100*chdtrc(DoF,chisq))
Curve fit converged with: ChiSq = 1.29030E-04 DoF = 1596 ChiSq/DoF = 8.08461E-08 CDF = 100.00%
Next step: calculate k and K, preferably without losing uncertainties
Perhaps we should use the uncertainties
package!
k1prim = 1 / poptwerr[3]
k2 = 1 / poptwerr[4]
print "k1prim =", k1prim, "ENHET?"
print "k2 =", k2, "ENHET?"
k1prim = 0.00244765079648+/-1.04493772085e-05 ENHET? k2 = 0.00073593621875+/-1.96070413922e-06 ENHET?
Ta 5 ml av HNO2/NaNO2-lösningen och späd ut det med 5 ml avjonat vatten (så att koncentrationen blir samma som under kinetikmätningen). Mät pH på lösningen.
Från känd koncentration av NaNO2, känt pH och pKa-värde för HNO2 (se SI-data) kan ni sedan räkna ut [HNO2] och [NO−2].
Vi saknar värden för [NaNO2], [HNO2] och [NO−2].
conc_NaNO2 = 0.5 # mol/L
conc_HNO2 = 0.0125 # mol/L
conc_NO2m = 0.5 # mol/L
k1 = k1prim / (conc_HNO2 * conc_NO2m)
print "k1 =", k1 # HÄR BEHÖVS KORREKTA VÄRDEN
print "k2 =", k2
k1 = 0.391624127437+/-0.00167190035336 k2 = 0.00073593621875+/-1.96070413922e-06
# Conc Co is known (each lab group should calculate from weighed mass)
conc_Co = 1 # HÄR BEHÖVS LÄMPLIGT VÄRDE
# Abs / (conc * length)
# Abs read from plot at 510 nm, conc in M, length in dm
epsilon510_ONO = 0.35 / (6.7E-3 * 0.1)
epsilon510_NO2 = 0.15 / (6.7E-3 * 0.1)
Anpassningen ...
Check this out
http://nbviewer.ipython.org/
Could be nice in combination with http://gist.github.com/
(Let students add ipynb file contents to gist.github.com