{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f225380f",
   "metadata": {},
   "source": [
    "\n",
    "# Least Square Fitting of Parameters to Data: Notebook Example\n",
    "\n",
    "In this example we will use least squares to fit the parameters of the Arrhenius form of the rate constant to experimental data.\n",
    "\n",
    "The form of the Arrhenius equation is the following:\n",
    "\n",
    "$$ k(T) = A \\exp \\left ( - \\frac{E_a}{RT} \\right )$$\n",
    "\n",
    "where $A$ is the pre-exponential factor, $E_a$ is the activation energy, $R$ is the ideal gas constant, and $T$ is the (absolute) temperature of the measurement (in K).  $k(T)$ has units of reciprocal time for first order reactions and units of reciprocal time * reciprocal concentration for second order reactions.\n",
    "\n",
    "The goal of this notebook is to demostrate how to use Jupyter to obtain least-squares estimates of $A$ and $E_a$.\n",
    "\n",
    "To this end we need to linearize the Arrhenius equation by taking the logarithm of the equation above:\n",
    "$$\\ln\\left ( k(T)\\right ) = \\ln(A) - \\frac{E_a}{RT}$$\n",
    "This equation is analogous to the familiar linear equation:\n",
    "$$y = b + mx$$\n",
    "where \n",
    "$$y = \\ln A$$\n",
    "$$m = \\frac{-E_a}{R}$$\n",
    "$$x = \\frac{1}{T}$$\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "795db611",
   "metadata": {},
   "source": [
    "\n",
    "## Experimental Data\n",
    "\n",
    "We will fit data for the isomerization of bi-cyclo[4.2.0]oct-7-ene into cyclo-octadiene.  This is a first order reaction and the data were otained from the textbook *Physical Organic Chemistry* by H. Maskill (1985).\n",
    "\n",
    "    \n",
    "\n",
    "|Temperature, K| Rate Constant k(T) x 10<sup>4</sup>, s<sup>-1</sup>|\n",
    "|:----:|:----:|\n",
    "|508.7|0.376|\n",
    "|517.1|0.736|\n",
    "|521.5|1.08|\n",
    "|526|1.53|\n",
    "|529|1.93|\n",
    "|532.4|2.44\n",
    "|535.5|3.32|\n",
    "|540.3|4.61|\n",
    "|552.8|10.5|\n",
    "|558.1|16.6|\n",
    "\n",
    "\n",
    "To fit these data to the Arrhenius equation we will need two libraries; ``numpy`` and ``matplotlib``.  These are entered is Python code in the next cell:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "8ba8e9f4",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e8c16808",
   "metadata": {},
   "source": [
    "The next step is to input the data into two arrays:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "8d3367ea",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Data, T in K and k in s^-1\n",
    "\n",
    "T = np.array([508.7, 517.1, 521.5, 526, 529, 532.4, 535.5,\n",
    "              540.3, 551.8, 558.1])\n",
    "kexp = np.array([.376, .763, 1.08, 1.53, 1.93, 2.44, 3.32,\n",
    "                 4.61, 10.5, 16.6])*1e-4\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4087c1fc",
   "metadata": {},
   "source": [
    "Now we need to plot the data.  From the equations above, we see that the relationship between $\\ln k(T)$ and $1/T$ is linear.  This can be confirmed by plotting the data using these instructions:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "1cb80f8e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Arrhenius Plot of ln(k) vs 1/T, Original Data')"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 26720 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "# Plot the data\n",
    "\n",
    "fig, ax = plt.subplots()\n",
    "ax.plot(1/T * 1e3, np.log(kexp), 'o')\n",
    "plt.xlabel('1/T (1/K) x 10^3')\n",
    "plt.ylabel('ln(k • s)')\n",
    "plt.title('Arrhenius Plot of ln(k) vs 1/T, Original Data')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a826bed5",
   "metadata": {},
   "source": [
    "The plot is, in fact, very linear and the fitting will give reliable values of the slope and intercept.  Note that we have kept the units inside the logarithm since these operate on dimensionless quantities.\n",
    "\n",
    "Next we will fit the data to the equation: $y = m x + b$ using the ``np.polyfit`` function, and calculate the **estimated** values of $\\ln(k_\\mathrm{exp})$ as ``y_est``"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "60aa3c41",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "*******************************\n",
      "\n",
      "Fitting Data to a first order kinetic model\n",
      "\n",
      "  y = b + m x\n",
      "\n",
      "\n",
      "  m =  21726 K\n",
      "  b =     33 \n",
      "  A = 1.33e+14 1/s\n",
      " Ea =    181 kJ/mol\n",
      "\n",
      "\n",
      "*******************************\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# fit a linear curve an estimate its y-values and their error.  deg=1 fits data to a linear equation y = b + m x\n",
    "m, b = np.polyfit(1/T, np.log(kexp), deg=1)\n",
    "\n",
    "\n",
    "# Calculate estimated values of y where y_est = ln(k)_est\n",
    "y_est = m * 1/T + b\n",
    "\n",
    "#and write the value of the results:   \n",
    "    \n",
    "print('\\n*******************************\\n')\n",
    "print('Fitting Data to a first order kinetic model\\n')\n",
    "print('  y = b + m x\\n\\n')\n",
    "print('  m = %6.0f K'%(-m))\n",
    "print('  b = %6.0f '%(b))\n",
    "print('  A = %3.2e 1/s'%np.exp(b))\n",
    "print(' Ea = %6.0f kJ/mol\\n\\n'%(-m * 8.314/1000))\n",
    "print('*******************************')\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7797ed49",
   "metadata": {},
   "source": [
    "Now we plot both the experimental data (as points) and the fit of the data to a linear equation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "ed10e678",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x113f32a50>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 44092 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax1 = plt.subplots()\n",
    "ax1.plot(1/T * 1e3, y_est, '-', label='Fitted line')\n",
    "ax1.plot(1/T * 1e3, np.log(kexp), 'o', label='Original data', markersize=10)\n",
    "plt.xlabel('1/T (1/K) * 10^3')\n",
    "plt.ylabel('ln(k • s)')\n",
    "plt.title('Least-Squares Fitting of Arrhenius Plot of ln(k) vs 1/T')\n",
    "plt.legend()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c27b5e6c",
   "metadata": {},
   "source": [
    "And we also plot the residuals, that is:\n",
    "\n",
    "residuals = y(estimated)-y(experiment)\n",
    "\n",
    "to verify that a linear equation is a good model to fit these data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "d428a13f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Residuals y_est-y_exp')"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 26620 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "# Plot the residuals\n",
    "\n",
    "fig, ax2 = plt.subplots()\n",
    "ax2.plot(1/T * 1e3, np.log(kexp)-y_est, 'o')\n",
    "plt.title('Plot of Residuals')\n",
    "plt.xlabel('1/T (1/K) x 10^3')\n",
    "plt.ylabel('Residuals y_est-y_exp')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69e5cfeb",
   "metadata": {},
   "source": [
    "The residuals are all small in magnitude and show no obvious 'trend', that is, the model is a good fit to the data.\n",
    "\n",
    "## End of Notebook Example\n",
    "rfl. emf modified 8/24"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2cae855e-e3ea-4acb-981c-b0b53fb82af7",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
