{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Example Plots\n",
    "This notebook is a series of example plots. It contains examples of simple plots, fits and interactive plots. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# interactive plot of finding pi using a monte-carlo approach\n",
    "import matplotlib.pyplot as plt\n",
    "import random\n",
    "import math\n",
    "def montecarlo_pi(number_experiments):\n",
    "    \"\"\"Finds pi using a montecarlo approach, by performing n random placements of points on a square and finding the\n",
    "    number of points in a circle compared to the number of points in a square on the interval [0,1]\"\"\"\n",
    "    x_positions=[random.uniform(-1,1) for i in range(number_experiments)]\n",
    "    y_positions=[random.uniform(-1,1) for i in range(number_experiments)]\n",
    "    \n",
    "    # area of circle of radius  is pi, area of square=4, so pi=4*number_in_circle/number_in_square\n",
    "    number_in_circle=0\n",
    "    inside_x=[]\n",
    "    inside_y=[]\n",
    "    for index,value in enumerate(x_positions):\n",
    "        if (value**2+y_positions[index]**2)<1.**2:\n",
    "            number_in_circle+=1\n",
    "            inside_x.append(value)\n",
    "            inside_y.append(y_positions[index])\n",
    "    #print number_in_circle\n",
    "    pi_estimate=4.0*float(number_in_circle)/(float(number_experiments))\n",
    "    plt.plot(x_positions,y_positions,'ro',alpha=0.5)\n",
    "    plt.plot(inside_x,inside_y,'bo',alpha=0.5)\n",
    "    plt.suptitle(r'Monte Carlo Estimate of  $\\pi\\approx%s $ for %s trials, %s percent difference'%(pi_estimate,\n",
    "                                                                                            number_experiments,\n",
    "                                                                                           100*(pi_estimate-math.pi)/math.pi))\n",
    "    circle=plt.Circle((0,0), radius=1, color='b',  alpha=0.5)\n",
    "    \n",
    "    ax = plt.gca()\n",
    "    ax.add_artist(circle)\n",
    "    #ax.set_aspect('equal', 'datalim'\n",
    "    plt.show()\n",
    "montecarlo_pi(1000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "003cd0bb7d1b43a28ddcb4b18568a3e9",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "interactive(children=(IntSlider(value=50000, description='number_experiments', max=100000, min=10, step=10), O…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<function __main__.montecarlo_pi(number_experiments)>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "from ipywidgets import *\n",
    "\n",
    "interact(montecarlo_pi,number_experiments=(10,100000,10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "9c428cbac3814f7388ee7a9a958badd2",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "interactive(children=(FloatSlider(value=0.5, description='amplitude', max=1.0), FloatSlider(value=0.0, descrip…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<function __main__.plot_gaussian_with_noise(amplitude, mu, sigma, noise_distribution, noise_width, noise_center)>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "from ipywidgets import *\n",
    "import random\n",
    "import numpy\n",
    "import scipy\n",
    "import scipy.optimize\n",
    "import scipy.stats\n",
    "\n",
    "def lorentzian_function(a,x):\n",
    "    \"a[0]=amplitude,a[1]=center,a[2]=FWHM\"\n",
    "    return a[0]*1/(1+(x-a[1])**2/(a[2]**2))\n",
    "\n",
    "def gaussian_function(a,x):\n",
    "    \" a[0]=amplitude, a[1]=center, a[2]=std deviation\"\n",
    "    return a[0]*scipy.exp(-(x-a[1])**2/(2.0*a[2]**2))\n",
    "def power_function(a,x):\n",
    "    \" a[0]=constant, a[1]=center, a[2]=std deviation\"\n",
    "    return a[0]+a[1]*x+a[2]*x**2\n",
    "\n",
    "# Define the fit function that returns least square optimization\n",
    "def fit(function,xdata,ydata,a0):\n",
    "    fit_dictionary={}\n",
    "    error_function=lambda a, xdata, ydata:function(a,xdata)-ydata\n",
    "    a,succes=scipy.optimize.leastsq(error_function, a0,args=(xdata,ydata))\n",
    "    return a\n",
    "\n",
    "\n",
    "def plot_gaussian_with_noise(amplitude,mu,sigma,noise_distribution,noise_width,noise_center):\n",
    "    xdata=numpy.linspace(-10,10,1000)\n",
    "    a=[amplitude,mu,sigma]\n",
    "    if noise_distribution in ['uniform']:\n",
    "        left=noise_center-noise_width/2\n",
    "        right=noise_center+noise_width/2\n",
    "        [noise_width,noise_center]=[left,right]\n",
    "        \n",
    "    ydata=[gaussian_function(a,x)+random.__dict__[noise_distribution](noise_center,noise_width) for x in xdata]\n",
    "    plt.plot(xdata,ydata)\n",
    "    plt.show()\n",
    "interact(plot_gaussian_with_noise,\n",
    "         amplitude=(0.,1.,.1),mu=(-10,10,.1),sigma=(.1,10,.1),\n",
    "         noise_distribution=['gauss','uniform','lognormvariate'],\n",
    "         noise_width=(0,1,.01),noise_center=fixed(0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def calculate_residuals(fit_function,a,xdata,ydata):\n",
    "    \"\"\"Given the fit function, a parameter vector, xdata, and ydata returns the residuals as [x,y] pairs\"\"\"\n",
    "    output_x=xdata\n",
    "    output_y=[fit_function(a,x)-ydata[index] for index,x in enumerate(xdata)]\n",
    "    return [output_x,output_y]\n",
    "\n",
    "def fit_and_plot(fit_function,xdata,ydata,a0=[1,1,1]):\n",
    "    \"\"\"fit and plot, fits xdata, ydata  with fit function and returns a plot of the fit overlaid with the data and \n",
    "    a plot of the residuals, including a histogram\"\"\"\n",
    "    fit_results=fit(fit_function,xdata,ydata,a0)\n",
    "    # To do 2 plots in 2 rows with shared axis\n",
    "    fig, (ax0, ax1) = plt.subplots(nrows=2, sharex=True)\n",
    "    ax0.plot(xdata,ydata,'bo',label='data')\n",
    "    ax0.plot(xdata,[fit_function(fit_results,x) for x in xdata],'r-',linewidth=3,label='fit')\n",
    "    ax0.legend(loc='upper right', shadow=True)\n",
    "    ax0.set_title('Fit of data using {0}'.format(fit_function.__name__))\n",
    "    [x,y]=calculate_residuals(fit_function,fit_results,xdata,ydata)\n",
    "    ax1.plot(x,y)\n",
    "    ax1.set_title('Residuals')\n",
    "    options={'fontsize':12}\n",
    "    ax0.text(11,\n",
    "             -.1,\n",
    "             \"a[0] = {0:3.2g}\\na[1]= {1:3.2g}\\na[2]= {2:3.2g}\".format(fit_results[0],fit_results[1],fit_results[2]),\n",
    "             **options)\n",
    "    plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 37448 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "xdata=numpy.linspace(-10,10,1000)\n",
    "ydata=[.5*scipy.exp(-(x-.1)**2/(2.0*3.0**2))+random.gauss(0,.1) for x in xdata]\n",
    "fit_and_plot(gaussian_function,xdata,ydata)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "ce3ba4c14e074e568473550c56593495",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "interactive(children=(FloatSlider(value=0.0, description='noise_sigma', max=1.0, step=0.01), FloatSlider(value…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<function __main__.<lambda>(noise_sigma, noise_mu)>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "interact(lambda noise_sigma,noise_mu:fit_and_plot(gaussian_function,\n",
    "                               xdata,\n",
    "                               [.5*scipy.exp(-(x-.1)**2/(2.0*3.0**2))+random.gauss(noise_mu,noise_sigma) for x in xdata]),\n",
    "         noise_sigma=(0,1,.01),\n",
    "         noise_mu=(0,1,.01))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "0758549afa1142c38c37a38b6a4c6e9d",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "interactive(children=(Dropdown(description='fit_function', options=('gaussian_function', 'lorentzian_function'…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<function __main__.<lambda>(fit_function, noise_sigma, noise_mu)>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "interact(lambda fit_function,noise_sigma,noise_mu:fit_and_plot(globals()[fit_function],\n",
    "                               xdata,\n",
    "                               [.5*scipy.exp(-(x-.1)**2/(2.0*3.0**2))+random.gauss(noise_mu,noise_sigma) for x in xdata]),\n",
    "         fit_function=['gaussian_function','lorentzian_function','power_function'],\n",
    "         noise_sigma=(0,1,.01),\n",
    "         noise_mu=(0,1,.01))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.7.0"
  },
  "widgets": {
   "state": {
    "4e35e7c01db74428950207b0f2cb76db": {
     "views": [
      {
       "cell_index": 2
      }
     ]
    },
    "5106dcf58c0746ffb48c03db855a3b1c": {
     "views": [
      {
       "cell_index": 7
      }
     ]
    },
    "919ca0d3d42b4670ac600b75252a86f6": {
     "views": [
      {
       "cell_index": 6
      }
     ]
    },
    "cc94333686084203a5e7181fa0084186": {
     "views": [
      {
       "cell_index": 3
      }
     ]
    }
   },
   "version": "1.2.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
