{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "34a7a981-1718-4dcb-af8c-981e0fa84023",
   "metadata": {},
   "source": [
    "## Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "390c33fa-ab42-4d69-ac06-604beb2c69db",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import scipy.optimize\n",
    "from impedance.models.circuits import CustomCircuit\n",
    "\n",
    "from scipy.signal import medfilt as medfilt\n",
    "\n",
    "# from impedance.visualization import plot_nyquist # Kept if you want to switch plotting methods"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a055f3f-6b2e-4fa8-8395-acebacade488",
   "metadata": {},
   "source": [
    "## Data Loading"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "9154f27a-5a02-4156-8105-b384205d6416",
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- Data Loading ---\n",
    "\n",
    "def lpr_cor_import(filename):\n",
    "    \"\"\" Import cor file as pandas dataframe.\"\"\"\n",
    "\n",
    "    try: \n",
    "        df = pd.read_csv(\n",
    "            filename,\n",
    "            skiprows=26,\n",
    "            sep='\\s+',\n",
    "            header=None,\n",
    "            names=[\"E\", \"i\", \"T\"],\n",
    "        ) #index_col=\"Freq\")\n",
    "    except FileNotFoundError as e:\n",
    "        print(f\"Error: File was not found.\")\n",
    "        print(e.message)\n",
    "        print(e.args)\n",
    "        return None\n",
    "    except Exception as e:\n",
    "        print(f\"Error reading the CSV file: {e}\")\n",
    "        return None   \n",
    "    else:\n",
    "        return df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "4d796ec7-48d9-4a23-bd98-c607067d330d",
   "metadata": {},
   "outputs": [],
   "source": [
    "HS1_1 = lpr_cor_import(\"HIPed_Stellite1_LPR/LPR_1.cor\")\n",
    "HS1_2 = lpr_cor_import(\"HIPed_Stellite1_LPR/LPR_2.cor\")\n",
    "HS1_3 = lpr_cor_import(\"HIPed_Stellite1_LPR/LPR_3.cor\")\n",
    "HS1_4 = lpr_cor_import(\"HIPed_Stellite1_LPR/LPR_4.cor\")\n",
    "HS1_5 = lpr_cor_import(\"HIPed_Stellite1_LPR/LPR_5.cor\")\n",
    "HS1_6 = lpr_cor_import(\"HIPed_Stellite1_LPR/LPR_6.cor\")\n",
    "\n",
    "\n",
    "# Keep it in the same cell to keep df reproducible, even if Vi clicks it multiple times\n",
    "area = 2 #cm^2\n",
    "kernel_size = 5\n",
    "\n",
    "for df in [HS1_1, HS1_2, HS1_3, HS1_4, HS1_5, HS1_6]:\n",
    "    df[\"i\"] = np.abs(df[\"i\"]/area) # Current density\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "26ab42ec-9576-4335-a38b-49762228f823",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>E</th>\n",
       "      <th>i</th>\n",
       "      <th>T</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>-0.206795</td>\n",
       "      <td>7.859750e-11</td>\n",
       "      <td>0.1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>-0.206805</td>\n",
       "      <td>5.445100e-11</td>\n",
       "      <td>0.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>-0.206809</td>\n",
       "      <td>6.106750e-11</td>\n",
       "      <td>0.3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>-0.206795</td>\n",
       "      <td>5.972600e-11</td>\n",
       "      <td>0.4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>-0.206780</td>\n",
       "      <td>5.621750e-11</td>\n",
       "      <td>0.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3999</th>\n",
       "      <td>-0.166870</td>\n",
       "      <td>7.752900e-11</td>\n",
       "      <td>400.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4000</th>\n",
       "      <td>-0.166854</td>\n",
       "      <td>7.931000e-11</td>\n",
       "      <td>400.1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4001</th>\n",
       "      <td>-0.166857</td>\n",
       "      <td>7.781400e-11</td>\n",
       "      <td>400.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4002</th>\n",
       "      <td>-0.166850</td>\n",
       "      <td>7.296700e-11</td>\n",
       "      <td>400.3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4003</th>\n",
       "      <td>-0.166846</td>\n",
       "      <td>6.987300e-11</td>\n",
       "      <td>400.4</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>4004 rows × 3 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "             E             i      T\n",
       "0    -0.206795  7.859750e-11    0.1\n",
       "1    -0.206805  5.445100e-11    0.2\n",
       "2    -0.206809  6.106750e-11    0.3\n",
       "3    -0.206795  5.972600e-11    0.4\n",
       "4    -0.206780  5.621750e-11    0.5\n",
       "...        ...           ...    ...\n",
       "3999 -0.166870  7.752900e-11  400.0\n",
       "4000 -0.166854  7.931000e-11  400.1\n",
       "4001 -0.166857  7.781400e-11  400.2\n",
       "4002 -0.166850  7.296700e-11  400.3\n",
       "4003 -0.166846  6.987300e-11  400.4\n",
       "\n",
       "[4004 rows x 3 columns]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "HS1_1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "4d717162-2cbf-4d0b-acf5-d7b2528539c7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 46520 characters]",
      "text/plain": [
       "<Figure size 600x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(figsize=(4,4), sharex=True, dpi=150)\n",
    "kernel_size = 49\n",
    "\n",
    "# Step 1\n",
    "# Filter the data a lil bit with a median filter, and find the lowest current, and then find the corresponding voltage\n",
    "Ecorr_guess = HS1_1['E'].iloc[ np.argmin(medfilt(HS1_1['i'], kernel_size=kernel_size)) ]\n",
    "ax.axhline(y=Ecorr_guess, color='green', linestyle='--', linewidth=2, alpha=0.5)\n",
    "\n",
    "\n",
    "# Step 2\n",
    "# Select data for anodic and cathodic Tafel regions\n",
    "anodic_df =  HS1_1[HS1_1['E'] > Ecorr_guess] \n",
    "cathodic_df =  HS1_1[HS1_1['E'] < Ecorr_guess] \n",
    "\n",
    "\n",
    "ax.semilogx(\n",
    "    np.abs(anodic_df[\"i\"].to_numpy()),\n",
    "    anodic_df[\"E\"].to_numpy(), \n",
    "    markersize=5, label=\"HS1 1 Anodic\")\n",
    "\n",
    "ax.semilogx(\n",
    "    np.abs(cathodic_df[\"i\"].to_numpy()),\n",
    "    cathodic_df[\"E\"].to_numpy(), \n",
    "    markersize=5, label=\"HS1 1 Cathodic\")\n",
    "\n",
    "\n",
    "ax.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "87f8f180-e850-4154-aeab-c2e6fc8d78bc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 53632 characters]",
      "text/plain": [
       "<Figure size 600x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import warnings\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(4,4), sharex=True, dpi=150)\n",
    "kernel_size = 49\n",
    "\n",
    "# Step 1\n",
    "# Filter the data a lil bit with a median filter, and find the lowest current, and then find the corresponding voltage\n",
    "Ecorr_guess = HS1_1['E'].iloc[ np.argmin(medfilt(HS1_1['i'], kernel_size=kernel_size)) ]\n",
    "ax.axhline(y=Ecorr_guess, color='green', linestyle='--', linewidth=2, alpha=0.5)\n",
    "\n",
    "\n",
    "# Step 2\n",
    "# Select data for anodic and cathodic Tafel regions\n",
    "anodic_df =  HS1_1[HS1_1['E'] > Ecorr_guess] \n",
    "cathodic_df =  HS1_1[HS1_1['E'] < Ecorr_guess] \n",
    "\n",
    "if anodic_df.empty or cathodic_df.empty:\n",
    "    warnings.warn(\"Warning: Not enough data for linear Tafel fit.\")\n",
    "    warnings.warn(\"Your E_corr guess is probably wrong.\")\n",
    "        \n",
    "# Step 3\n",
    "# Median filter the hell out of the data, cos it isn't going to change the magnitude of the data :D\n",
    "kernel_size = 299\n",
    "medfilt_anodic_df_i = medfilt(anodic_df[\"i\"], kernel_size=kernel_size)\n",
    "medfilt_cathodic_df_i = medfilt(cathodic_df[\"i\"], kernel_size=kernel_size)\n",
    "\n",
    "ax.semilogx(\n",
    "    medfilt_anodic_df_i,\n",
    "    #np.abs(anodic_df[\"i\"].to_numpy()),\n",
    "    anodic_df[\"E\"].to_numpy(), \n",
    "    markersize=5, label=\"HS1 1 Anodic\")\n",
    "\n",
    "ax.semilogx(\n",
    "    medfilt_cathodic_df_i,\n",
    "    #np.abs(cathodic_df[\"i\"].to_numpy()),\n",
    "    cathodic_df[\"E\"].to_numpy(), \n",
    "    markersize=5, label=\"HS1 1 Cathodic\")\n",
    "\n",
    "ax.semilogx(\n",
    "    np.abs(HS1_1['i'].to_numpy()),\n",
    "    HS1_1[\"E\"].to_numpy(), \n",
    "    markersize=5, label=\"HS1 1\", alpha=0.5)\n",
    "\n",
    "ax.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "86ed1f2e-7df6-49a3-b8fb-77401c877cdc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 127576 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import warnings\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from scipy.signal import medfilt\n",
    "\n",
    "# --- 1. Initial Setup ---\n",
    "fig, ax = plt.subplots(figsize=(8, 4), dpi=150)\n",
    "\n",
    "# --- 2. Data Preparation ---\n",
    "# Apply a median filter to smooth the current data.\n",
    "KERNEL_SIZE_INITIAL = 49\n",
    "filtered_current = medfilt(HS1_1['i'], kernel_size=KERNEL_SIZE_INITIAL)\n",
    "\n",
    "# Estimate corrosion potential (Ecorr) at the minimum smoothed current.\n",
    "ecorr_guess_index = np.argmin(filtered_current)\n",
    "ecorr_guess = HS1_1['E'].iloc[ecorr_guess_index]\n",
    "\n",
    "# Split data into anodic and cathodic regions based on Ecorr.\n",
    "anodic_df = HS1_1[HS1_1['E'] > ecorr_guess]\n",
    "cathodic_df = HS1_1[HS1_1['E'] < ecorr_guess]\n",
    "\n",
    "if anodic_df.empty or cathodic_df.empty:\n",
    "    warnings.warn(\"Insufficient data for Tafel fit. Ecorr guess may be incorrect.\")\n",
    "\n",
    "# --- 3. Advanced Filtering and Curve Fitting ---\n",
    "# Apply a stronger median filter for cleaner fitting.\n",
    "KERNEL_SIZE_FIT = 299\n",
    "medfilt_anodic_i = medfilt(anodic_df[\"i\"], kernel_size=KERNEL_SIZE_FIT)\n",
    "medfilt_cathodic_i = medfilt(cathodic_df[\"i\"], kernel_size=KERNEL_SIZE_FIT)\n",
    "\n",
    "# Perform linear fit on E vs. current (for semilog plot).\n",
    "p_anodic = np.poly1d(np.polyfit(medfilt_anodic_i, anodic_df[\"E\"], 1))\n",
    "p_cathodic = np.poly1d(np.polyfit(medfilt_cathodic_i, cathodic_df[\"E\"], 1))\n",
    "\n",
    "# --- 4. Plotting ---\n",
    "# Plot filtered experimental data.\n",
    "ax.semilogx(medfilt_anodic_i, anodic_df[\"E\"], 'o', markersize=1, label=\"Anodic Data\")\n",
    "ax.semilogx(medfilt_cathodic_i, cathodic_df[\"E\"], 'o', markersize=1, label=\"Cathodic Data\")\n",
    "\n",
    "# Plot Ecorr and Tafel fit lines.\n",
    "ax.axhline(y=ecorr_guess, color='green', linestyle='--', linewidth=2, alpha=0.5, label='$E_{corr}$')\n",
    "i_anodic_fit = np.linspace(medfilt_anodic_i.min(), medfilt_anodic_i.max(), 100)\n",
    "#ax.plot(i_anodic_fit, p_anodic(i_anodic_fit), 'r--', label='Anodic Fit')\n",
    "i_cathodic_fit = np.linspace(medfilt_cathodic_i.min(), medfilt_cathodic_i.max(), 100)\n",
    "#ax.plot(i_cathodic_fit, p_cathodic(i_cathodic_fit), 'b--', label='Cathodic Fit')\n",
    "\n",
    "# --- 5. Tangent Line Calculation and Plotting ---\n",
    "# Anodic Tangent\n",
    "i_extreme_anodic = medfilt_anodic_i.max()\n",
    "E_extreme_anodic = p_anodic(i_extreme_anodic)\n",
    "tangent_slope_anodic = p_anodic.coeffs[0] * (i_extreme_anodic * np.log(10))\n",
    "log_i_extreme_anodic = np.log10(i_extreme_anodic)\n",
    "log_i_tangent_anodic = np.linspace(log_i_extreme_anodic - 0.5, log_i_extreme_anodic, 100)\n",
    "E_tangent_anodic = tangent_slope_anodic * (log_i_tangent_anodic - log_i_extreme_anodic) + E_extreme_anodic\n",
    "ax.plot(10**log_i_tangent_anodic, E_tangent_anodic, 'm', linestyle='-.', linewidth=2, label='Anodic Tangent')\n",
    "\n",
    "# Cathodic Tangent\n",
    "i_extreme_cathodic = medfilt_cathodic_i.max()\n",
    "E_extreme_cathodic = p_cathodic(i_extreme_cathodic)\n",
    "tangent_slope_cathodic = p_cathodic.coeffs[0] * (i_extreme_cathodic * np.log(10))\n",
    "log_i_extreme_cathodic = np.log10(i_extreme_cathodic)\n",
    "log_i_tangent_cathodic = np.linspace(log_i_extreme_cathodic - 0.5, log_i_extreme_cathodic, 100)\n",
    "E_tangent_cathodic = tangent_slope_cathodic * (log_i_tangent_cathodic - log_i_extreme_cathodic) + E_extreme_cathodic\n",
    "ax.plot(10**log_i_tangent_cathodic, E_tangent_cathodic, 'c', linestyle='-.', linewidth=2, label='Cathodic Tangent')\n",
    "\n",
    "# --- 6. Final Configuration ---\n",
    "# Configure plot aesthetics.\n",
    "ax.set_xlabel(\"Current (A)\")\n",
    "ax.set_ylabel(\"Potential (V)\")\n",
    "ax.set_title(\"Tafel Plot for HS1_1\")\n",
    "ax.legend()\n",
    "ax.grid(True, which=\"both\", ls=\"--\", linewidth=0.5)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "a5159c47-93d9-4993-a073-f7b80cd4a81e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 2.42916762e+08 -1.84040974e-01]\n",
      "[-4.99294175e+08 -1.82337841e-01]\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 125788 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import warnings\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from scipy.signal import medfilt\n",
    "\n",
    "def analyze_tafel_data(df):\n",
    "\n",
    "    INITIAL_KERNEL=49\n",
    "    FIT_KERNEL=299\n",
    "    \n",
    "    # 1. Estimate Corrosion Potential (Ecorr)\n",
    "    filtered_current = medfilt(df['i'], kernel_size=INITIAL_KERNEL)\n",
    "    ecorr_guess_index = np.argmin(filtered_current)\n",
    "    ecorr_guess = df['E'].iloc[ecorr_guess_index]\n",
    "\n",
    "    # 2. Split data into anodic and cathodic regions\n",
    "    anodic_df = df[df['E'] > ecorr_guess]\n",
    "    cathodic_df = df[df['E'] < ecorr_guess]\n",
    "\n",
    "    if anodic_df.empty or cathodic_df.empty:\n",
    "        warnings.warn(\"Insufficient data for Tafel fit. Ecorr guess may be incorrect.\")\n",
    "        return None\n",
    "\n",
    "    # 3. Apply a stronger filter for cleaner fitting\n",
    "    medfilt_anodic_i = medfilt(anodic_df['i'], kernel_size=FIT_KERNEL)\n",
    "    medfilt_cathodic_i = medfilt(cathodic_df['i'], kernel_size=FIT_KERNEL)\n",
    "\n",
    "    # 4. Perform linear fit and generate points for the fit line\n",
    "    coeff_anodic = np.polyfit(medfilt_anodic_i, anodic_df['E'], 1)    \n",
    "    p_anodic = np.poly1d(np.polyfit(medfilt_anodic_i, anodic_df['E'], 1))\n",
    "    i_anodic_fit = np.linspace(medfilt_anodic_i.min(), medfilt_anodic_i.max(), 100)\n",
    "    E_anodic_fit = p_anodic(i_anodic_fit)\n",
    "\n",
    "    coeff_cathodic = np.polyfit(medfilt_cathodic_i, cathodic_df['E'], 1)\n",
    "    p_cathodic = np.poly1d(np.polyfit(medfilt_cathodic_i, cathodic_df['E'], 1))\n",
    "    i_cathodic_fit = np.linspace(medfilt_cathodic_i.min(), medfilt_cathodic_i.max(), 100)\n",
    "    E_cathodic_fit = p_cathodic(i_cathodic_fit)\n",
    "\n",
    "    # 5. Calculate tangent lines\n",
    "    i_extreme_anodic = medfilt_anodic_i.max()\n",
    "    E_extreme_anodic = p_anodic(i_extreme_anodic)\n",
    "    tangent_slope_anodic = p_anodic.coeffs[0] * (i_extreme_anodic * np.log(10))\n",
    "    log_i_extreme_anodic = np.log10(i_extreme_anodic)\n",
    "    log_i_tangent_anodic = np.linspace(log_i_extreme_anodic - 0.5, log_i_extreme_anodic, 100)\n",
    "    E_tangent_anodic = tangent_slope_anodic * (log_i_tangent_anodic - log_i_extreme_anodic) + E_extreme_anodic\n",
    "\n",
    "    i_extreme_cathodic = medfilt_cathodic_i.max()\n",
    "    E_extreme_cathodic = p_cathodic(i_extreme_cathodic)\n",
    "    tangent_slope_cathodic = p_cathodic.coeffs[0] * (i_extreme_cathodic * np.log(10))\n",
    "    log_i_extreme_cathodic = np.log10(i_extreme_cathodic)\n",
    "    log_i_tangent_cathodic = np.linspace(log_i_extreme_cathodic - 0.5, log_i_extreme_cathodic, 100)\n",
    "    E_tangent_cathodic = tangent_slope_cathodic * (log_i_tangent_cathodic - log_i_extreme_cathodic) + E_extreme_cathodic\n",
    "\n",
    "    print(coeff_anodic)\n",
    "    print(coeff_cathodic)\n",
    "    \n",
    "    # 6. Package results into a dictionary\n",
    "    results = {\n",
    "        \"ecorr_guess\": ecorr_guess,\n",
    "        \"anodic_tangent_i\": 10**log_i_tangent_anodic,\n",
    "        \"anodic_tangent_E\": E_tangent_anodic,\n",
    "        \"cathodic_tangent_i\": 10**log_i_tangent_cathodic,\n",
    "        \"cathodic_tangent_E\": E_tangent_cathodic,\n",
    "    }\n",
    "    return results\n",
    "\n",
    "# =============================================================================\n",
    "# --- Global Namespace: Analysis and Plotting ---\n",
    "# =============================================================================\n",
    "\n",
    "# 1. Analyze the dataset\n",
    "analysis_results = analyze_tafel_data(HS1_1)\n",
    "\n",
    "# 2. Set up the plot\n",
    "fig, ax = plt.subplots(figsize=(8, 4), dpi=150)\n",
    "ax.set_xscale('log') # Set x-axis to log scale\n",
    "\n",
    "ax.semilogx(\n",
    "    np.abs(HS1_1[\"i\"].to_numpy()),\n",
    "    HS1_1[\"E\"].to_numpy(), \n",
    "    markersize=5)\n",
    "\n",
    "# 3. Plot all data if analysis was successful\n",
    "if analysis_results:\n",
    "    # Plot Ecorr\n",
    "    ax.axhline(\n",
    "        y=analysis_results[\"ecorr_guess\"],\n",
    "        color='green', linestyle='--', linewidth=2, alpha=0.5, label='$E_{corr}$'\n",
    "    )\n",
    "\n",
    "    # Plot tangent lines\n",
    "    ax.plot(\n",
    "        analysis_results[\"anodic_tangent_i\"],\n",
    "        analysis_results[\"anodic_tangent_E\"],\n",
    "        'r', linestyle='-.', linewidth=2, label='Anodic Tangent'\n",
    "    )\n",
    "    ax.plot(\n",
    "        analysis_results[\"cathodic_tangent_i\"],\n",
    "        analysis_results[\"cathodic_tangent_E\"],\n",
    "        'b', linestyle='-.', linewidth=2, label='Cathodic Tangent'\n",
    "    )\n",
    "\n",
    "    # 4. Configure final plot aesthetics\n",
    "    ax.set_xlabel(\"Current (A)\")\n",
    "    ax.set_ylabel(\"Potential (V)\")\n",
    "    ax.set_title(\"Tafel Plot for HS1_1\")\n",
    "    ax.legend()\n",
    "    ax.grid(True, which=\"both\", ls=\"--\", linewidth=0.5)\n",
    "\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "89fcb5a1-e351-4014-bc1e-9a1ede37eafc",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "\n",
    "def analyze_tafel_data(\n",
    "    data: pd.DataFrame\n",
    ") -> dict | None:\n",
    "\n",
    "    INITIAL_KERNEL = 49\n",
    "    FIT_KERNEL = 49\n",
    "    \n",
    "    # 1. Estimate Corrosion Potential (Ecorr) using a median filter\n",
    "    filtered_current = medfilt(data['i'], kernel_size=INITIAL_KERNEL)\n",
    "    ecorr_guess_index = np.argmin(filtered_current)\n",
    "    ecorr_guess = data['E'].iloc[ecorr_guess_index]\n",
    "\n",
    "    # 2. Split data into anodic and cathodic regions based on Ecorr\n",
    "    anodic_data = data[data['E'] > ecorr_guess]\n",
    "    cathodic_data = data[data['E'] < ecorr_guess]\n",
    "\n",
    "    # 3. Apply a stronger filter for a cleaner linear fit\n",
    "    medfilt_anodic_i = medfilt(anodic_data['i'].iloc[30:-30], kernel_size=FIT_KERNEL)\n",
    "    medfilt_cathodic_i = medfilt(cathodic_data['i'].iloc[30:-30], kernel_size=FIT_KERNEL)\n",
    "\n",
    "    # 4. Perform linear fit on E vs. i for each branch\n",
    "    p_anodic = np.poly1d(np.polyfit(medfilt_anodic_i, anodic_data['E'].iloc[30:-30], 1))\n",
    "    p_cathodic = np.poly1d(np.polyfit(medfilt_cathodic_i, cathodic_data['E'].iloc[30:-30], 1))\n",
    "\n",
    "    # 5. Calculate tangent lines at the extreme ends of the filtered data\n",
    "    # NOTE: The following tangent slope calculation is preserved from the original script.\n",
    "    i_extreme_anodic = medfilt_anodic_i.max()\n",
    "    e_extreme_anodic = p_anodic(i_extreme_anodic)\n",
    "    tangent_slope_anodic = p_anodic.coeffs[0] * (i_extreme_anodic * np.log(10))\n",
    "\n",
    "    log_i_extreme_anodic = np.log10(i_extreme_anodic)\n",
    "    log_i_tangent_anodic = np.linspace(log_i_extreme_anodic - 0.5, log_i_extreme_anodic, 100)\n",
    "    e_tangent_anodic = (\n",
    "        tangent_slope_anodic * (log_i_tangent_anodic - log_i_extreme_anodic)\n",
    "        + e_extreme_anodic\n",
    "    )\n",
    "\n",
    "    i_extreme_cathodic = medfilt_cathodic_i.max()\n",
    "    e_extreme_cathodic = p_cathodic(i_extreme_cathodic)\n",
    "    tangent_slope_cathodic = p_cathodic.coeffs[0] * (i_extreme_cathodic * np.log(10))\n",
    "\n",
    "    log_i_extreme_cathodic = np.log10(i_extreme_cathodic)\n",
    "    log_i_tangent_cathodic = np.linspace(log_i_extreme_cathodic - 0.5, log_i_extreme_cathodic, 100)\n",
    "    e_tangent_cathodic = (\n",
    "        tangent_slope_cathodic * (log_i_tangent_cathodic - log_i_extreme_cathodic)\n",
    "        + e_extreme_cathodic\n",
    "    )\n",
    "\n",
    "    # 6. Package results into a dictionary\n",
    "    results = {\n",
    "        \"ecorr_guess\": ecorr_guess,\n",
    "        \"beta_a\": -p_anodic.coeffs[1],        \n",
    "        \"beta_c\": p_cathodic.coeffs[1],\n",
    "        \"anodic_tangent_i\": 10**log_i_tangent_anodic,\n",
    "        \"anodic_tangent_E\": e_tangent_anodic,\n",
    "        \"cathodic_tangent_i\": 10**log_i_tangent_cathodic,\n",
    "        \"cathodic_tangent_E\": e_tangent_cathodic,\n",
    "    }\n",
    "    return results\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "a17286f8-a4e7-4904-b304-8a343c2c1c51",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "def plot_tafel(data: pd.DataFrame, results: dict, title: str):\n",
    "    \"\"\"\n",
    "    Generates and displays a Tafel plot from the data and analysis results.\n",
    "\n",
    "    Args:\n",
    "        data (pd.DataFrame): The original experimental data.\n",
    "        results (dict): The dictionary returned by analyze_tafel_data.\n",
    "        title (str): The title for the plot.\n",
    "    \"\"\"\n",
    "    fig, ax = plt.subplots(figsize=(8, 4), dpi=150)\n",
    "\n",
    "    # Plot the raw experimental data\n",
    "    ax.semilogx(\n",
    "        np.abs(data[\"i\"].to_numpy()),\n",
    "        data[\"E\"].to_numpy(),\n",
    "        marker='o',\n",
    "        linestyle='',\n",
    "        markersize=3,\n",
    "        alpha=0.6,\n",
    "        label=\"Experimental Data\"\n",
    "    )\n",
    "\n",
    "    # Plot the analysis results if available\n",
    "    if results:\n",
    "        # Ecorr line\n",
    "        ax.axhline(\n",
    "            y=results[\"ecorr_guess\"],\n",
    "            color='green',\n",
    "            linestyle='--',\n",
    "            linewidth=2,\n",
    "            label=f'$E_{{corr}}$ = {results[\"ecorr_guess\"]:.3f} V'\n",
    "        )\n",
    "        # Anodic tangent line\n",
    "        ax.plot(\n",
    "            results[\"anodic_tangent_i\"],\n",
    "            results[\"anodic_tangent_E\"],\n",
    "            color='red',\n",
    "            linestyle='-.',\n",
    "            linewidth=2,\n",
    "            label=f'Anodic Tangent {results[\"beta_a\"]}'\n",
    "        )\n",
    "        # Cathodic tangent line\n",
    "        ax.plot(\n",
    "            results[\"cathodic_tangent_i\"],\n",
    "            results[\"cathodic_tangent_E\"],\n",
    "            color='blue',\n",
    "            linestyle='-.',\n",
    "            linewidth=2,\n",
    "            label=f'Cathodic Tangent {results[\"beta_c\"]}'\n",
    "        )\n",
    "\n",
    "    # Configure plot aesthetics\n",
    "    ax.set_xlabel(\"Absolute Current (A)\")\n",
    "    ax.set_ylabel(\"Potential (V)\")\n",
    "    ax.set_title(title)\n",
    "    ax.legend()\n",
    "    ax.grid(True, which=\"both\", ls=\"--\", linewidth=0.5)\n",
    "    plt.tight_layout()\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "2ca6744c-7d06-4f76-845a-1ab7f979a9ec",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "beta_a 0.1839147086435225\n",
      "beta_c -0.1821741558893317\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 169288 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# =============================================================================\n",
    "# --- Main Execution Block ---\n",
    "# =============================================================================\n",
    "\n",
    "# 1. Analyze the dataset\n",
    "analysis_results = analyze_tafel_data(HS1_1)\n",
    "print(f\"beta_a {analysis_results['beta_a']}\")\n",
    "print(f\"beta_c {analysis_results['beta_c']}\")\n",
    "\n",
    "# 2. Plot the results\n",
    "if analysis_results:\n",
    "    plot_tafel(HS1_1, analysis_results, title=\"Tafel Plot for HS1_1\")\n",
    "else:\n",
    "    print(\"Analysis could not be completed.\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "d88cffa3-f006-4612-903c-6863fe28110d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- Butler-Volmer Kinetic Parameters ---\n",
      "Anodic Charge Transfer Coefficient (α_a): 0.7785\n",
      "Cathodic Charge Transfer Coefficient (α_c): 0.5499\n",
      "\n",
      "--- Next Step: Finding the Exchange Current Density (j₀) ---\n",
      "The exchange current density (j₀) is found from your Tafel plot.\n",
      "It is the current density value where the anodic and cathodic tangent lines intersect.\n",
      "This point corresponds to the equilibrium potential (where overpotential η = 0).\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "\n",
    "# --- 1. Define Physical Constants ---\n",
    "R = 8.314  # Ideal Gas Constant (J/(mol·K))\n",
    "F = 96485  # Faraday Constant (C/mol)\n",
    "n = 2 # Number of electrons transferred in your electrochemical reaction.\n",
    "\n",
    "# --- 2. Provide Your Experimental Data Here ---\n",
    "anodic_slope = 0.038  # Example value in V/decade, replace with your own.\n",
    "cathodic_slope = -0.0538 # Example value in V/decade, replace with your own.\n",
    "\n",
    "# --- 3. Calculations ---\n",
    "# The temperature at which the experiment was conducted.\n",
    "temp_kelvin = 25.0 + 273.15\n",
    "\n",
    "\n",
    "# Calculate the anodic charge transfer coefficient (alpha_a)\n",
    "# This value represents the fraction of the potential that assists the oxidation reaction.\n",
    "try:\n",
    "    alpha_a = (2.303 * R * temp_kelvin) / (anodic_slope * n * F)\n",
    "    alpha_c = -(2.303 * R * temp_kelvin) / (cathodic_slope * n * F)    \n",
    "except ZeroDivisionError as e:\n",
    "    print(\"Slope is zero, what happened?\")\n",
    "    print(e)\n",
    "    \n",
    "\n",
    "# --- 4. Display the Results ---\n",
    "print(\"--- Butler-Volmer Kinetic Parameters ---\")\n",
    "print(f\"Anodic Charge Transfer Coefficient (α_a): {alpha_a:.4f}\")\n",
    "print(f\"Cathodic Charge Transfer Coefficient (α_c): {alpha_c:.4f}\")\n",
    "print(\"\\n--- Next Step: Finding the Exchange Current Density (j₀) ---\")\n",
    "print(\"The exchange current density (j₀) is found from your Tafel plot.\")\n",
    "print(\"It is the current density value where the anodic and cathodic tangent lines intersect.\")\n",
    "print(\"This point corresponds to the equilibrium potential (where overpotential η = 0).\")\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2b103a62-8b25-4f78-bbe3-3cf25644df78",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "92f40d16-49c1-487f-8b83-f05fc3a5b851",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a4643c2-60e6-4645-9d23-d13c6c410337",
   "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.10.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
