{ "cells": [ { "cell_type": "markdown", "id": "a2d81585-b363-4ec3-a8a0-926f12d7f491", "metadata": {}, "source": [ "

TP 4: Matplotlib

\n", "\n", "Objectives:\n", "" ] }, { "attachments": {}, "cell_type": "markdown", "id": "88363a16-e64c-467f-82b6-b72570ff7ce0", "metadata": {}, "source": [ "I. Plotting a curve $y=f(x)$\n", "\n", "1) Basic commands of the module Pyplot from the package Matplotlib\n", "\n", "Matplotlib is a package to make figures. The most relevant module for us is Pyplot. We list below the most relevant functions. For more details, consult the lectures notes §III.1, or look at the documentation: https://matplotlib.org/3.5.3/api/_as_gen/matplotlib.pyplot.html.\n", "\n", "a) The function figure\n", "\n", "The function figure is used to initialize the graph. Without this statement, Python will initialize a new figure with default characteristics. So using this function allows you to start a clean environment, possibly tailored to your needs. \n", "\n", "It is possible to pass a window name (type str) or a number as an argument. In this case, if the same program is run several times without closing the window, the graph is plotted as many times with different colours.\n", "\n", "b) The function plot\n", "\n", "The function plot is probably the most used function in scientific visualization. It allows you to plot two lists, or two NumPy arrays, which contain the abscissae and ordinates.\n", "\n", "c) The function show\n", "\n", "The function show requests the display of all open figures. It is used once all the operations for constructing the figures have been completed. Thus, many plotting actions can be accumulated before displaying.\n", "\n", "The function show does not close the figure. It is still possible to add elements to it later until the close instruction (if you do not manually close the figure). This may not work in Jupyter notebooks which may have an \"auto-clearing\" behaviour after show (but we will not discuss this in detail).\n", "\n", "d) The function close\n", "\n", "The function close is never used in interactive mode (i.e., when you directly pass commands after running python or python3 in a terminal) as it destroys the window. \n", "\n", "In programming, it is a good habit to place a close before the call to figure in order to recreate a new figure and not to take the risk of rewriting in an already existing figure of the same name.\n", "\n", "\n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " Run the code below to understand the basic use of pyplot functions. Add appropriate comments when required.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "2f91589d-af76-490e-8a5b-ed609415463b", "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt # We load the package pyplot from the module Matplotlib.\n", "x = [0, 2, 1, 0] # List of abscissa (it could be a NumPy 1D array also).\n", "y = [0, 0, 3, 0] # List of ordinates (it could be a NumPy 1D array also).\n", "z = [0, 0, -3, 0] # List of ordinates (it could be a NumPy 1D array also).\n", "plt.close() # COMMENT REQUIRED\n", "plt.figure() # COMMENT REQUIRED\n", "plt.plot(x, y) # COMMENT REQUIRED\n", "plt.show() # COMMENT REQUIRED" ] }, { "cell_type": "code", "execution_count": null, "id": "afb5f789-86a0-419f-a419-a0eb637d540d", "metadata": {}, "outputs": [], "source": [ "plt.close()\n", "x = [0, 1]\n", "y1 = [0, 1]\n", "y2 = [1, 0]\n", "plt.close()\n", "plt.figure('fig1') # COMMENT REQUIRED\n", "plt.plot(x, y1)\n", "plt.figure('fig2') # COMMENT REQUIRED\n", "plt.plot(x, y2) # COMMENT REQUIRED\n", "plt.show() # COMMENT REQUIRED" ] }, { "cell_type": "code", "execution_count": null, "id": "27649be0-f253-4e2e-a1fc-7cc2fc7aeef1", "metadata": {}, "outputs": [], "source": [ "x = [0, 1]\n", "y1 = [0, 1]\n", "y2 = [1, 0]\n", "plt.close()\n", "plt.figure('fig1')\n", "plt.plot(x, y1)\n", "plt.figure('fig2')\n", "plt.plot(x, y2)\n", "plt.close('fig1')\n", "plt.show() # COMMENT REQUIRED" ] }, { "attachments": {}, "cell_type": "markdown", "id": "798e2127-0fe3-4b68-913c-b3a2da1b85b1", "metadata": {}, "source": [ "2) Combination with NumPy to draw a curve \n", "\n", "Contrary to gnuplot or Mathematica, you cannot directly plot a function with Matplotlib. You have to manually create a list or array of abscissae and a second list or array of ordinates. As explained in detail in TP3, it is better to use NumPy arrays which allow element-wise calculations to directly compute the array of ordinates from the array of abscissae (vectorization). For more details, consult the lectures notes §III.2.\n", "\n", "\n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " Run the code below to understand how to plot a function with NumPy and Matplotlib. Add comments when required.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "7e9bf1c0-a057-439f-9ed1-aabe653f2f5d", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "x = np.linspace(0, 2 * np.pi, 50) # COMMENT REQUIRED\n", "y = np.cos(x) # COMMENT REQUIRED\n", "plt.figure(\"Plotting a cosine function\")\n", "plt.plot(x, y)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "f75dbfe0-3c3d-4571-9e21-d41db89af559", "metadata": {}, "outputs": [], "source": [ "def my_func(x):\n", " return x / (1 + x ** 2)\n", "\n", "\n", "x = np.linspace(0, 10, 200)\n", "y = my_func(x)\n", "plt.figure(\"Plotting my function\")\n", "plt.plot(x, y)\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "d2410f99-1f54-48e3-9f3d-5edfc94e6569", "metadata": {}, "source": [ "3) Drawing several curves on the same graph \n", "\n", "As long as you do not run the function show, multiple calls to the function plot leads to the accumulation of the different drawings on the same figure. By default, Python uses a different colour for the different curves.\n", "\n", "You can also use a single call to the function plot but with 2D arrays where each column corresponds to the function you want to plot.\n", "\n", "The range of the two axes is adjusted automatically. \n", "\n", "You can label the different curves and show the legend of the plot.\n", "\n", "\n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " Run the codes below which illustrates the overplotting of different functions on the same figure. Add appropriate comments when required.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "1d5ed0da-38ef-4bb5-a446-c3de001f84c0", "metadata": {}, "outputs": [], "source": [ "plt.figure(\"Plotting three functions\")\n", "x = np.linspace(0, 2 * np.pi, 50)\n", "plt.plot(x, np.cos(x), label=\"cos(x)\")\n", "x = np.linspace(- np.pi, np.pi, 50)\n", "plt.plot(x, np.sin(x), label=\"sin(x)\")\n", "x = np.linspace(-5, 5, 50)\n", "plt.plot(x, 1 / (1 + np.exp(-x)), label=\"1/(1+e^{-x})\")\n", "plt.legend() # By default, Python tries to find the best location of the legend to avoid overlap with the curves.\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "3e6b3bb2-c285-4d40-b898-8254ce49e87d", "metadata": {}, "outputs": [], "source": [ "plt.figure(\"Plotting three functions\")\n", "x = np.linspace(-np.pi, 2 * np.pi, 50)\n", "xx = x.reshape((x.size, 1)) # COMMENT REQUIRED\n", "y = np.hstack((np.cos(xx), np.sin(xx))) # COMMENT REQUIRED\n", "plt.plot(x, y, label=['cos(x)', 'sin(x)']) # COMMENT REQUIRED\n", "x = np.linspace(-5, 5, 50)\n", "plt.plot(x, 1 / (1 + np.exp(-x)), label=\"1/(1+e^{-x})\")\n", "plt.legend()\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "fc69a5c4-22a6-461e-a465-01dc4b2366bb", "metadata": {}, "outputs": [], "source": [ "plt.figure(\"Plotting three functions\")\n", "x = np.linspace(0, 2 * np.pi, 50)\n", "plt.plot(x, np.cos(x), label=\"cos(x)\")\n", "x = np.linspace(- np.pi, np.pi, 50)\n", "plt.plot(x, np.sin(x), label=\"sin(x)\")\n", "x = np.linspace(-5, 5, 50)\n", "plt.plot(x, 1 / (1 + np.exp(-x)), label=\"1/(1+e^{-x})\")\n", "plt.legend(loc=0) # loc = 0 means that Matplotlib tries to find the best location, but you can try changing the value of loc (integers\n", "# between 0 and 10 to see how the legend moves).\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "6bcc5ca6-1b2b-4b43-bb98-d02a9e5f1255", "metadata": {}, "outputs": [], "source": [ "plt.figure(\"Plotting three functions\")\n", "x = np.linspace(0, 2 * np.pi, 50)\n", "plt.plot(x, np.cos(x), label=r\"$\\cos(x)$\") # To write the legend with LaTeX, you have to put an 'r' before the string, and then you can\n", "# use LaTeX commands in the string.\n", "x = np.linspace(- np.pi, np.pi, 50)\n", "plt.plot(x, np.sin(x), label=r\"$\\sin(x)$\")\n", "x = np.linspace(-5, 5, 50)\n", "plt.plot(x, 1 / (1 + np.exp(-x)), label=r\"$\\dfrac{1}{1+e^{-x}}$\")\n", "plt.legend()\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "910c08c0-f890-418f-9167-eb528a7ee319", "metadata": {}, "source": [ "4) Defining axes, grid and labels \n", "\n", "A readable figure should include titles on axes and the values it displays should be readable.\n", "\n", "a) The range\n", "\n", "The function axis([xmin, xmax, ymin, ymax]) defines the extent of the two axes.\n", "\n", "b) The grid \n", "\n", "For the figure to be more readable you can add a grid with the function grid.\n", "\n", "c) Title of the axes\n", "\n", "The functions xlabel('title of the x-axis') and ylabel('title of the y-axis') allow you to give titles to the axes.\n", "\n", "d) Title of the graph\n", "\n", "To add a title to the entire graph, you can use the function title.\n", "\n", "e) Ticks on the axes\n", "\n", "You can specify the ticks on the x-axis and on the y-axis with the functions xticks(list_of_ticks, list_of_tick_labels) and yticks(list_of_ticks, list_of_tick_labels).\n", "\n", "f) Changing the scale of axes\n", "\n", "It is sometimes useful to show data in logarithmic scale rather than in linear scale. To switch one axis from a linear scale (default) to a logarithmic scale, you can use the function xscale('log') or yscale('log'). You can then switch back to a linear scale using xscale('lin') and yscale('lin').\n", "\n", "\n", "\n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " Run the codes below which illustrates how to specify the axes of a figure. Add appropriate comments when required.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "146a1591-0c78-4995-b0c0-3603e66db864", "metadata": {}, "outputs": [], "source": [ "plt.figure()\n", "x = np.linspace(0, 2 * np.pi, 50)\n", "plt.plot(x, np.cos(x), label=r\"$\\cos(x)$\")\n", "plt.plot(x, np.sin(x), label=r\"$\\sin(x)$\")\n", "plt.axis([0, 2. * np.pi, -1.01, 1.01])\n", "plt.grid()\n", "plt.xlabel('x')\n", "plt.ylabel(r'$\\cos(x), \\ \\sin(x)$')\n", "plt.title('Trigonometric functions')\n", "plt.xticks([0., np.pi / 2., np.pi, 3. * np.pi / 2., 2 * np.pi], ['0', r'$\\dfrac{\\pi}{2}$', r'$\\pi$', r'$\\dfrac{3\\pi}{2}$', r'$2\\pi$'])\n", "plt.yticks([-1., 0., 1.]) # COMMENT REQUIRED\n", "plt.legend()\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "ec1d98c1-cb40-4e93-a626-fad40682bd5e", "metadata": {}, "outputs": [], "source": [ "plt.figure()\n", "x = np.linspace(-2, 2, 50)\n", "plt.plot(x, np.exp(x))\n", "plt.grid()\n", "plt.xlabel('x')\n", "plt.ylabel(r'$\\exp(x)$')\n", "plt.title('Exponential function in linear scale')\n", "plt.show()\n", "\n", "plt.figure()\n", "x = np.linspace(-2, 2, 50)\n", "plt.plot(x, np.exp(x))\n", "plt.grid()\n", "plt.axis([-2, 2, 0.1, 10])\n", "plt.yscale('log')\n", "plt.xlabel('x')\n", "plt.ylabel(r'$\\exp(x)$')\n", "plt.title('Exponential function in logarithmic scale')\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "997fa701-5cfe-4b1e-801b-608fcdb66793", "metadata": {}, "source": [ "5) Customizing drawings \n", "\n", "It is possible to customize the drawings of curves (add points, choose their shape, their color, their size, change the linestyle, change the linewidth, change the color of the line, etc.). There are two possible ways.\n", "\n", "\n", "\n", "\n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " Run the codes below which illustrates how to customize a plot. Add comments when required.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "76db8ef4-ed32-4983-b092-0894ecffe80b", "metadata": {}, "outputs": [], "source": [ "plt.figure()\n", "x = np.linspace(0, 2 * np.pi, 50)\n", "plt.plot(x, np.cos(x), 'r-o', label=r\"$\\cos(x)$\") # COMMENT REQUIRED\n", "plt.plot(x, np.sin(x), 'b--s', label=r\"$\\sin(x)$\") # COMMENT REQUIRED\n", "plt.plot(x, -np.cos(x), 'g-.^', label=r\"$-\\cos(x)$\") # COMMENT REQUIRED\n", "plt.plot(x, -np.sin(x), 'k:.', label=r\"$-\\sin(x)$\") # COMMENT REQUIRED\n", "plt.plot(x, np.tan(x), 'yv', label=r\"$\\tan(x)$\") # COMMENT REQUIRED\n", "plt.plot(x, -np.tan(x), 'c-*', label=r\"$-\\tan(x)$\") # COMMENT REQUIRED\n", "plt.plot(x, 1. / np.tan(x), 'm:d', label=r\"$\\mathrm{cotan}(x)$\") # COMMENT REQUIRED\n", "plt.axis([0., 2 * np.pi, -1.1, 1.1])\n", "plt.legend()\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "854c6995-b5a0-43c5-82f8-53bbbf3e9bf7", "metadata": {}, "outputs": [], "source": [ "plt.figure()\n", "x = np.linspace(0, 2 * np.pi, 50)\n", "plt.plot(x, np.cos(x), linestyle='-', marker='8', color='k', markeredgecolor=(0.4, 0.3, 0.5),\n", " markerfacecolor='#FF4D4D', linewidth=2, markersize=10, markeredgewidth=3) # COMMENT REQUIRED\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "d7f63ddf-ecb5-4a29-ac5a-b3ac5b38a546", "metadata": {}, "source": [ "6) Multiple graphics on a single figure \n", "\n", "The subplot() or subplot2grid functions allow several graphs to be displayed in the same window. Many configurations are possible: two graphs aligned in a row, or in a column, sharing the same x-axis or y-axis, etc.\n", "\n", "\n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " Run the code below which illustrates how to construct multiple adjacent graphics on the same figure. Add comments when required.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "0286760b-bb9b-4dd1-a845-ec976b39d16e", "metadata": {}, "outputs": [], "source": [ "plt.figure()\n", "x = np.linspace(0, 2 * np.pi, 50)\n", "plt.subplot(2, 1, 1) # COMMENT REQUIRED\n", "plt.plot(x, np.cos(x))\n", "plt.ylabel(r'$\\cos(x)$')\n", "plt.subplot(2, 1, 2) # COMMENT REQUIRED\n", "plt.plot(x, np.sin(x))\n", "plt.ylabel(r'$\\sin(x)$')\n", "plt.xlabel('x')\n", "plt.suptitle('Trigonometric functions') # COMMENT REQUIRED\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "37a07f49-1c4b-49ac-b854-fa07fbadd5dd", "metadata": {}, "outputs": [], "source": [ "plt.figure()\n", "x = np.linspace(0, 2 * np.pi, 50)\n", "plt.subplot2grid((2, 2), (0, 0)) # COMMENT REQUIRED\n", "plt.plot(x, np.cos(x))\n", "plt.ylabel(r'$\\cos(x)$')\n", "plt.subplot2grid((2, 2), (0, 1)) # COMMENT REQUIRED\n", "plt.plot(x, np.sin(x))\n", "plt.ylabel(r'$\\sin(x)$')\n", "plt.subplot2grid((2, 2), (1, 0), colspan=2) # COMMENT REQUIRED\n", "plt.plot(x, np.cos(x), label=r'$\\cos(x)$')\n", "plt.plot(x, np.sin(x), label=r'$\\sin(x)$')\n", "plt.ylabel(r'$\\cos(x),\\ \\sin(x)$')\n", "plt.xlabel('x')\n", "plt.suptitle('Trigonometric functions')\n", "plt.tight_layout() # COMMENT REQUIRED\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "27836e6c-fbd7-48b2-82cd-272cfd44f545", "metadata": {}, "source": [ "II. Scatter plots\n", "\n", "The function scatter plots only points but, unlike the function plot, allows you to change the size and colour of the points, and even to change the symbol for each pair $(x_i,\\, y_i)$. This allows you to plot points from different experiments using different symbols or colours. For more details, see §III.3.1 of the lecture notes.\n", "\n", "There are multiple ways of specifying colours.\n", "\n", "\n", "There are two ways of specifying sizes.\n", "\n", "\n", "\n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " Run the code below to understand how the function scatter works. Add appropriate comments when asked.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "cef8dac4-71df-4c11-90e9-adf5d5445d79", "metadata": {}, "outputs": [], "source": [ "x = np.random.random(10) # Generate a 1D array of size 10 with random numbers in the range [0,1) distributed uniformly (see TP5).\n", "y = np.random.random(10)\n", "plt.scatter(x, y, s=200., c='m') # COMMENT REQUIRED\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "d13f7a95-9b8c-4fd6-a9ce-0343b73869f6", "metadata": {}, "outputs": [], "source": [ "x = np.random.random(10)\n", "y = np.random.random(10)\n", "colors = np.random.random(10)\n", "sizes = np.pi * (15. * np.random.random(10)) ** 2\n", "plt.scatter(x, y, s=sizes, c=colors, cmap='viridis') # COMMENT REQUIRED\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "a556b2ee-54a5-4295-a327-7babbca960bd", "metadata": {}, "outputs": [], "source": [ "x = np.random.random(10)\n", "y = np.random.random(10)\n", "colors = np.random.random(10)\n", "sizes = np.pi * (15. * np.random.random(10)) ** 2\n", "plt.scatter(x, y, s=sizes, c=colors, cmap='hot', alpha=0.5) # COMMENT REQUIRED\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "68b4bcc0-8ec0-4496-975b-ffd08fbb10e3", "metadata": {}, "outputs": [], "source": [ "x = np.random.random(100)\n", "y = np.random.random(100)\n", "colors = np.random.random(100)\n", "sizes = np.pi * (15. * np.random.random(100)) ** 2\n", "scatter_plot = plt.scatter(x, y, s=sizes, c=colors, cmap='hot', alpha=0.5)\n", "plt.colorbar(scatter_plot, label='Intensity') # COMMENT REQUIRED\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "f97722f6-381e-4a5d-bbee-19ee7b98b0ad", "metadata": {}, "source": [ "III. Histograms\n", "\n", "There is a function hist which computes the histogram before plotting it. The function takes several arguments which are detailed in the examples below. For more details, see §III.3.2 of the lecture notes.\n", "\n", "\n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " Run the code below to understand how the function hist works. Add appropriate comments when asked.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "e66f24c1-aef8-4f3a-959a-7500c77f7850", "metadata": {}, "outputs": [], "source": [ "data = np.random.normal(size=100000) # Generates a 1D array of 100000 random numbers drawn from a Gaussian distribution of zero mean\n", "# and unit variance (see TP5).\n", "plt.figure()\n", "print(plt.hist(data)) # COMMENT REQUIRED" ] }, { "cell_type": "code", "execution_count": null, "id": "bc54584d-8453-444b-925a-5019c007acc6", "metadata": {}, "outputs": [], "source": [ "data = np.random.normal(size=100000)\n", "plt.figure()\n", "plt.hist(data, bins=100) # COMMENT REQUIRED" ] }, { "cell_type": "code", "execution_count": null, "id": "4fdd78d5-e29a-461f-a98a-c398911a6248", "metadata": {}, "outputs": [], "source": [ "data = np.random.normal(size=100000)\n", "plt.figure()\n", "plt.hist(data, bins=100, density=True) # COMMENT REQUIRED" ] }, { "cell_type": "code", "execution_count": null, "id": "5ad7d2a6-e4d8-422f-8df3-8c9f5a2be3f6", "metadata": {}, "outputs": [], "source": [ "data = np.random.normal(size=100000)\n", "plt.figure()\n", "plt.hist(data, bins=100, range=(-3, 3)) # COMMENT REQUIRED" ] }, { "cell_type": "code", "execution_count": null, "id": "097907ff-7eca-4d1e-8b8d-e5a163cc5368", "metadata": {}, "outputs": [], "source": [ "data = np.random.normal(size=100000)\n", "data2 = np.random.normal(size=100000)\n", "plt.figure()\n", "plt.hist(data, bins=100, density=True, facecolor='red', alpha=0.3)\n", "plt.hist(data2, bins=100, density=True, facecolor='green', alpha=0.3)\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "271f406e-66b2-4501-a1a0-d9250638fd25", "metadata": {}, "source": [ "IV. Plotting surfaces $z=f(x,y)$\n", "\n", "1) Contour lines\n", "\n", "One possible way of representing a function of two variables is to display its contour lines, i.e., the set of points $(x,\\,y)$ for a particular value of $z$. For example, if $f(x,y)$ is the electrostatic potential, then these contour lines are just the equipotentials. For more details, see §III.4 of the lecture notes.\n", "\n", "We focus on the case of a rectangular space (simpler). The procedure to generate such a plot is the following.\n", "1) Create two 1D arrays X and Y corresponding to the values of $x$ and $y$ respectively where you will compute the function $f$.\n", "2) From these two 1D arrays, create two 2D arrays XX and YY such that XX[i,j]=X[i] and YY[i,j]=Y[j]. Here, we are just creating a regular mesh and these arrays give, for each node $(i,\\,j)$ its $x$-coordinate and its $y$-coordinate.\n", "3) Compute the value of the function $f$ on all nodes of the regular mesh.\n", "4) Draw the contour lines using the function contour or the function contourf.\n", "\n", "\n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " Run the code below to understand how to generate a figure with the contour lines of a two-dimensional function. Add appropriate comments when asked.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "9f3a5674-5646-4c7b-b625-8613b3c6b9e9", "metadata": {}, "outputs": [], "source": [ "x = np.linspace(-1., 1., 51) # COMMENT REQUIRED\n", "y = np.copy(x) # COMMENT REQUIRED\n", "xx, yy = np.meshgrid(x, y) # COMMENT REQUIRED\n", "print(xx)\n", "sigma = 0.5\n", "\n", "\n", "def my_func(x, y): # COMMENT REQUIRED\n", " return np.exp(-((x - 0.5) ** 2 + y ** 2) / (2. * sigma ** 2)) + np.exp(-((x + 0.5) ** 2 + y ** 2) / (2. * sigma ** 2))\n", "\n", "\n", "z = my_func(xx, yy)\n", "plt.figure()\n", "plt.contour(xx, yy, z, cmap='jet') # COMMENT REQUIRED\n", "plt.xlabel('x')\n", "plt.ylabel('y')\n", "plt.title(r'Contour plots of $z=e^{-[(x-0.5)^2+y^2]/(2\\sigma^2)}+ e^{-[(x+0.5)^2+y^2]/(2\\sigma^2)}$ for $\\sigma=$' + str(sigma))\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "0fb04f01-80db-4e25-bd75-53988313684a", "metadata": {}, "outputs": [], "source": [ "x = np.linspace(-1., 1., 101) # COMMENT REQUIRED\n", "y = np.copy(x)\n", "xx, yy = np.meshgrid(x, y)\n", "sigma = 0.5\n", "\n", "\n", "def my_func(x, y):\n", " return np.exp(-((x - 0.5) ** 2 + y ** 2) / (2. * sigma ** 2)) + np.exp(-((x + 0.5) ** 2 + y ** 2) / (2. * sigma ** 2))\n", "\n", "\n", "z = my_func(xx, yy)\n", "plt.figure()\n", "plt.contour(xx, yy, z, cmap='jet')\n", "plt.xlabel('x')\n", "plt.ylabel('y')\n", "plt.title(r'Contour plots of $z=e^{-[(x-0.5)^2+y^2]/(2\\sigma^2)}+ e^{-[(x+0.5)^2+y^2]/(2\\sigma^2)}$ for $\\sigma=$' + str(sigma))\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "b7c02bc4-1284-4cd4-91ee-09792a829395", "metadata": {}, "outputs": [], "source": [ "x = np.linspace(-1., 1., 101)\n", "y = np.copy(x)\n", "xx, yy = np.meshgrid(x, y)\n", "sigma = 0.5\n", "\n", "\n", "def my_func(x, y):\n", " return np.exp(-((x - 0.5) ** 2 + y ** 2) / (2. * sigma ** 2)) + np.exp(-((x + 0.5) ** 2 + y ** 2) / (2. * sigma ** 2))\n", "\n", "\n", "z = my_func(xx, yy)\n", "plt.figure()\n", "contour_plot = plt.contour(xx, yy, z, cmap='jet')\n", "plt.clabel(contour_plot) # COMMENT REQUIRED\n", "plt.xlabel('x')\n", "plt.ylabel('y')\n", "plt.title(r'Contour plots of $z=e^{-[(x-0.5)^2+y^2]/(2\\sigma^2)}+ e^{-[(x+0.5)^2+y^2]/(2\\sigma^2)}$ for $\\sigma=$' + str(sigma))\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "0152958f-9a8e-4321-a75f-15ce3c1b154a", "metadata": {}, "outputs": [], "source": [ "x = np.linspace(-1., 1., 101)\n", "y = np.copy(x)\n", "xx, yy = np.meshgrid(x, y)\n", "sigma = 0.5\n", "\n", "\n", "def my_func(x, y):\n", " return np.exp(-((x - 0.5) ** 2 + y ** 2) / (2. * sigma ** 2)) + np.exp(-((x + 0.5) ** 2 + y ** 2) / (2. * sigma ** 2))\n", "\n", "\n", "z = my_func(xx, yy)\n", "plt.figure()\n", "plt.contourf(xx, yy, z, cmap='jet') # COMMENT REQUIRED\n", "contour_plot = plt.contour(xx, yy, z, colors='k') # COMMENT REQUIRED\n", "plt.clabel(contour_plot) # COMMENT REQUIRED\n", "plt.xlabel('x')\n", "plt.ylabel('y')\n", "plt.title(r'Filled contour plots of $z=e^{-[(x-0.5)^2+y^2]/(2\\sigma^2)}+ e^{-[(x+0.5)^2+y^2]/(2\\sigma^2)}$ for $\\sigma=$' + str(sigma))\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "126bd6cb-687f-410a-bd9b-273b2d272df4", "metadata": {}, "source": [ "2) Heat maps\n", "\n", "Another possible way of representing a function of two variables is to display its heat map, i.e., an image where the color of each pixel encodes the value of the function at the pixel position. For example, if $f(x,y)$ is the temperature field, then this image is just the map you see on the weather forecast everyday. For more details, see §III.4 of the lecture notes.\n", "\n", "We focus on the case of a rectangular space (simpler). The procedure to generate such a plot is the following.\n", "1) Create two 1D arrays X and Y corresponding to the values of $x$ and $y$ respectively where you will compute the function $f$.\n", "2) From these two 1D arrays, create two 2D arrays XX and YY such that XX[i,j]=X[i] and YY[i,j]=Y[j]. Here, we are just creating a regular mesh and these arrays give, for each node $(i,\\,j)$ its $x$-coordinate and its $y$-coordinate.\n", "3) Compute the value of the function $f$ on all nodes of the regular mesh.\n", "4) Draw the image using the function imshow or the function pcolormesh.\n", "\n", "\n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " Run the code below to understand how to generate a figure with the heat map of a two-dimensional function. Add appropriate comments when asked.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "e5cfed25-e4d1-4207-a523-140813bd6646", "metadata": {}, "outputs": [], "source": [ "x = np.linspace(-1., 1., 201)\n", "y = np.copy(x)\n", "xx, yy = np.meshgrid(x, y)\n", "sigma = 0.2\n", "\n", "\n", "def my_func(x, y):\n", " return np.exp(-((x - 0.5) ** 2 + y ** 2) / (2. * sigma ** 2)) + np.exp(-((x + 0.5) ** 2 + y ** 2) / (2. * sigma ** 2))\n", "\n", "\n", "z = my_func(xx, yy)\n", "plt.figure()\n", "heat_map = plt.imshow(z, extent=(-1, 1, -1, 1), cmap='viridis') # COMMENT REQUIRED\n", "plt.colorbar(heat_map, label='Temperature')\n", "plt.xlabel('x')\n", "plt.ylabel('y')\n", "plt.title(r'Heat map of $z=e^{-[(x-0.5)^2+y^2]/(2\\sigma^2)}+ e^{-[(x+0.5)^2+y^2]/(2\\sigma^2)}$ for $\\sigma=$' + str(sigma))\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "99b5ba5b-1e3f-401e-9cb7-319a6f93095d", "metadata": {}, "outputs": [], "source": [ "x = np.linspace(-1., 1., 201)\n", "y = np.copy(x)\n", "xx, yy = np.meshgrid(x, y)\n", "sigma = 0.2\n", "\n", "\n", "def my_func(x, y):\n", " return np.exp(-((x - 0.5) ** 2 + y ** 2) / (2. * sigma ** 2)) + np.exp(-((x + 0.5) ** 2 + y ** 2) / (2. * sigma ** 2))\n", "\n", "\n", "z = my_func(xx, yy)\n", "plt.figure()\n", "heat_map = plt.pcolormesh(xx, yy, z, cmap='viridis') # COMMENT REQUIRED\n", "plt.colorbar(heat_map, label='Temperature')\n", "plt.xlabel('x')\n", "plt.ylabel('y')\n", "plt.title(r'Heat map of $z=e^{-[(x-0.5)^2+y^2]/(2\\sigma^2)}+ e^{-[(x+0.5)^2+y^2]/(2\\sigma^2)}$ for $\\sigma=$' + str(sigma))\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "5f651714-c763-47d2-ae04-6863347d1747", "metadata": {}, "source": [ "V. Exercises\n", "\n", "Exercise 1:\n", "\n", "Write a program that plots the function $f(x) = \\dfrac{\\sin(x)}{x}\\sqrt{x^2+1}$ on the interval $[−6,\\, 6]$ with 121 calculated points. Make the plot such that it is understandable to anyone." ] }, { "cell_type": "code", "execution_count": null, "id": "27e82f44-15e8-4a8a-996b-a7fb5d46aa18", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "0a55ec5a-46b3-4cde-acab-622e939fad0d", "metadata": {}, "source": [ "Exercise 2:\n", "\n", "Write a program to visualize (via contour lines) the function $f(x, y) = \\ln(3x^2 + y^2 + 1)$ on the interval $[-2,\\,2]\\times[-7,\\,7]$ with a mesh size of 0.2 and 0.5 in the $x$ and $y$-directions respectively. Again, the figure must be understandable to anyone." ] }, { "cell_type": "code", "execution_count": null, "id": "81a47467-9671-47e5-a22b-54ce34c69b8d", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "8ed5444b-7ecf-4d55-a119-1002a8615579", "metadata": {}, "source": [ "Exercise 3:\n", "\n", "Write a program to represent the function $f(x) = e^{−\\mathrm{i}2\\pi x}e^{-x^2}$ on the interval $[−3,\\, 3]$ with 101 values of $x$ using a coloured scale to visualize the argument values. Again, the figure must be understandable to anyone." ] }, { "cell_type": "code", "execution_count": null, "id": "17a42ebf-e9fa-4d19-b7ff-05a9f8d65791", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "fc1d3e2c-a723-4686-b700-892aecb80d84", "metadata": {}, "source": [ "Exercise 4:\n", "\n", "The Padé approximant is a mathematical method of approximating an analytic function by a rational function, i.e., expressed as a ratio of two polynomials $P_n(x)/Q_m(x)$. This form of approximation is very useful in Physics when the analytical function has poles. By increasing the degrees $n$ and $m$ of the polynomials, the approximation improves.\n", "Two Padé approximants of the function $f(x) = \\dfrac{\\arctan(x)}{x}$ are proposed:\n", "$$\\dfrac{P_2(x)}{Q_2(x)}=\\dfrac{1+\\dfrac{4}{15}x^2}{1+\\dfrac{9}{15}x^2},$$\n", "$$\\dfrac{P_4(x)}{Q_4(x)}=\\dfrac{1+\\dfrac{7}{9}x^2+\\dfrac{64}{945}x^4}{1+\\dfrac{10}{9}x^2+\\dfrac{5}{21}x^4}.$$\n", "\n", "1) Write the two functions pade22() and pade44() which compute $\\dfrac{P_2}{Q_2}$ and $\\dfrac{P_4}{Q_4}$ respectively.\n", "\n", "2) Plot the function $f(x)$ on the interval $[−5,\\, +5]$ with 51 points as a solid line, and superimpose the two approximants as unconnected symbols. The figure must be understandable to anyone.\n", "\n", "3) Explain the error message you obtain, and propose a solution." ] }, { "cell_type": "code", "execution_count": null, "id": "80753966-0931-4239-827a-f9e47cb53fb3", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "e12aa5c3-0ed3-4fec-b4fc-3027c9855fae", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "3f651979-981a-436c-a1a1-df04834797dd", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "e2bc9c89-9fc1-47bb-a45a-b32dbcea097e", "metadata": {}, "source": [ "Exercise 5:\n", "\n", "The Mandelbrot set is a fractal defined as the set of points $c$ of the complex plane for which the sequence of complex numbers defined by the recurrence relation $z_{n+1} = z_n^2 + c$, with $z_0=0$, remains bounded. One can show that if the sequence of moduli of $z_n$ is strictly greater than 2 for a certain index $i_\\mathrm{div}$ then this sequence is increasing from this index, and tends to infinity.\n", "\n", "For a mesh of size $N \\times M$ in the complex plane, in the limits $[−1.4,\\, 1.4]$ on the complex axis and $[−2,\\, 0.8]$ on the real axis, create an image which shows the index $i_\\mathrm{div}$ from which the series diverges. This figure should be understandable to anyone.\n", "\n", "Only one loop is allowed (20 iterations are sufficient for the figure)." ] }, { "cell_type": "code", "execution_count": null, "id": "0f5365c4-fd61-4d5d-8199-0a17e905898f", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "3d763916-29bc-4a0b-911d-62ad7d5cdc89", "metadata": {}, "source": [ "Exercise 6:\n", "\n", "A continued fraction is a mathematical expression that can be writen as: $\\displaystyle q_0+\\dfrac{1}{q_1+\\dfrac{1}{q_2+\\dfrac{1}{q_3+\\dots}}}$.\n", "\n", "This representation can be used to demonstrate the irrationality of certain numbers ($\\pi$, $e$) when the continued fraction is infinite. In diophantine approximation, continued fractions provide excellent approximations of reals by rationals.\n", "\n", "Let $x$ be any real number. It can be written as $x = q_0 + e_0$ where $q_0$ is an integer, the floor of $x$ (integer part or integral part, i.e., $q_0 = \\lfloor x\\rfloor$), and $e_0$ is the remainder, so the fractional part ($e_0 = x − \\lfloor x\\rfloor$).\n", "\n", "By construction $e_0<1$, so it can be written as $1/e_0 = q_1 + e_1 = \\lfloor(1/e_0)\\rfloor + e_1$ with $0 \\leq e_1 < 1$. Similarly,\n", "$1/e_1 = q_2 + e_2 = \\lfloor(1/e_1)\\rfloor + e_2$, etc. We then establish recurrence relations for $n \\geq 0$:\n", "$$\\begin{cases}\n", "q_{n+1}=\\Bigl\\lfloor\\dfrac{1}{e_n}\\Bigr\\rfloor,\\\\\n", "e_{n+1}=\\dfrac{1}{e_n}-q_{n+1}=\\dfrac{1}{e_n}-\\Bigl\\lfloor\\dfrac{1}{e_n}\\Bigr\\rfloor.\n", "\\end{cases}$$\n", "The sequence of incomplete quotients $q_n$, called the canonical representation, is given in square brackets: $[q_0,\\,q_1,\\,q_2,\\dots,\\, q_n]$.\n", "For example $\\dfrac{15 625}{6842}$ has $[2,\\,3,\\,1,\\,1,\\,9,\\,1,\\,1,\\,48]$ as a canonical representation.\n", "\n", "1) Write the function canonical_rep which calculates and returns the $n$ significant values of the sequence $q_n$ as a function of $x$ and $\\epsilon$ given as arguments, where $\\epsilon$ is the precision to be achieved, such that $e_n\\leq \\epsilon$. You can use the example given above to test your program. Apply it also to $x = \\exp(1)$ with a precision of $\\epsilon=10^{-5}$. Your function should also take a maximum number of iterations (by default equal to 20) as an input in case of irrational numbers.\n", "\n", "2) Write the function cont_frac which calculates and returns the continued fraction approximation of $x$ given as arguments. The other arguments given to the function must be the precision $\\epsilon$ and the maximum number of iterations for the calculation of the canonical representation.\n", "\n", "Hint: The continued fraction approximation corresponds to the first element $\\alpha_0$ of the sequence $\\alpha_i$, defined by the following recurrence relation for decreasing indices: $\\alpha_i = q_i + 1/\\alpha_{i+1}$ for $i = 0,\\dots, n-1$ and $\\alpha_n = q_n$.\n", "\n", "3) Plot the difference between the continued fraction and $x = \\exp(1)$ as a function of the size of the canonical representation $n$ for $n=1,\\dots,20$." ] }, { "cell_type": "code", "execution_count": null, "id": "88e1cc94-4a5d-4d33-8232-7551f2880ed5", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "41e3045d-f6a5-4834-8523-7ffd778ac0b3", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "222dac5b-5525-4cc4-b5b4-c41f6891e3d2", "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.13.5" } }, "nbformat": 4, "nbformat_minor": 5 }