{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from IPython.core.display import display, HTML\n",
    "display(HTML(\"<style>.container { width:100% !important; }</style>\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import math\n",
    "import scipy\n",
    "\n",
    "from __future__ import print_function\n",
    "from ipywidgets import interact, interactive, fixed, interact_manual\n",
    "import ipywidgets as widgets"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Read in Measurements"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "two_k_sampling_trafo = pd.read_csv(r'2000OhmSamplingTrafoSupply.csv')\n",
    "one_k_sampling_trafo = pd.read_csv(r'1000OhmSamplingTrafoSupply.csv')\n",
    "temperature_measurement = pd.read_csv(r'TempSamplingTrafoSupply.csv')\n",
    "constant_sampling = pd.read_csv(r'1000OhmSampling.csv')\n",
    "shielded_df = pd.read_csv(r'ContactPT1000HeatgunCooldown.csv')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Calculation Function for $\\vartheta(R_{PT1000})$\n",
    "$\\vartheta(R_{PT1000}) = \\frac{-\\alpha R_0 + \\sqrt{\\alpha^2R_0^2 - 4\\beta R_0 \\left(R_0 - R_{PT1000}\\right)}}{2\\beta R_0}$\n",
    "\n",
    "with\n",
    "* $\\alpha = 3.9083 \\cdot 10^{-3}$\n",
    "* $\\beta = -5.7750 \\cdot 10^{-7}$\n",
    "* $R_0 = 1000~\\Omega$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "R_zero = 1000.0\n",
    "A = 3.9083E-3\n",
    "B = -5.7750E-7\n",
    "\n",
    "def calc_temp(resistance):\n",
    "    temp = (-R_zero * A + np.sqrt(R_zero*R_zero * A * A - 4* R_zero * B * (R_zero - resistance)))/(2*R_zero*B)\n",
    "    return temp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_histogram(ax, data, bin_count, title, signal_name):\n",
    "    n, bins, patches = ax.hist(data, bin_count, density=1, color='navy')\n",
    "    mu = np.mean(data)\n",
    "    sigma = np.std(data)\n",
    "    y = ((1 / (np.sqrt(2 * np.pi) * sigma)) * np.exp(-0.5 * (1 / sigma * (bins - mu))**2))\n",
    "    ax.plot(bins, y, color='darkorange')\n",
    "    ax.set_title(title)\n",
    "    ax.set_ylabel(signal_name + ' probability (normalized)')\n",
    "    ax.set_xlabel(signal_name)\n",
    "    # Plot sigma and mu lines\n",
    "    ax.axvline(x=mu-sigma, ls='--', color='magenta')\n",
    "    ax.axvline(x=mu+sigma, ls='--', color='magenta')\n",
    "    ax.axvline(x=mu, ls='--', color='lawngreen')\n",
    "\n",
    "    #Plot textbox\n",
    "    textstr = '\\n'.join((\n",
    "        r'$\\mu=%.2f$' % (mu, ),\n",
    "        r'$\\sigma=%.4f$' % (sigma, ),\n",
    "        r'$N_{Sa} =%d$' % (len(data), )))\n",
    "    props = dict(boxstyle='round', facecolor='wheat', alpha=0.5)\n",
    "    ax.text(0.05, 0.95, textstr, transform=ax.transAxes, fontsize=14,\n",
    "    verticalalignment='top', bbox=props)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "--------------------\n",
    "# Calculate Temperature from Resistance Value"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def calculate_temp_for_df(data_frame, resistance_col_name='ext_lf_corr', temp_col_name='temp_calculated'):\n",
    "    data_frame[temp_col_name] = data_frame.apply(lambda row: calc_temp(row[resistance_col_name]) , axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_list = [one_k_sampling_trafo, two_k_sampling_trafo, temperature_measurement, constant_sampling, shielded_df]\n",
    "for df in df_list:\n",
    "    calculate_temp_for_df(df)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Histograms  (Uncalibrated)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plot_data = [(one_k_sampling_trafo, '1 kOhm Sampling Transformer powered', 0), (two_k_sampling_trafo, '2 kOhm Sampling Transformer powered' , 0), (constant_sampling, '1 kOhm Sampling', 100)]\n",
    "signal_list = [('ext_lf_corr', 20), ('temp_calculated', 20)]\n",
    "\n",
    "fig, axes = plt.subplots(nrows=len(plot_data), ncols=len(signal_list), figsize=(28,20))\n",
    "\n",
    "for (data_df, title, start_idx), ax_rows in zip(plot_data, axes):\n",
    "    for ax,sig in zip(ax_rows, signal_list):\n",
    "        plot_histogram(ax, data_df[sig[0]][start_idx:], sig[1], title,sig[0])\n",
    "\n",
    "        \n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Startup of Moving Average Filter with $\\alpha' = 0.005$\n",
    "\n",
    "Filter difference equation: $y[n] = (1-\\alpha')y[n-1] + \\alpha'x[n]$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(nrows=2, ncols=1, figsize=(28,6), sharex=True)\n",
    "data = constant_sampling['ext_lf_corr'][:20]\n",
    "ax[0].plot(constant_sampling['Time'][:20], data)\n",
    "ax[1].plot(constant_sampling['Time'][:20], constant_sampling['temp_calculated'][:20])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Temperature Plotting\n",
    "\n",
    "Noise is visible as soon as the temperature sensor is touched or connected to ground in an improper way."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "idx_count = len(temperature_measurement.index)\n",
    "@interact(low=(0,idx_count -1,10), high=(0, idx_count-1, 10))\n",
    "def plot_temp(low=0, high=idx_count-1):\n",
    "    fig, ax = plt.subplots(nrows=3, ncols=1, figsize=(28,9*3), sharex=True)\n",
    "    ax[0].plot(temperature_measurement['Time'][low:high], temperature_measurement['adc_results.pa2_raw'][low:high])\n",
    "    ax[1].plot(temperature_measurement['Time'][low:high], temperature_measurement['ext_lf_corr'][low:high])\n",
    "    ax[2].plot(temperature_measurement['Time'][low:high], temperature_measurement['temp_calculated'][low:high])\n",
    "    titles = ['Raw ADC Results', 'Low Pass Filtered Resistance Reading', 'Calculated Low Frequency Temperature']\n",
    "    for i, title in zip(range(0,3), titles):\n",
    "        ax[i].grid()\n",
    "        ax[i].set_title(title)\n",
    "    plt.plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Temperature Plotting With Proper Grounding of Circuit and the Cable Shield"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Derivateve of temp\n",
    "shielded_df['temp_gradient'] = shielded_df['temp_calculated'].diff() / shielded_df['Time'].diff()\n",
    "\n",
    "# Low pass filter gradient with moving average\n",
    "shielded_df['temp_gradient_lf'] = 0.0\n",
    "shielded_df['temp_gradient_lf_2'] = 0.0\n",
    "last_grad_lf = 0.0\n",
    "\n",
    "alpha = 0.005\n",
    "delta_alpha = 0.00\n",
    "zeta = 20\n",
    "\n",
    "for index, row in shielded_df.iterrows():\n",
    "    if index == 0:\n",
    "        pass\n",
    "    else:\n",
    "        current_gradient = row['temp_gradient']\n",
    "        if last_grad_lf != 0.0:\n",
    "            alpha_corr = abs(current_gradient) / zeta  * delta_alpha\n",
    "        else:\n",
    "            alpha_corr = 0\n",
    "        last_grad_lf = last_grad_lf * (1-(alpha+alpha_corr)) + (alpha+alpha_corr) * current_gradient\n",
    "        shielded_df.at[index, 'temp_gradient_lf'] = last_grad_lf\n",
    "        \n",
    "# Derivateve of grad is grad2\n",
    "shielded_df['temp_gradient_lf_2'] = shielded_df['temp_gradient_lf'].diff() / shielded_df['Time'].diff()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Full curve"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(figsize=(28,9))\n",
    "tau = 25\n",
    "tau2 = 0\n",
    "ax.plot(shielded_df['Time'], shielded_df['temp_calculated'], label='Uncalibrated Temperature')\n",
    "ax.plot(shielded_df['Time'], shielded_df['temp_calculated']+shielded_df['temp_gradient_lf']*tau + shielded_df['temp_gradient_lf_2']*tau2, label=r'PT1 corrected with $\\tau = %f$' % tau)\n",
    "ax.grid()\n",
    "ax.legend()\n",
    "ax.set_title('Temperature measurement with proper ground connection')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Temperature Gradient Noise vs Moving Average\n",
    "### Time Domain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(figsize=(28,8))\n",
    "tau = 30\n",
    "ax.plot(shielded_df['Time'], shielded_df['temp_gradient'], label=r\"$\\dot{\\vartheta} = \\frac{\\partial\\vartheta}{\\partial t}$\")\n",
    "ax.plot(shielded_df['Time'], shielded_df['temp_gradient_lf'], label=r'$\\tilde{\\dot{\\vartheta}}$')\n",
    "ax.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cooldown to Room Temperature in Detail"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(figsize=(28,9))\n",
    "start_time = -320\n",
    "filtered_cooldown = shielded_df[shielded_df['Time'] > start_time]\n",
    "ax.plot(filtered_cooldown['Time'], filtered_cooldown['temp_calculated'], label='Measured Cooldown')\n",
    "ax.plot(filtered_cooldown['Time'], filtered_cooldown['temp_calculated']+filtered_cooldown['temp_gradient_lf']*tau, label='Calculated Exterior Temperature')\n",
    "ax.grid()\n",
    "ax.set_title('Cooldown without airflow | Convection has to be taken into account') \n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "# Target Implementation Sampling of 1k Resistor"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Histograms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Read in data\n",
    "kilo_ohm_sampling1 = pd.read_csv(r'1000OhmSamplingFixedStableCircuit.csv')\n",
    "kilo_ohm_sampling1_ht = pd.read_csv(r'1000OhmSamplingFixedStableCircuitHT.csv')\n",
    "kilo_ohm_sampling2 = pd.read_csv(r'1000OhmSamplingFixedStableCircuitDay2.csv')\n",
    "plot_data_tuples = [(kilo_ohm_sampling1, 'Day 1 Sampling -- Stable circuit -- RT'),\n",
    "                    (kilo_ohm_sampling1_ht, 'Day 1 Sampling -- Stable circuit -- HT'),\n",
    "                    (kilo_ohm_sampling2, 'Day 2 Sampling -- Stable circuit'),\n",
    "                    (pd.read_csv(r'1000OhmSamplingFixedStableCircuitDay3.csv'), 'Day 3 Sampling -- Stable Circuit (improved)'),\n",
    "                    (pd.read_csv(r'1000OhmSamplingFixedStableCircuitDay4.csv'), 'Day 4 Sampling -- Stable Circuit (improved)'),\n",
    "                    (pd.read_csv(r'1000OhmSampling-v1.2.csv'), 'Day 1 Sampling v1.2')\n",
    "                   ]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# def plot_histogram(ax, data, bin_count, title, signal_name):\n",
    "# def calculate_temp_for_df(data_frame, resistance_col_name='ext_lf_corr', temp_col_name='temp_calculated'):\n",
    "\n",
    "fig, axes = plt.subplots(nrows=len(plot_data_tuples), ncols=2, sharex='col', figsize=(28, 8*len(plot_data_tuples)))\n",
    "\n",
    "if len(plot_data_tuples) == 1:\n",
    "    axes = [axes]\n",
    "\n",
    "for df, title in plot_data_tuples:\n",
    "    calculate_temp_for_df(df, resistance_col_name='pt1000_value')\n",
    "\n",
    "for (df,title),ax in zip(plot_data_tuples, axes):\n",
    "    plot_histogram(ax[0], df['pt1000_value'], 21, title, 'PT1000 Resistance')\n",
    "    plot_histogram(ax[1], df['temp_calculated'], 21, title, 'Calculated Temperature in °C')\n",
    "    ax[0].grid()\n",
    "    ax[1].grid()\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, axes = plt.subplots(nrows=1, ncols=2, sharex='col', figsize=(28, 8))\n",
    "v12_df = pd.read_csv(r'hw-v12-1000Ohm.csv')                       \n",
    "plot_histogram(axes[0], v12_df['pt1000_res_raw_lf'], 21, 'HW v1.2 1k Ohm Sampling', '1k Resistance')\n",
    "plot_histogram(axes[1], v12_df['adc_pt1000_raw_reading_hf'], 21, 'HW v1.2 1k Ohm Sampling', '1k Resistance HF RAW')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, axes = plt.subplots(nrows=1, ncols=2, sharex='col', figsize=(28, 8))\n",
    "v13_df = pd.read_csv(r'1000OhmSampling-v1.3.csv')                       \n",
    "plot_histogram(axes[0], v13_df['pt1000_res_raw_lf'], 21, 'HW v1.3 1k Ohm Sampling', '1k Resistance')\n",
    "plot_histogram(axes[1], v13_df['adc_pt1000_raw_reading_hf'], 21, 'HW v1.3 1k Ohm Sampling', '1k Resistance')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(calc_temp(1000.6)-calc_temp(1000.4))\n",
    "\n",
    "adc_min_res = 1/4095*2500\n",
    "print('Min res: ', adc_min_res)\n",
    "\n",
    "print(calc_temp(2000))\n",
    "print(calc_temp(2000+adc_min_res))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.9.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
