{ "cells": [ { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## Introduction to Scientific Computing\n", "### Lecture 05: Introduction to Data Visualization with Matplotlib\n", "#### J.R. Gladden, Spring 2018, Univ. of Mississippi" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Matplotlib has become a robust and industry standard library for plotting in Python. Since we are working here in a Ipython notebook, we can use the %matplolib \"magic\" to display the graphical output on the browser page (inline), or popup in external windows using a variety of graphical backends (osx, gtk, qt, ...)," ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Warning: Cannot change to a different GUI toolkit: wx. Using qt4 instead.\n" ] } ], "source": [ "%matplotlib wx" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "\n", "# Define a few functions to plot:\n", "\n", "def expdecay(x,lam=1.,A=1.):\n", " return A*np.exp(-x*lam)\n", "\n", "def dampedsine(x,lam=1.,k=1.,A=1.):\n", " apass=A\n", " lampass=lam\n", " return expdecay(x,lam=lampass,A=apass)*np.sin(k*x)\n", "\n", "def gauss(x,A=1.,sig=1.,x0=5.):\n", " return A*np.exp(-(x-x0)**2/sig)\n", "\n", "#Lets close any open windows:\n", "plt.close('all')\n", "\n", "\n", "# Now create an array of x values\n", "\n", "x=np.arange(0,10,0.02)\n", "\n", "# Make the first plot using a green line \n", "plt.plot(x,dampedsine(x,lam=0.4,k=10),'g-')\n", "plt.title(\"A damped sine curve\")\n", "plt.xlabel(\"Time (s)\")\n", "plt.ylabel(\"Amplitude (m)\")\n", "#Won't pop up until you tell it to:\n", "plt.show()\n" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "We can add a second curve by simply adding another plot command. Note we adding 2 new curves here." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plt.plot(x,expdecay(x,lam=0.4),'b--')\n", "plt.plot(x,-expdecay(x,lam=0.4),'b--')" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "plt.figure(1)\n", "plt.plot(x,np.sin(10*x))\n", "\n", "plt.figure(2,figsize=(12,8)) #(size in inches wide,high)\n", "plt.plot(x,dampedsine(x,k=10)*gauss(x))\n", "\n", "#Make figure 1 active and save it to a file\n", "plt.figure(1)\n", "plt.savefig('test.png')\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Plotting multiple data sets. We're also are adding a legend - note how we are dynamically updating the legend text based on the current parameters." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true, "deletable": true, "editable": true }, "outputs": [], "source": [ "t=np.linspace(0,10,100)\n", "def V(t,RC): \n", " return 10*np.exp(-t/RC)\n", "RCvals=[0.1,1.0,2.0,4.0,10.0]\n", "markers=['o','s','^','+','D']\n", "for i in range(len(RCvals)):\n", " marker=markers[i] \n", " RC=RCvals[i] \n", " plt.plot(t,V(t,RC),'b-'+marker, label='RC=%2.1f'%RC)\n", "plt.legend(loc=1)\n", "plt.xlabel('Time (s)', fontsize=16)\n", "plt.ylabel('Potential (V)',fontsize=16)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Best to use two different axes if your data sets have a large difference in scales." ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "plt.close('all')\n", "x=np.linspace(0,10,100)\n", "y1=np.sqrt(x)\n", "y2=x**3\n", "plt.plot(x,y1,'g-',lw=2,label='Sqrt(x)')\n", "plt.ylabel('Sqrt(x)')\n", "plt.legend(loc=2)\n", "ax2=plt.twinx()\n", "plt.plot(x,y2,'b--',lw=2,label='x^3')\n", "plt.ylabel('x^3')\n", "plt.xlabel('x')\n", "plt.legend(loc=4)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "This is how you do subplots. The subplot triple number (like 221) means a subplot 2x2 grid and the next plot command will go to the 1st plot in the grid." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "x=np.linspace(-np.pi,np.pi,100)\n", "plt.subplot(221)\n", "plt.plot(x,np.sin(x))\n", "plt.xlabel('X')\n", "plt.ylabel('Sin(x)')\n", "plt.subplot(222)\n", "plt.plot(x,np.cos(x))\n", "plt.xlabel('X')\n", "plt.ylabel('Cos(x)')\n", "plt.subplot(223)\n", "plt.plot(x,np.tan(x))\n", "plt.xlabel('X')\n", "plt.ylabel('Tan(x)')\n", "plt.subplot(224)\n", "plt.plot(x,np.cosh(x))\n", "plt.xlabel('X')\n", "plt.ylabel('Cosh(x)')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "** Fancy Stuff:** Adding arrows, add text annotations, even Latex equations!" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "plt.close('all')\n", "x=np.linspace(0,np.pi,100)\n", "plt.fill_between(x,np.tan(x),y2=0,lw=2,color='green')\n", "plt.annotate('A pole',xy=(np.pi/2.0,50), xytext=(0.25,10), \n", " fontsize=16,arrowprops=dict(facecolor='blue',shrink=0.05))\n", "plt.text(2,40,'$\\int_0^\\pi \\mathrm{tan}(x) = 0$',fontsize=25)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "deletable": true, "editable": true }, "source": [ "** Polar Plots: ** " ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "theta=np.arange(0,2*np.pi,np.pi/100)\n", "r1=3+np.sin(4*theta)\n", "r2=3+np.sin(6*theta)\n", "plt.polar(theta,r1)\n", "plt.polar(theta,r2)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "** Quiver (Vector) Plots: ** These are 2D plots of a vector field. So every point in the 2D space needs to have a vector (magnitude and direction) associated with it. This requires generating a 'meshgrid' in the 2D space. Also take care about the length of the vectors since they can vary wildly and obscure the story you are trying to tell." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plt.close('all')\n", "gridvec=np.linspace(0,2*np.pi,50) \n", "x,y=np.meshgrid(gridvec,gridvec) # Make a uniform square mesh of 2D points. Outputs 2 2D arrays.\n", "U=np.sin(y) # function for the 'x' component of the vector\n", "V=np.cos(x) # function for the 'y' component\n", "plt.quiver(x,y,U,V,np.sqrt(U**2+V**2)) # The last argument scales the color by the magnitude.\n", "plt.title('Vector (quiver) plot of V_x=sin(x), V_y=cos(y)', fontsize=20)\n", "plt.xlabel('x',fontsize=20)\n", "plt.ylabel('y',fontsize=20)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": true }, "outputs": [], "source": [ "plt.quiver?" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "** Interacting with plots: ** Matplotlib does provide tools for interacting with plots to make them more dynamic. This requires capturing an 'event' (such as a click, button press, or mouse movment) and adjusting something on the plot when that event occurs. This is rather basic \"event handling\" but sufficient for a lot of what we do as scientists. This example plots a bunch of gaussians centered on where a user clicks in the plot area. It also takes in some button clicks to clear of quit (and close the window). ** NOTE: ** This **sometimes** works in the iPython notebook, but should work fine when run in Canopy or directly in the iPython command line." ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "plt.close('all')\n", "\n", "\n", "def click(event):\n", " col=(np.random.rand(),np.random.rand(),np.random.rand()) #set a random RGB tuple for the current curve color\n", " #OR could use: col=tuple(rand(3))\n", " xClick,yClick= event.xdata, event.ydata # grab the x,y coordinates of the click (floats)\n", " plt.plot(x,gauss(x,A=yClick,x0=xClick),color=col)\n", " plt.draw()\n", "\n", "def done(event1):\n", " if event1.key == 'q': close('all') \n", " if event1.key == 'c': \n", " plt.clf()\n", " plt.plot([0],[0]) #clears existing graphs\n", " plt.axis([0, 10, 0, 1])\n", " plt.draw()\n", "# Define x values\n", "x=np.linspace(0,10,100)\n", "#now register the event to the above function\n", "cid = plt.connect('button_press_event',click)\n", "cid1= plt.connect('key_press_event',done)\n", "\n", "plt.title(\"Click anywhere in the graph to draw a new Gaussian. \\n Type 'q' to quit\")\n", "plt.xlabel(\"X\")\n", "plt.ylabel(\"Y\")\n", "plt.plot([0],[0]) #clears existing graphs\n", "plt.axis([min(x), max(x), 0, 1])\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "ename": "AttributeError", "evalue": "'module' object has no attribute 'random'", "output_type": "error", "traceback": [ "\u001b[0;31m\u001b[0m", "\u001b[0;31mAttributeError\u001b[0mTraceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrandom\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mAttributeError\u001b[0m: 'module' object has no attribute 'random'" ] } ], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.13" } }, "nbformat": 4, "nbformat_minor": 0 }