Code
try:
import fysisk_biokemi
print("Already installed")
except ImportError:
%pip install -q "fysisk_biokemi[colab] @ git+https://github.com/au-mbg/fysisk-biokemi.git"
Load the dataset deter-reacti-orders.xlsx
using the widget below
Run the next cell after uploading the file
Add two new columns with the concentrations given in M.
For each reactant make a plot of
We will be adding more elements to the plot in the following parts of the exercise, therefore we will wrap the code for plotting in a function such that it can be easily reused.
The cell below defines the function for plotting, add the missing code in places with ...
.
Once we’ve written the plotting function we can make the plot as done in the cell below.
Now we want to determine the reaction orders by making fits to the data under the assumption of different integrated rate laws.
In the cell below finish the code to define functions for the integrated rate laws of zeroth, first and second order.
We can then use these to make fits, here it is helpful to define a small function to help us with that.
from scipy.optimize import curve_fit
def make_fit(x_data, y_data, x_eval, A0, order):
# Don't worry about this line for now.
# It just picks the correct function for the given order and sets A0.
func = lambda t, k: rate_laws[order](t, k, A0)
# Make fit
popt, pcov = curve_fit(func, x_data, y_data)
# Evaluate fit
k = popt[0]
y_fit = func(x_eval, k)
return k, y_fit
Next we will define the known constants and extract a few things from the DataFrame
. In the cell below put the initial concentrations in M.
Now we can make and plot the fits
fig, axes = plt.subplots(1, 3, figsize=(8, 4), sharey=True, layout='constrained')
axes[0].set_ylabel('Concentration (M)')
for ax in axes:
plot_dataframe(ax, df)
for ax, order in zip(axes, orders):
k1, y_fit = make_fit(t, A1, t_eval, A1_0, order)
ax.plot(t_eval, y_fit, color='C2', label=rf'k = {k1:.2e}')
k2, y_fit = make_fit(t, A2, t_eval, A2_0, order)
ax.plot(t_eval, y_fit, color='C3', label=rf'k = {k2:.2e}')
ax.legend()
ax.set_title(f'Reaction order: {order}')
Based on this plot;
The cell above used a for
-loop. These are a powerful way of performing the same operation with different inputs, you will learn more about them later on.
By inspecting the plot we can make a qualitative judgement of the reaction orders. To get a more quantitative results we can look at the residuals, recall they are defined as
\[ r_i = y_i - f(x_i | \theta) \]
We can calculate these in much the same way we calculate the fits, except we don’t evaluate the fit at a new set of points but at the observations \(x_i\).
def calculate_residuals(x_data, y_data, A0, order):
# Don't worry about this line for now.
# It just picks the correct function for the given order and sets A0.
func = lambda t, k: rate_laws[order](t, k, A0)
# Make fit
popt, pcov = curve_fit(func, x_data, y_data)
# Evaluate fit
k = popt[0]
y_fit = ... # Calculate the fit at the x_data using `func`
residuals = ... # Calculate the residuals.
return residuals
We can then plot the residuals, here using a histogram where the x-axis is the value of the residual and the bars indicate the number of residuals within that range of values.
fig, axes = plt.subplots(2, 3, figsize=(8, 4), sharey=True, layout='constrained', sharex=True)
axes[0, 0].set_ylabel('Count')
axes[1, 0].set_ylabel('Count')
for ax_col, order in zip(axes.T, orders):
residuals = calculate_residuals(t, A1, A1_0, order)
ax_col[0].hist(residuals, alpha=0.75, color='C0')
residuals = calculate_residuals(t, A2, A2_0, order)
ax_col[1].hist(residuals, alpha=0.75, color='C1')
ax_col[1].set_xlabel('Residual')
Does this support your conclusions about the reaction order from (d)?
Consider the following reaction
\[ A \underset{k_{2}}{\stackrel{k_1}{\rightleftharpoons}} B \]
The magnitudes of the rate constants are \(k_1 = 10 \ \mathrm{s}^{-1}\) and \(k_2 = 1 \ \mathrm{s}^{-1}\).
What is the reaction order in each direction?
Show mathematically how the equilibrium constant \(K_{\mathrm{eq}}\) is given by the ratio between the two rate constants.
Calculate the concentrations of A and B at equilibrium, \([\mathrm{A}]_{\mathrm{eq}}\) and \([\mathrm{B}]_\mathrm{eq}\), if \([\mathrm{A}]_0 = 10^{-3} \text{M}\)
Calculate the forward and reverse rates at equilibrium at this concentration.
If \([\mathrm{A}]_0 = 10^{-3} \text{M}\) and \([\mathrm{B}]_0 = 0 \text{M}\), calculate the initial rate of formation of B.
We now want to calculate and plot the time-dependent concentrations using the above equations.
In the cell below finish the implementation of the function A_time
that calculates the concentration [A] as a function of time.
Be careful to correctly set parantheses when implementing this function!
And then we can use that function to calculate and plot the concentrations as a function of time.
fig, ax = plt.subplots()
t_max = ... # Set the time in seconds
t = np.linspace(0, t_max, 100)
At = ... # Use your function to calculate [A](t)
Bt = ... # Calculate [B](t)
ax.plot(t, At, label='[A](t)')
ax.plot(t, Bt, label='[B](t)')
ax.set_ylabel('Concentrations (M)')
ax.set_xlabel('Time (s)')
ax.legend()
The irreversible isomerization of compound A to compound B results in a decreasing absorbance. The isomerization was followed in a time course at two different temperatures (T1 = 25 °C and T2 = 40 °C). The absorbance (\(\epsilon\) = 16700 \(\mathrm{cm}^{-1} \mathrm{M}^{-1}\)) was used to calculate the concentration of compound A in a spectrophotometer with a pathlength of 1 cm. The obtained dataset is given in the file deter-reacti-order-activ.csv
.
What are the two temperatures in Kelvin? Set them as varilabes in the cell below.
Load the dataset using the widget below
Run the next cell after uploading the file
Calculate the concentration of A at each timepoint in SI units, by adding new columns to the DataFrame
.
We will be resuing the plot, so we will put the code for it in a function.
You can run this next cell to see your plot and adjust as neccesarry.
In the exercise on “Determination of reaction orders” we saw how we can fit to the expressions for the integrated rate laws to determine the reaction order.
In that exercise we wrote the functions in the next two cells, we will reuse them here
from scipy.optimize import curve_fit
def make_fit(x_data, y_data, x_eval, A0, order):
func = lambda t, k: rate_laws[order](t, k, A0)
popt, pcov = curve_fit(func, x_data, y_data)
# Evaluate fit at new points
k = popt[0]
y_fit_new = func(x_eval, k)
# Evaluate fit at data-points to calculate residuals
y_fit_data = func(x_data, k)
residuals = y_data - y_fit_data
return k, y_fit_new, residuals
Now we need to set a few things before we can do the fitting
You’ve already calculated the initial concentration, it is contained in the DataFrame
.
Now we can use our plotting and fitting functions to analyze the data
fig, axes = plt.subplots(2, 3, figsize=(8, 6), sharey='row', layout='constrained')
for ax in axes.T:
plot_dataframe(ax[1], df)
orders = [0, 1, 2]
t_eval = np.linspace(0, t.max()*1.05)
for ax_col, order in zip(axes.T, orders):
# Calculate the fits
k25, y_fit_25, residuals_25 = make_fit(t, A_25, t_eval, A0_25, order)
k40, y_fit_40, residuals_40 = make_fit(t, A_40, t_eval, A0_40, order)
# Plot the fits
ax = ax_col[1]
ax.plot(t_eval, y_fit_25, color='k')
ax.plot(t_eval, y_fit_40, color='k')
ax.text(0.05, 0.15, f'k (25 C) = {k25:.4f}', transform=ax.transAxes)
ax.text(0.05, 0.05, f'k (40 C) = {k40:.4f}', transform=ax.transAxes)
ax.legend()
# Plot the residuals
ax = ax_col[0]
ax.hist(residuals_25, facecolor='C0', alpha=0.75, edgecolor='k', label='25 C')
ax.hist(residuals_40, facecolor='C1', alpha=0.75, edgecolor='k', label='40 C')
ax.set_xlabel('Residual')
ax.set_ylabel('Count')
ax.legend()
ax.set_title(f'Reaction order: {order}')
Based on these plots
What is the half-life of the reaction at these temperatures and is it constant through-out the reaction?
With the assumption that the Arrhenius constant A and the activation energy are temperature independent in the interval measured, use the Arrhenius equation to calculate the activation energy of the isomerization of the compound A.
Perform the calculation in the cell below.
Assume that a compound R can react with the unprotonated form of Histidine, \(\text{His}\), to form a covalent reaction product, \(\text{P}\): \[ \text{His} + \text{R} \rightarrow \text{P} \]
The protonated form of Histidine, \(\text{HisH}^+\), is in equilibrium with \(\text{His}\):
\[ \text{HisH}^+ \rightleftharpoons \text{His} + \text{H}^+ \]
The pKa value for this acid-base equilibrium is 6.0. Further assume that the total concentration of Histidine, is
\[ [\text{HisH}^+] + [\text{His}] = 10^{-3} \ \text{M} \]
Using the Henderson-Hasselbach equation, calculate the percentage of unprotonated Histidine, \(\text{His}\), at pH 6.0.
Calculate \([\text{His}]\) at pH 6
The reaction equation for the reaction between \(\text{His}\) and \(\text{R}\) is
\[ v = - \frac{d[\text{His}]}{dt} = k \cdot [\text{His}] \cdot [\text{R}] \]
What’s the reaction order?
If \([\text{R}]\) is much higher than \([\text{His}]\), what can then be concluded regarding the order of the reaction?
Show how a new rate constant, \(k'\), can be defined in these conditions. How does \(k'\) depend on \(\text{R}\)?
At pH 6.0 the reaction rate \(v = 1 \ \text{mM}\cdot \text{s}^{-1}\) and constant \([\text{R}] = 0.2 \ \text{M}\)
Convert the reaction rate to SI-units given in \(\text{M}\cdot \text{s}^{-1}\).
Use the concentration of \([\text{His}]\) at pH 6 calculated in question (b) and calculate the rate constant k.
In the Excel document tø12_week49_data you will find a data set in which an enzyme catalyzed formation of product P, with varying start concentration of substrates, [S], was followed over time. The product absorbs light at a specific wavelength with an extinction coefficient of 0.068 \(\mu\text{M}^{-1}\cdot \text{cm}^{-1}\), and the absorbance was measured in a light path of 1 cm throughout the time course.
You can load the dataset using the cells below;
Run the next cell after uploading the file
The headers, like Abs_S1
refer to the substrate concentration so S1
means a substrate concentration of 1 \(\mu\text{M}\).
Convert the extinction coefficient to units given in \(\text{M}^{-1}\cdot \text{cm}^{-1}\) and assign it to a variable. Also assign the light path length to a variable.
Using Lambert-Beers law, calculate the concentration of product, [P], in M for each time series.
Loops are one of the most useful parts of programming, loops allows us to repeat an operation on many different elements. This allows us to not have to repeat code many times, making it simpler to understand and less prone to error - and at the same time more flexible.
A common type of loop in Python is the for
loop, which does something for
every item it is told to consider. The syntax of a for
-loop is like so:
Which will print
I have 1 apples
I have 2 apples
I have 3 apples
I have 4 apples
I have 5 apples
So the for
-loop did the operation of printing a string for each value of count
.
When working with a DataFrame
like in this exercise, we may for example want to do something for
each column, one way of doing that is to loop over the column names, say we want we have a DataFrame
df
with columns named "col1", "col2", "col3"
we can loop over that as
The cell below setups a loop calculate the concentrations for each of these current columns in the dataframe.
substrate_concentrations = [1, 3, 5, 7, 9, 11, 13, 15]
for s in substrate_concentrations:
abs_col_name = f'Abs_S{s}' # This creates a string where the value of 's' is put instead of "{s}"".
conc_col_name = f'C_S{s}' # Same type string creation
df[conc_col_name] = ... # Your code here
# We can print in each iteration of the loop to see what's going on.
print(s, abs_col_name, conc_col_name)
And we can check that the columns we expect have been added to the DataFrame
.
Plot [P] as a function of time for all experiments in one single graph.
Here it is again very useful to use a for
-loop
How could you use Excel to determine \(V_0\) for each concentration of \(S\)? Create a table of \(V_0\) vs \([S]\)
Why is it important to use \(V_0\) rather than \(V\) at a later time point when creating the Michaelis-Menten plot?
Plot \(V_0\) against substrate concentration and estimate \(k_{cat}\) and \(K_M\) visually (remember units)
The kinetics for an enzyme were investigated using the absorbance of the product to calculate the initial velocities for a range of different initial concentrations of the substrate. The data given in the dataset analys-data-set-obeyin.xlsx
was obtained. Use these data to answer the following questions.
Run the next cell after uploading the file
Convert the concentrations of substrate and the velocities to the SI units \(\text{M}\) and \(\text{M}\cdot\text{s}^{-1}\), respectively.
Plot the initial velocities, \(V_0\), as a function of substrate concentrations, \([S]\). Estimate \(K_M\) and \(V_\mathrm{max}\) from this plot.
Now we want to fit using the Michaelis-Menten equation, as per usual when the task is fitting we have to define the function we are fitting with
This is one of those places were parentheses are crucial.
And then we can follow our usual procedure to make the fit
How do these values compare to your estimate?
The \(k_{cat}\) of the enzyme was determined to be \(20000 \ \text{s}^{-1}\). Calculate, in the cell below, the concentration of the enzyme used in the assay.
---
title: Week 47
engine: jupyter
categories: ['regression', 'calculation', 'data', 'plotting']
format-links:
- text: "Open in Google Colab"
href: "https://colab.research.google.com/github/au-mbg/fysisk-biokemi/blob/built-notebooks/built_notebooks/student/week_47.ipynb"
icon: box-arrow-up-right
---
{{< include tidbits/_install_import.qmd >}}
---
{{< include exercises/deter-reacti-orders.qmd >}}
---
{{< include exercises/analys-rever-reacti.qmd >}}
---
{{< include exercises/deter-reacti-order-activ.qmd >}}
---
{{< include exercises/the-ph-effect-active.qmd >}}
---
{{< include exercises/design-enzyme-kineti-exper.qmd >}}
---
{{< include exercises/analys-data-set-obeyin.qmd >}}