{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# **Interactive trigonometric functions**\n", "\n", "In this notebook, we will show you how to develop an interactive notebook to demonstrate trigonometric functions. We are using the \"matplotlib\" package to create the main figure and widgets from \"ipywidgets\" as controllers." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **1. Import all the required Python packages**\n", "\n", "

\n", " Here, we need to import all the functions from different packages. \n", " \"Matplotlib\" is used to plot the figure. \"Numpy\" is for computing \n", " the trigonometric function. \"Ipywidgets\" are needed to create the widgets.\n", "

\n", "\n", "

\n", " The widgets are graphical control elements, which allow the users to \n", " interact with the figure. \"Ipywidgets\" is a Python package, which offers \n", " widgets for the Jupyter notebook and JupyterLab. It has many widgets such \n", " as slider, checkbox, dropdown, button, etc. In this notebook, all of the \n", " widgets are from the \"ipywidgets\" package. Please read more at the homepage of the \n", " \"ipywidgets\" package.\n", "

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib widget\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from ipywidgets import IntSlider, Dropdown, Box, HBox, VBox, Layout, ColorPicker, Button, Text" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **2. Deploy widgets** \n", "\n", "

\n", " Before development, we need to think about what functionality we want \n", " to offer the users. For the trigonometric function, we want to let the user \n", " select the parameters k and w in the function $sin(kx+w)$. We can use two sliders to achieve this: one for parameter k and another for parameter w. Users should also be able to choose between a sine \n", " or cosine function via a dropdown menu. We also want to make it possible to change \n", " the color of the plotted line. The color picker widget can help us with this \n", " functionality. Finally, we can use a text box to allow for specification of the title of the plot.\n", " Here, we define all the widgets through use of the code shown below.\n", "

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Two integral sliders for the parameter k and w\n", "k_slider = IntSlider(value=0, min=-10, max=10, description = \"$k$\", continuous_update=False)\n", "w_slider = IntSlider(value=0, min=-10, max=10, description = \"$w$\", continuous_update=False)\n", "\n", "#Color picker for the color of the function line\n", "color_picker = ColorPicker(concise=False, description='Pick a color for plot', value='red', disabled=False)\n", "\n", "#Text box for inputting the title of the figure\n", "title_widget = Text(value='Input title name here', description='Figure title:', disabled=False)\n", "\n", "#Dropdown to select sine or cosine function\n", "type_widget = Dropdown(options=(\n", " (\"Sine function\",\"sin\"),\n", " (\"Cosine function\",\"cos\"), \n", " ), \n", " description = \"function type\", continuous_update=False, layout=Layout(width='250px'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **3. Get the x, y data for plot**\n", "\n", "

\n", " Define a function to compute the x and y data arrays, which will be used for plotting the graphs in the figure. \n", "

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def get_numerical_array(k_value, w_value, function_type):\n", " x = np.linspace(0, 2 * np.pi, 2000)\n", " if function_type == \"sin\":\n", " y = np.sin(k_value*x + w_value)\n", " elif function_type == \"cos\":\n", " y = np.cos(k_value*x + w_value)\n", " return x, y " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **4. Initalize the figure**\n", "\n", "

\n", " In this notebook, we used \"matplotlib\" for plotting the figure. \n", " Please read the instructions for usage of matplotlib on the homepage of the\n", " \"matplotlib\" package.\n", "

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "\n", "#Set x, y labels of the figure\n", "ax.set_xlabel(\"X\")\n", "ax.set_ylabel(\"Y\")\n", "\n", "#Set x, y limit of the figure\n", "ax.set_xlim(0, 2*np.pi)\n", "ax.set_ylim(-1, 1)\n", "\n", "#Turn on the grid for the figure\n", "ax.grid()\n", "\n", "#Define the function line, which allows to change the data and color later by the widgets\n", "line, = ax.plot([], [], color = color_picker.value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **5. Widget events**\n", "\n", "

\n", " We need to connect the widgets with the plot by using so-called \"widget events\". \n", " Here, we used the \"observe\" method of the widgets. To expand upon what is happening in the code below: when we \n", " move the k or w slider, this action shall trigger the execution of the \"callback\" function \"on_parameters_change\". \n", " Inside the \"on_parameters_change\" function, the x and y data arrays are recomputed using the new values of k and w and the figure subsequently updated.\n", "

\n", "\n", "

\n", " More information regarding widget events can be found at:\n", " Widget Events\n", "

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Define callback function for the parameters changing\n", "def on_parameters_change(change):\n", " x, y = get_numerical_array(k_slider.value, w_slider.value, type_widget.value)\n", " line.set_data(x, y)\n", "\n", "#Define callback function for the color changing\n", "def on_color_change(change):\n", " line.set_color(color_picker.value)\n", " \n", "#Define callback function for the title changing\n", "def on_title_change(change):\n", " ax.set_title(title_widget.value)\n", " \n", "#Use observe method of the widgets\n", "k_slider.observe(on_parameters_change, names='value', type='change')\n", "w_slider.observe(on_parameters_change, names='value', type='change')\n", "type_widget.observe(on_parameters_change, names='value', type='change')\n", "color_picker.observe(on_color_change, names='value', type='change')\n", "title_widget.observe(on_title_change, names='value', type='change')\n", "\n", "on_parameters_change(None)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **6. Display the widgets**\n", "\n", "

\n", " Use the \"VBox\" and \"HBox\" to arrange the layout of the widgets. \n", " \"VBox\" arranges all widgets in one column. \"HBox\" arranges all widgets in one row.\n", "

\n", "\n", "

\n", " You can read more about the layout of widgets at:\n", "Layout and styling of Jupyter widgets\n", "

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "box1 = VBox([k_slider, w_slider, type_widget], layout=Layout(width='400px'))\n", "box2 = VBox([color_picker, title_widget], layout=Layout(width='400px'))\n", "\n", "display(HBox([box1, box2]))\n", "display(fig)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "(**Note**: the figure and widgets above are not \"active\" on the website, but would be fully interactive and dynamic if you run the code in Jupyter.)" ] }, { "cell_type": "code", "execution_count": null, "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.8.8" } }, "nbformat": 4, "nbformat_minor": 4 }