diff --git a/TeachingExamples/Demonstrations.ipynb b/TeachingExamples/Demonstrations.ipynb index 27f59d2..36e4352 100644 --- a/TeachingExamples/Demonstrations.ipynb +++ b/TeachingExamples/Demonstrations.ipynb @@ -1,89 +1,89 @@ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ - "# Demonstrations - Using digital artefacts to improve your explanations\n", + "# Virtual demonstrations - Using digital artefacts to illustrate explanations\n", "\n", "Sometimes, showing students a phenomenon using a demonstration in class is much simpler than explaining it. For instance, describing only with words the movement of a ball when it is thrown up in the air vertically can be quite lengthy and hard to grasp for students. Whereas throwing up a real ball in the air clearly illustrates what happens. Classroom demonstrations are among students’ favorite elements of introductory science classes and they are well known from teachers to stimulate students’ interest and motivation. \n", "Jupyter Notebooks allow you to design very easily **virtual demonstrations** to show students **things that you could not demonstrate in real life**. \n", "\n", "But how to ensure that your demonstrations are **more than just entertainment**?\n", "\n", "## Essential ingredients of virtual demonstrations\n", "### Using \"prediction questions\"\n", "\n", "Catherine Crouch and her colleagues at Harvard University (C. Crouch, Fagen, Callan, & Mazur, 2004) were interested in knowing whether the demonstrations traditionally used in introductory science courses were really helping students to learn. More specifically, they wanted to know if there were ways to use classroom demonstrations that would help students better understand than others. \n", "So they tested three different ways of using demonstrations in a large introductory physics class (133 students), and assessed students' understanding of the underlying concepts at the end of the semester.\n", "\n", "It turned out that the students who just observed the demonstrations and listened to the explanation from the teacher displayed no greater understanding of the underlying concepts than those who did not see the demonstrations at all. However, *when students were engaged in predicting the outcome of the demonstrations before seing them*, results on the test showed a significantly higher rate of correct explanations compared to both those who just saw the demo and those who didn’t see the demo. This type of result has been reproduced consistently, showing that **having students predict the outcome of a demonstration before doing it can really make your demonstrations more effective** than just entertainment...\n", "\n", "### Including multiple representations\n", "\n", "\n", "TODO multiple representations\n", "\n", "## Examples of virtual demonstrations for teaching\n", "\n", "You can show students virtual demonstrations in Jupyter Notebooks in class. As seen above, asking your students prediction questions before showing them the demo will make your virtual demonstrations more effective.\n", "Below are examples of simple virtual demonstrations which include prediction questions in different formats.\n", "\n", "Making the virtual demonstrations available to the students can be a good idea.\n", "By transforming them into exercises, which include questions and instructions on what to observe in the demo you will ensure students use them effectively.\n", "Below are examples of simple virtual demonstrations turned into homework exercises.\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
In classHomework exercise
Suspended objectsThis example includes an interactive prediction question in the form of a MCQ that can be asked to students using the notebook or any other technology of your choice (raise of hands, clickers, etc.)The prediction question makes a nice quiz for students
Falling objectsIn this example, the prediction question is paper-based, no technology involved other than the notebook!This example illustrates the idea of a notebook \"to complete\", in which students write their own explanations and observations.
\n", " This example contains a coding exercise allowing students to get a deeper understanding of how simulations work and develop their computational thinking
\n", "\n", "\n", "## Bibliography\n", "\n", "Crouch, C., Fagen, A. P., Callan, J. P., & Mazur, E. (2004). Classroom demonstrations: Learning tools or entertainment? American Journal of Physics, 72(6), 835–838. \n", "https://aapt.scitation.org/doi/10.1119/1.1707018\n", "\n" ] } ], "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.6.8" } }, "nbformat": 4, "nbformat_minor": 2 } diff --git a/TeachingExamples/FallingObjects-computational.ipynb b/TeachingExamples/FallingObjects-computational.ipynb new file mode 100644 index 0000000..237f416 --- /dev/null +++ b/TeachingExamples/FallingObjects-computational.ipynb @@ -0,0 +1,192 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Falling objects - computational exercise\n", + "\n", + "## 1. Understand the \"Falling objects\" virtual lab\n", + "\n", + "A. First, do the [exercise with the \"Falling objects\" virtual lab](FallingObjects-exercise.ipynb)\n", + "\n", + "B. Draw a diagram representing the different elements of the code [available in this python file](lib/suspendedobjects.py). \n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "07b23378e6f84eca8de8c7490444b8c3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(Output(layout=Layout(margin='2px 6px')), HBox(children=(VBox(children=(HBox(children=(Label(val…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%matplotlib inline\n", + "from lib.fallingobjects import *\n", + "FallingObjectsLab();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Extend the virtual lab\n", + "\n", + "You can extend the virtual lab by redefining the following elements:\n", + "* The list of the objects available in the lab so that you can add properties to these objects\n", + "* The functions representing the equations of motion\n", + " \n", + "Redefine these elements to implement a quadratic model of air friction in the virtual lab." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "###--- Static list of objects with which we can experiment.\n", + "# Objects come with a number of attributes, of which:\n", + "# - a name and a color : mandatory so that the virtual lab executes\n", + "# - a mass and a friction coefficient : used by the functions implementing the motion equations, can be replaced or renamed \n", + "# as long as the three functions accel_time_withair, veloc_time_withair and height_time_withair are redefined\n", + "objects_with_k = [{\n", + " 'name':'Bowling ball',\n", + " 'mass':5.0,\n", + " 'k': (6*np.pi*0.11) * 1.8*10**-5,\n", + " 'color':'#DC143C'\n", + " },{\n", + " 'name':'Tennis ball',\n", + " 'mass':0.0567,\n", + " 'k': (6*np.pi*0.032) * 1.8*10**-5,\n", + " 'color':'#2E8B57'\n", + " },{\n", + " 'name':'Ping-pong ball',\n", + " 'mass':0.0027,\n", + " 'k': (6*np.pi*0.02) * 1.8*10**-5,\n", + " 'color':'#FF4500'\n", + " },{\n", + " 'name':'Balloon',\n", + " 'mass':0.013,\n", + " 'k': 0.02,#(6*np.pi*0.28) * 1.8*10**-5,\n", + " 'color':'#000080'\n", + "}]\n", + "\n", + "## Utility function to print objects nicely\n", + "def object_string(obj):\n", + " return '{!s}:\\n mass = {} kg \\n friction coeff. = {:.2e}'.format(obj.name, obj.mass, obj.k)\n", + "\n", + "\n", + "###--- Functions representing the equations of the movement as functions of time and the problem parameters\n", + "def accel_time_withair(obj, g, h_0, v_0, t):\n", + " # TODO to replace!! -->\n", + " lamb = obj.k / obj.mass\n", + " return -g * np.exp(- lamb * t)\n", + " # <--\n", + "\n", + "def veloc_time_withair(obj, g, h_0, v_0, t):\n", + " # TODO to replace!! -->\n", + " lamb = obj.k / obj.mass\n", + " return (v_0 + (g / lamb)) * np.exp(- lamb * t) - (g / lamb)\n", + " # <--\n", + "\n", + "def height_time_withair(obj, g, h_0, v_0, t):\n", + " # TODO to replace!! -->\n", + " lamb = obj.k / obj.mass\n", + " return (1 / lamb) * (v_0 + (g / lamb)) * (1 - np.exp(- lamb * t)) - (g / lamb) * t + h_0\n", + " # <--" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Test your functions by executing the following cell:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "30e74080b95643999e5d70fc3957234a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(Output(layout=Layout(margin='2px 6px')), HBox(children=(VBox(children=(HBox(children=(Label(val…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "FallingObjectsLab(objects = objects_with_k, \n", + " accel_time = accel_time_withair, veloc_time = veloc_time_withair, height_time = height_time_withair);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## References : \n", + "\n", + "frottements linéaires vs. quadratiques : \n", + "\n", + "http://www.physagreg.fr/mecanique/m12/M12-chute-libre-frottements.pdf\n", + "\n", + "https://femto-physique.fr/mecanique/problemes-de-chute.php\n", + "\n", + "equations avec frottements linéaires :\n", + "\n", + "https://fr.wikipedia.org/wiki/Frottement_fluide\n", + "\n", + "equations avec frottements quadratiques :\n", + "\n", + "http://hyperphysics.phy-astr.gsu.edu/hbase/Mechanics/fallq.html\n", + "\n", + "https://studylibfr.com/doc/4875224/chute-libre-avec-frottement---gilles-auriol\n", + "\n", + "https://fr.wikipedia.org/wiki/Chute_avec_r%C3%A9sistance_de_l%27air" + ] + } + ], + "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.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/TeachingExamples/FallingObjects-demo.ipynb b/TeachingExamples/FallingObjects-demo.ipynb index 1b26c62..377a3af 100644 --- a/TeachingExamples/FallingObjects-demo.ipynb +++ b/TeachingExamples/FallingObjects-demo.ipynb @@ -1,180 +1,172 @@ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "This notebook is about demonstrating:\n", - "* prediction questions\n", - "* observation questions\n", + "* using **different types of questions** to engage students with the virtual demonstration\n", + "* using the type of **visualisations** that students will be asked to use **when solving similar problems**\n", "\n", - "The example chosen is voluntarily *simple* so that anyone can understand what is illustrated and focus the pedagogical features of the example." + "The example chosen is voluntarily *simple* so that anyone can understand what is illustrated and focus the pedagogical features of the example.\n", + "\n", + "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "---\n", "# Falling objects\n", "\n", "## In-class scenario\n", "\n", "### Problem\n", "\n", "We **drop** an object from a given height with **no initial velocity**. Just like an apple would fall from a tree. \n", "We consider the movement of the object, **ignoring resistance from the air**.\n", "\n", "### Questions\n", "1. Ask the following **prediction questions** to students - make sure they write down their answers on a piece of paper:\n", " * Which object would reach the ground first: a bowling ball (5 kg) or a tennis ball (0.05 kg)?\n", " * Why? Describe in words your explanation for this behavior.\n", " * Sketch your prediction for the *height* of the object as a function of time. Describe in words what this graph means.\n", " * Sketch your prediction for the *velocity* of the object as a function of time. Describe in words what this graph means.\n", " * Sketch your prediction for the *acceleartion* of the object as a function of time. Describe in words what this graph means.\n", "\n", "\n", "2. **Run the demo** and ask the following **observation questions** :\n", - " * When does the bowling ball reaches the ground (time in seconds)?\n", - " * When does the tennis ball reaches the ground (time in seconds)?\n", - " * When does the ostrich feather reaches the ground (time in seconds)?\n", - " * What if we plot multiple objects at the same time?\n", + " * When does the each object reaches the ground (time in seconds)?\n", + " * What do you observe when we plot multiple objects at the same time?\n", " * What can you conclude from this experiment?\n", "\n", "\n", "3. Provide the explanation (e.g. solving the problem on the board), and have students compare their explanation with your own explanation. \n", "Then ask the following **explanation questions**:\n", - " * What happens if we don't ignore the resistance from the air?\n", - " * Why can we ignore resistance from the air in this case? \n", - " * What are the criteria to decide when we can ignore it or not when solving problems?\n", + " * What happens if we don't ignore the resistance from the air? -- here you can use the virtual lab to show the effect of air resistance\n", + " * What are the criteria to decide when we can ignore resistance from the air or not when solving problems?\n", "\n", "\n", "4. For additional impact, you can show an excerpt of the video below, which demonstrates how a bowling ball and ostrich feathers fall in a vacuum chamber" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Virtual demo" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "from lib.fallingobjects import *\n", + "\n", "FallingObjectsLab();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*If you wonder how the virtual lab works and would like to see the code, [you can have a look at it at the end of this notebook](#How-does-the-virtual-demo-work%3F).*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Video" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import YouTubeVideo\n", "YouTubeVideo('E43-CfukEgs', 560, 315)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "# How does the virtual demo work?\n", "\n", "You can have a look at the code of the virtual demo by [opening this python file](lib/fallingobjects.py). \n", "\n", "## Use of the virtual demo\n", "\n", "Execute the cell below to see the documentation:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "FallingObjectsLab?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Utility computation functions\n", "\n", - "By executing the following three cells, you will see the code of the three functions used to compute the movement equations for the falling objects. \n", + "You can see the code of the functions used to compute the movement equations for the falling objects using the same kind of syntax. \n", + "Below are two examples showing the code of the function computing height without and with air resistance.\n", + "\n", "These functions can be redefined and given as parameters when initializing the lab." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "accel_time??" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "veloc_time??" + "height_time??" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "height_time??" + "height_time_withair??" ] } ], "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.6.8" } }, "nbformat": 4, "nbformat_minor": 2 } diff --git a/TeachingExamples/FallingObjects-exercise.ipynb b/TeachingExamples/FallingObjects-exercise.ipynb index e54dbea..188086b 100644 --- a/TeachingExamples/FallingObjects-exercise.ipynb +++ b/TeachingExamples/FallingObjects-exercise.ipynb @@ -1,319 +1,318 @@ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "This notebook is about demonstrating:\n", - "* prediction questions\n", - "* observation questions\n", - "* hiding code\n", + "* How to make a **demonstration available to students** in the form of an **exercise including different types of questions**\n", + "* Using notebook cells to encourage students to **take notes** when they use a virtual demonstration\n", "\n", "The example chosen is voluntarily *simple* so that anyone can understand what is illustrated and focus the pedagogical features of the example.\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Falling objects \"apple \n", "\n", "## The problem \n", "We **drop** an object from a given height with **no initial velocity**. Just like an apple would fall from a tree. \n", "We consider the movement of the object, **ignoring resistance from the air**.\n", "\n", " \n", "\n", "## Initial questions\n", "\n", "Answer the following questions _before_ using the virtual lab.\n", "\n", "**Question 1:** Which object would reach the ground first: a bowling ball (5 kg) or a tennis ball (0.05 kg)? Write down your answer in the cell below." ] }, { "cell_type": "raw", "metadata": {}, "source": [ "### Type your answer here." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Question 2:** Why? In the cell below, describe in words your explanation for this behavior." ] }, { "cell_type": "raw", "metadata": {}, "source": [ "### Type your answer here." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Tip:* In physics, as in many disciplines, sketching your ideas can really help you figure out problems. \n", "It might be a good idea to take a piece of paper and sketch what you think the following variables will look like as a function of time: the *height* of the object, the *velocity* of the object and the *acceleration* of the object." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "\n", "## Virtual lab\n", "The virtual demonstration below illustrates the movement of different objects. \n", "Execute the cell below to launch the virtual demonstration, then *answer the questions below*." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "from lib.fallingobjects import *\n", - "FallingObjectsLab();" + "FallingObjectsLab(show_withair=False);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "\n", "**Question 1:** Choose an initial height that will be the same for all the objects you will observe, e.g. 5 meters. \n", "When does the each object reaches the ground? \n", "Note down the time in seconds below." ] }, { "cell_type": "raw", "metadata": {}, "source": [ "### Object 1 reaches the ground at:\n", "### Object 2 reaches the ground at:\n", "### Object 3 reaches the ground at:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Tip:* Actually, the interactive figure allows you to plot the movement of several objects simultaneously by maintaining the 'ctrl' key selected while clicking with your mouse on the objects you want to display. \n", "Try to select several objects to display simultaneously.\n", "\n", "**Question 2:** What can you conclude from this experiment? \n", "*If you wonder how the virtual lab works and would like to see the code, [you can have a look at it at the end of this notebook](#How-does-the-virtual-lab-work%3F).*" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "### Type your answer here." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "\n", "## Synthesis\n", "\n", "**Question 1:** How does your own explanation compare with the explanation provided below?" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "### Type your answer here." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Problem analysis\n", "\n", "\n", "We are looking for the time at which the object will reach the ground. Therefore *we are looking for an equation giving us the height of the object as a function of time*.\n", "\n", "We know the initial height and velocity of the object, as well as its mass. \n", "In addition, if we ignore the friction from air, we know that the only force applied on the object is the weight: $\\vec F = m \\vec g$\n", "\n", "#### Movement of the object\n", "Since there is only one force involved, it seems quite straightforward to use Newton's second law: $\\sum \\vec F = m \\vec a$\n", "\n", "With the weight the only force on the object, we get: $\\vec F = m \\vec a$ \n", "Using the expression of the weight it gives us: $m \\vec g = m \\vec a$ \n", "Therefore the movement of the object is described by $\\vec a = \\vec g$.\n", "\n", "To get the equation of acceleration as a function of time, we project onto our coordinate system: $a = -g$, therefore $a(t) = -g$. \n", "This means that the ball is under **constant acceleration**.\n", "\n", "From there we can get the equations for velocity and height by integrating successively: \n", "$\\left\\{\\begin{matrix} a(t) = -g \\\\ v(t) = -g\\,t + v_0 \\\\ h(t) = -\\frac{1}{2}\\,g\\,t^2 + v_0\\,t + h_0\\end{matrix}\\right. $\n", "\n", "The above equations have the following parameters:\n", "* the initial height $h_0$ from which the object is dropped\n", "* the initial velocity of the object $v_0$, with $v_0 = 0$ when the object is dropped with no initial velocity\n", "* and of course the acceleration due to gravity $g$\n", "\n", "#### Conclusion\n", "We see clearly that **the mass $m$ of the object plays no role at all in the equations of the movement**.\n", "\n", "**Question 2:** What happens if we don't ignore the resistance of the air?" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "### Type your answer here." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Question 3:** Why is it reasonable to ignore the resistance of the air in this situation? \n", "List the criteria that you could you to decide if resistance from the air can be ignored or not when solving a problem." ] }, { "cell_type": "raw", "metadata": {}, "source": [ "### Type your answer here." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "\n", " \n", "\n", "---\n", "\n", "## How does that look in real life?\n", "\n", "The following video demonstrates how a bowling ball and ostrich feathers fall in a vacuum chamber, thus illustrating how what we have seen so far looks in the real world." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import YouTubeVideo\n", "YouTubeVideo('E43-CfukEgs', 560, 315)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "\n", "---\n", "## How does the virtual lab work?\n", "\n", "You can have a look at the code of the virtual lab by [opening this python file](lib/fallingobjects.py). \n", "By executing the following three cells, you will see the code of the three functions used to compute the movement equations for the falling object.\n", "\n", "#### Code of $a(t) = -g$\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "accel_time??" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Code of $v(t) = -g\\,t + v_0$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "veloc_time??" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Code of $h(t) = -\\frac{1}{2}\\,g\\,t^2 + v_0\\,t + h_0$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "height_time??" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "\n", "---\n", "\n", "## Other resources on the web\n", "\n", "Detailed explanations with examples on falling objects: https://opentextbc.ca/physicstestbook2/chapter/falling-objects/\n", "\n", "Impact of air resistance on falling objects (in French): http://www.physagreg.fr/mecanique/m12/M12-chute-libre-frottements.pdf" ] } ], "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.6.8" } }, "nbformat": 4, "nbformat_minor": 2 } diff --git a/TeachingExamples/SuspendedObjects-demo.ipynb b/TeachingExamples/SuspendedObjects-demo.ipynb index 6da8587..a03263d 100644 --- a/TeachingExamples/SuspendedObjects-demo.ipynb +++ b/TeachingExamples/SuspendedObjects-demo.ipynb @@ -1,145 +1,148 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook is about demonstrating:\n", + "* using **different types of questions** to engage students with the virtual demonstration\n", + "* using **different types of visualizations** to help students understand the phenomena\n", + "\n", + "The example chosen is voluntarily *simple* so that anyone can understand what is illustrated and focus the pedagogical features of the example.\n", + "\n", + "---" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Suspended objects\n", "\n", "## In-class scenario\n", "\n", "### Problem\n", "\n", "\n", "We consider a clothesline made of two poles and a cable. \n", "The cable is fixed on one pole. A pulley on the other pole allows to attach a counterweight to pull the cable taut.\n", "\n", "### Questions\n", "\n", "1. Ask the following **prediction question** to students:\n", - " * Estimate which counterweight allows to suspend wet jeans (3kg) on the cable so that the cable is taut as shown on the diagram: 1,5 kg, 3 kg, 6 kg, 20 kg, 50 kg or more\n", + " * Estimate which counterweight allows to suspend wet jeans (3kg) on the cable so that the cable is taut as shown on the diagram?\n", + " * 1,5 kg\n", + " * 3 kg\n", + " * 6 kg\n", + " * 20 kg\n", + " * 50 kg or more\n", " * Why? Describe in words your explanation for this behavior.\n", - " \n", - "#### TODO: here, replace by interactive polling question!!!\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from ipywidgets import interact\n", - "print(\"Estimate which counterweight allows to suspend wet jeans (3kg) on the cable so that the cable is taut as shown on the diagram: \")\n", - "f = lambda w:str(w)\n", - "interact(f, w=['1,5 kg', '3 kg', '6 kg', '20 kg', '50 kg or more']);" + " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2. Run the demo and ask the following **observation questions** :\n", " * What it the height of the point at which the jeans are suspended for a counterweight of 3kg?\n", " * What it the height of the point at which the jeans are suspended for a counterweight of 6kg?\n", " * What it the height of the point at which the jeans are suspended for a counterweight of 20kg?\n", " * What it the height of the point at which the jeans are suspended for a counterweight of 50kg?\n", " * What can you conclude from this experiment?\n", "\n", "\n", "3. Provide the explanation (e.g. solving the problem on the board), and have students compare their explanation with your own explanation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Virtual demo" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "from lib.suspendedobjects import *\n", - "\n", - "SuspendedObjectsLab(m_object = 3);" + "SuspendedObjectsLab();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*If you wonder how the virtual lab works and would like to see the code, [you can have a look at it at the end of this notebook](#How-does-the-virtual-lab-work%3F).*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "# How does the virtual demo work?\n", "\n", "You can have a look at the code of the virtual demo by [opening this python file](lib/suspendedobjects.py). \n", "\n", "## Use of the virtual demo\n", "\n", "Execute the cell below to see the documentation:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "SuspendedObjectsLab?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Utility computation function\n", "\n", "By executing the following cell, you will see the code of the function used to compute the angle that the line makes with the horizon depending on the masses of the object and the counterweight. \n", "This function can be redefined and given as parameter when initializing the lab." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "get_angle_from_masses??" ] } ], "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.6.8" } }, "nbformat": 4, "nbformat_minor": 2 } diff --git a/TeachingExamples/SuspendedObjects-exercise.ipynb b/TeachingExamples/SuspendedObjects-exercise.ipynb index b3e321c..9542ede 100644 --- a/TeachingExamples/SuspendedObjects-exercise.ipynb +++ b/TeachingExamples/SuspendedObjects-exercise.ipynb @@ -1,204 +1,205 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook is about demonstrating:\n", + "* making a demonstration available to students in the form of an exercise including **auto-corrected quizzes**\n", + "* using **different types of visualizations** to help students understand the phenomena\n", + "\n", + "The example chosen is voluntarily *simple* so that anyone can understand what is illustrated and focus the pedagogical features of the example.\n", + "\n", + "---" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Suspended objects\n", "\n", "## The problem\n", "\n", "\n", "We consider a clothesline made of two poles and a cable.\n", "The cable is fixed on one pole. A pulley on the other pole allows to attach a counterweight to pull the cable taut.\n", "\n", "## Initial questions\n", "\n", "**Question:** Estimate which counterweight allows to suspend wet jeans (3kg) on the cable so that the cable is taut as shown on the diagram below? \n", "\n", "#### TODO: here, replace by auto-corrected quiz!!!\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Virtual lab" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "from lib.suspendedobjects import *\n", "SuspendedObjectsLab();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "\n", "*If you wonder how the virtual lab works and would like to see the code, [you can have a look at it at the end of this notebook](#How-does-the-virtual-lab-work%3F).*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Conceptual explanation\n", "\n", "TODO" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Analytic explanation\n", "\n", "### Hypotheses and simplifications:\n", "\n", "* the jeans are exactly mid-way between the poles so the tension is equal on both sides of the cable\n", - "* we represent the jeasn by the point at which they are suspended\n", - "* the cable is considered as rigid (not bended)\n", + "* we represent the jeans by the point at which they are suspended\n", + "* the cable is considered as rigid (not bended), with a negligible mass\n", + "* the pulley is considered as perfect, without mass nor friction\n", "* we consider the static equilibrium obtained after changing the weight, once the system is stabilized\n", "\n", "### Resolution\n", "\n", - "We are looking for the expression of the mass of the counterweight as a function of the other parameters of the problem.\n", + "We are looking for the expression of the **mass of the counterweight as a function of the other parameters of the problem**.\n", "\n", "\n", "\n", - "The forces applied on the *jeans* are the following:\n", + "The *forces applied on the jeans* are the following:\n", "* the weight: $\\vec F_j = m_j \\vec g$ \n", "* the force exerted by the cable on each side of the jeans: assuming the jeans are suspended at the exact center of the cable, then the tension applied on each of the two sides is is equally distributed $\\vec T$, which combine into a vertical resulting tention $\\vec T_r = 2.\\vec T$\n", "\n", - "From Newton's second law in a static equilibrium we can write: $\\sum \\vec F_j = \\vec 0$\n", - "\n", - "With the forces: $\\vec F_j + \\vec T_r = 0$\n", - "\n", + "From Newton's second law in a static equilibrium we can write: $\\sum \\vec F_j = \\vec 0$ \n", + "With the forces involved in our problem we get: $\\vec F_j + \\vec T_r = 0$ \n", "Using the fact that the tension is equal on both sides of the jeans: $\\vec F_j + 2.\\vec T = 0$\n", "\n", - "If we project on $x$ and $y$ axes, we get:\n", - "\n", + "If we project on $x$ and $y$ axes, we get: \n", "$\\left\\{\\begin{matrix} F_{jx} + 2.T_x = 0 \\\\ F_{jy} + 2.T_y = 0\\end{matrix}\\right. $\n", "\n", - "Since the weight does not have a component on the x axis, it simplifies into:\n", - "\n", + "Since the weight does not have a component on the x axis, it simplifies into: \n", "$\\left\\{\\begin{matrix} T_x = 0 \\\\ F_{jy} + 2.T_y = 0\\end{matrix}\\right. $\n", "\n", - "NB: $T_x = 0$ means that the tension on each side of the jeans cancel out.\n", - "\n", - "The component of the weight on the y axis is $F_{jy} = - m_j.g$, which gives us:\n", - "\n", + "The component of the weight on the y axis is $F_{jy} = - m_j.g$, which gives us: \n", "$\\left\\{\\begin{matrix} T_x = 0 \\\\ - m_j.g + 2.T_y = 0\\end{matrix}\\right. $\n", "\n", "Using the angle $\\alpha$ we can get the tension $T_y$ expressed as a function of T since $sin(\\alpha) = \\frac{T_y}{T}$, therefore $T_y = T.sin(\\alpha)$\n", "\n", - "So we get:\n", - "\n", + "By replacing $T_y$ by this expression in the above equation we get: \n", "$\\left\\{\\begin{matrix} T_x = 0 \\\\ - m_j.g + 2.T.sin(\\alpha) = 0\\end{matrix}\\right. $\n", "\n", - "From there we can get $T$:\n", - "\n", + "From there we can get $T$: \n", "$T = \\frac{m_j.g}{2.sin(\\alpha)}$ $(1)$\n", "\n", + " \n", "\n", "On the other hand, the forces applied on the *counterweight* are following:\n", "* the weight: $\\vec F_{cw} = m_{cw} \\vec g$ \n", "* the force exerted by the line: a simple pulley simply changes the direction of the tension so the tension applied on the counterweight is therefore $\\vec T$\n", "\n", - "From Newton's second law in a static equilibrium we can write: $\\sum \\vec F_{cw} = \\vec 0$ \n", - "\n", - "With the forces: $\\vec F_{cw} + \\vec T = \\vec 0$\n", - "\n", - "All forces being vertical, there is no need to project on $x$ so we get: $- F_{cw} + T = 0$\n", - "\n", - "With the detail of the weight: $-m_{cw}.g + T = 0$\n", + "From Newton's second law in a static equilibrium we can write: $\\sum \\vec F_{cw} = \\vec 0$ \n", + "With the forces involved in our problem : $\\vec F_{cw} + \\vec T = \\vec 0$ \n", "\n", + "All forces being vertical, there is no need to project on $x$ so we get: $- F_{cw} + T = 0$ \n", + "Using the expression of the weight: $-m_{cw}.g + T = 0$ \n", "Which gives us $T = m_{cw}.g$ $(2)$\n", "\n", - "From equations $(1)$ and $(2)$ we get:\n", - "\n", + "From equations $(1)$ and $(2)$ we get: \n", "$\\left\\{\\begin{matrix}T = \\frac{m_j.g}{2.sin(\\alpha)} \\\\ T = m_{cw}.g\\end{matrix}\\right. $\n", "\n", - "Which allows us to find the mass of the counterweight as a function of the *mass of the jeans* and of the *angle that the line makes with the horizon*:\n", - "\n", + "Which allows us to find the mass of the counterweight as a function of the *mass of the jeans* and of the *angle that the line makes with the horizon*: \n", "$m_{cw} = \\frac{m_j}{2.sin(\\alpha)}$\n", "\n", "For the line to be taut as show on the figure, $\\alpha$ has to be really small i.e. close to zero. \n", "This means that $sin(\\alpha)$ will also be close to zero, which means in turn that $m_{cw}$ will be very big.\n", "Actually, **the more we want the line to be close to the horizon, the bigger $m_{cw}$ we will need!**\n", "In fact, it is impossible to get the line taut so that it is absolutely straight...\n", "\n", "### Application\n", "\n", "For a pair of wet jeans of $3 kg$ and an angle of $4^\\circ = \\frac{\\pi}{45}$, which is approximately like depicted on the figure, we need to put a counterweight of more than 20 kg!\n", "\n", "You can try out the manual calculation below and check that you get a similar result with the virtual lab above:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m_j = 3\n", "alpha = np.pi / 45\n", "\n", "m_cw = m_j / (2 * np.sin(alpha))\n", "print(m_cw)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "\n", "---\n", "# How does the virtual lab work?\n", "\n", "You can have a look at the code of the virtual lab by [opening this python file](lib/suspendedobjects.py).\n", "\n", "By executing the following cell, you will see the code of the function used to compute the angle that the line makes with the horizon depending on the masses of the object and the counterweight. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "get_angle_from_masses??" ] } ], "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.6.8" } }, "nbformat": 4, "nbformat_minor": 2 } diff --git a/TeachingExamples/lib/fallingobjects.py b/TeachingExamples/lib/fallingobjects.py index f1a0ccc..1e4a1c5 100644 --- a/TeachingExamples/lib/fallingobjects.py +++ b/TeachingExamples/lib/fallingobjects.py @@ -1,242 +1,345 @@ import numpy as np import pandas from ipywidgets import interact, interactive, fixed, interact_manual -from ipywidgets import HBox, VBox, Label, Layout +from ipywidgets import Box, HBox, VBox, Label, Layout import ipywidgets as widgets from IPython.display import set_matplotlib_formats set_matplotlib_formats('svg') import matplotlib.pyplot as plt plt.style.use('seaborn-whitegrid') # global style for plotting -###--- Functions representing the equations of the movement as functions of time and the problem parameters -def accel_time(g, h_0, v_0, m, t): +###--- Equation functions implementing a model without air resistance (free fall) +def accel_time(o, g, h_0, v_0, t): ''' - Computes the acceleration of the object as a function of time - a(t) = -g + Computes the acceleration of the object o as a function of time + Implements a constantly accelerated vertical motion (free fall) of equation: a(t) = -g + :o: object considered :g: gravitational acceleration constant :h_0: initial height of the object :v_0: initial velocity of the object - :m: mass of the object :t: time scale (array of time points at which to compute the equation) :returns: array of values for acceleration at each point of the time scale ''' return [-g] * t.size # returning a list of same length as the time interval filled with -g -def veloc_time(g, h_0, v_0, m, t): +def veloc_time(o, g, h_0, v_0, t): ''' - Computes the velocity of the object as a function of time - v(t) = -g.t + v_0 + Computes the velocity of the object o as a function of time + Implements a constantly accelerated vertical motion (free fall) of equation: v(t) = -g.t + v_0 + :o: object considered :g: gravitational acceleration constant :h_0: initial height of the object :v_0: initial velocity of the object - :m: mass of the object :t: time scale (array of time points at which to compute the equation) :returns: array of values for velocity at each point of the time scale ''' return -g * t + v_0 -def height_time(g, h_0, v_0, m, t): +def height_time(o, g, h_0, v_0, t): ''' - Computes the height of the object as a function of time - h(t) = -1/2.g.t^2 + v_0.t + h_0 + Computes the height of the object o as a function of time + Implements a constantly accelerated vertical motion (free fall) of equation: h(t) = -1/2.g.t^2 + v_0.t + h_0 + :o: object considered :g: gravitational acceleration constant :h_0: initial height of the object :v_0: initial velocity of the object - :m: mass of the object :t: time scale (array of time points at which to compute the equation) :returns: array of values for height at each point of the time scale ''' return -0.5 * g * (t **2) + v_0 * t + h_0 +###--- Equation functions implementing a model with linear friction from air +def accel_time_withair(obj, g, h_0, v_0, t): + ''' + Computes the height of the object o as a function of time + Implements a vertical motion taking into account a linear friction from air + + :o: object considered -- must have a mass and a friction coefficient k + :g: gravitational acceleration constant + :h_0: initial height of the object + :v_0: initial velocity of the object + :t: time scale (array of time points at which to compute the equation) + + :returns: array of values for height at each point of the time scale + ''' + coeff = obj.k / obj.mass + return -g * np.exp(- coeff * t) + +def veloc_time_withair(obj, g, h_0, v_0, t): + ''' + Computes the height of the object o as a function of time + Implements a vertical motion taking into account a linear friction from air + + :o: object considered -- must have a mass and a friction coefficient k + :g: gravitational acceleration constant + :h_0: initial height of the object + :v_0: initial velocity of the object + :t: time scale (array of time points at which to compute the equation) + + :returns: array of values for height at each point of the time scale + ''' + coeff = obj.k / obj.mass + return (v_0 + (g / coeff)) * np.exp(- coeff * t) - (g / coeff) + +def height_time_withair(obj, g, h_0, v_0, t): + ''' + Computes the height of the object o as a function of time + Implements a vertical motion taking into account a linear friction from air + + :o: object considered -- must have a mass and a friction coefficient k + :g: gravitational acceleration constant + :h_0: initial height of the object + :v_0: initial velocity of the object + :t: time scale (array of time points at which to compute the equation) + + :returns: array of values for height at each point of the time scale + ''' + coeff = obj.k / obj.mass + return (1 / coeff) * (v_0 + (g / coeff)) * (1 - np.exp(- coeff * t)) - (g / coeff) * t + h_0 + + ###--- Static list of objects with which we can experiment. -# Objects come with a name, a mass (in kg) and a color for identifying them in the graphical display. +# Objects come with a name, a mass (in kg), a friction coefficient and a color for identifying them in the graphical display. objects = [{ 'name':'Bowling ball', 'mass':5.0, + 'k': (6*np.pi*0.11) * 1.8*10**-5, 'color':'#DC143C' },{ 'name':'Tennis ball', - 'mass':0.05, + 'mass':0.0567, + 'k': (6*np.pi*0.032) * 1.8*10**-5, 'color':'#2E8B57' - },{ - 'name':'Ostrich feather', - 'mass':0.005, - 'color':'#483D8B' + },{ + 'name':'Ping-pong ball', + 'mass':0.0027, + 'k': (6*np.pi*0.02) * 1.8*10**-5, + 'color':'#FF4500' + },{ + 'name':'Air-inflated balloon', + 'mass':0.013, + 'k': 0.02,#(6*np.pi*0.28) * 1.8*10**-5, + 'color':'#000080' }] +def object_string(obj): + '''Utility function to print objects nicely''' + return '{!s}:\n mass = {} kg \n friction coeff. = {:.2e}'.format(obj.name, obj.mass, obj.k) + +###--- Virtual lab class FallingObjectsLab: """ This class embeds all the necessary code to create a virtual lab to study the movement of objects falling vertically in vacuum. """ - def __init__(self, g = 9.81, h_0 = 5, v_0 = 0, t = np.linspace(0,3,25), objects = objects, + def __init__(self, objects = objects, g = 9.81, h_0 = 1.5, v_0 = 0, t = np.linspace(0,1.5,30), accel_time = accel_time, veloc_time = veloc_time, height_time = height_time, - show_v_0 = False): + accel_time_withair = accel_time_withair, veloc_time_withair = veloc_time_withair, height_time_withair = height_time_withair, + show_v_0 = False, show_withair = True): ''' Initiates and displays the virtual lab on falling objects. + :objects: nested dictionnary with the objects to display, which should come with a name, a mass (in kg), a radius (in m) and a color (hex code) + :g: gravitational acceleration constant :h_0: initial height of the objects :v_0: initial velocity of the objects :t: time scale (array of time points at which to compute the equation) - :objects: nested dictionnary with the objects to display, which should come with a name, a mass (in kg) and a color (hex code) - :accel_time: function to compute the acceleration of the objects as a function of time -- a(g, h_0, v_0, m, t) - :veloc_time: function to compute the velocity of the objects as a function of time -- v(g, h_0, v_0, m, t) - :height_time: function to compute the height of the objects as a function of time -- h(g, h_0, v_0, m, t) - + :accel_time: function to compute the acceleration of an object as a function of time -- without air resistance -- a(o, g, h_0, v_0, t) + :veloc_time: function to compute the velocity of an object as a function of time -- without air resistance -- v(o, g, h_0, v_0, t) + :height_time: function to compute the height of an object as a function of time -- without air resistance -- h(o, g, h_0, v_0, t) + + :accel_time_withair: function to compute the acceleration of an object as a function of time -- WITH air resistance -- a(o, g, h_0, v_0, t) + :veloc_time_withair: function to compute the velocity of an object as a function of time -- WITH air resistance -- v(o, g, h_0, v_0, t) + :height_time_withair: function to compute the height of an object as a function of time -- WITH air resistance -- h(o, g, h_0, v_0, t) + :show_v_0: when True, a slider to change the initial velocity of objects is displayed in the interface + :show_withair: when True, a checkbox allows to plot the equations which include air resistance ''' ###--- We define the parameters of our problem: + # Create indexed list of objects + self.objects_list = pandas.DataFrame(objects) + self.objects_list.set_index('name', inplace=True) # We index objects by their name to find them easily after + + # Initialize list of currently selected objects with first element of the list + self.selected_objs_names = [self.objects_list.index[0],] + + # The standard acceleration due to gravity self.g = g # gravity in m/s2 # The initial conditions of our problem self.h_0 = h_0 # initial height in m self.v_0 = v_0 # initial velocity in m/s # To plot the movement of our objects in time we need to define a time scale. self.t = t # time interval from 0 to x seconds, with n points in the interval - # Functions to compute movement equations + # Functions to compute movement equations - free fall (no air resistance) self.accel_time = accel_time self.veloc_time = veloc_time self.height_time = height_time - - # Create indexed list of objects - self.objects_list = pandas.DataFrame(objects) - self.objects_list.set_index('name', inplace=True) # We index objects by their name to find them easily after - - # Initialize list of currently selected objects with first element of the list - self.objs = [self.objects_list.index[0],] + # Functions to compute movement equations - with air resistance (linear friction) + self.withair = False + self.accel_time_withair = accel_time_withair + self.veloc_time_withair = veloc_time_withair + self.height_time_withair = height_time_withair + - ###--- Then we define the elements of the ihm: + ###--- Then we define the elements of the IHM: # parameters for sliders self.h_min = 0 - self.h_max = 10 + self.h_max = 3 self.v_min = 0 - self.v_max = 5 + self.v_max = 3 # IHM input elements - input_layout=Layout(margin='5px 10px') + input_layout=Layout(margin='2px 6px') self.h_label = Label('Initial height ($m$):', layout=input_layout) - self.h_widget = widgets.FloatSlider(min=self.h_min,max=self.h_max,step=1,value=self.h_0, layout=input_layout) + self.h_widget = widgets.FloatSlider(min=self.h_min,max=self.h_max,value=self.h_0, layout=input_layout) self.h_input = HBox([self.h_label, self.h_widget]) self.v_label = Label('Initial velocity ($m.s^{-1}$):', layout=input_layout) - self.v_widget = widgets.FloatSlider(min=self.v_min,max=self.v_max,step=1,value=self.v_0, layout=input_layout) + self.v_widget = widgets.FloatSlider(min=self.v_min,max=self.v_max,value=self.v_0, layout=input_layout) self.v_input = HBox([self.v_label, self.v_widget]) - self.obj_m_label = Label('Choice of object(s):', layout=input_layout) - self.obj_m_widget = widgets.SelectMultiple( + self.obj_label = Label('Choice of object(s):', layout=input_layout) + self.obj_widget = widgets.SelectMultiple( options = self.objects_list.index, - value = self.objs, + value = self.selected_objs_names, disabled = False, layout=input_layout ) - self.obj_m_input = HBox([self.obj_m_label, self.obj_m_widget]) - + self.obj_input = HBox([self.obj_label, self.obj_widget]) + + self.air_label = Label('Include air friction:', layout=input_layout) + #self.air_widget = widgets.Checkbox(value=self.withair, layout=input_layout) + self.air_widget = widgets.ToggleButton(value=self.withair, description="ok", layout=input_layout) + self.air_input = HBox([self.air_label, self.air_widget]) + + # IHM output elements - self.obj_m_output = widgets.Output(layout=input_layout) + self.obj_output = widgets.Output(layout=input_layout) self.graph_output = widgets.Output(layout=input_layout) # Linking widgets to handlers self.h_widget.observe(self.h_event_handler, names='value') self.v_widget.observe(self.v_event_handler, names='value') - self.obj_m_widget.observe(self.obj_m_event_handler, names='value') + self.obj_widget.observe(self.obj_event_handler, names='value') + self.air_widget.observe(self.air_event_handler, names='value') - # Organize layout + # Organize layout + opt_inputs = [self.h_input] + if show_v_0: opt_inputs.append(self.v_input) + if show_withair: opt_inputs.append(self.air_input) + self.ihm = VBox([self.graph_output, HBox([ - VBox([self.obj_m_input, self.obj_m_output]), - VBox([self.h_input, self.v_input]) if show_v_0 else VBox([self.h_input]) + VBox([self.obj_input, self.obj_output]), + VBox(opt_inputs) ]) ]) ###--- Finally, we display the whole interface and we update it right away so that it plots the graph with current values display(self.ihm); self.update_lab() # Event handlers def h_event_handler(self, change): self.h_0 = change.new self.update_lab() def v_event_handler(self, change): self.v_0 = change.new self.update_lab() - def obj_m_event_handler(self, change): - self.objs = change.new + def obj_event_handler(self, change): + self.selected_objs_names = change.new + self.update_lab() + + def air_event_handler(self, change): + self.withair = change.new self.update_lab() - # Display updated output function + # Update output function def update_lab(self): # Clear outputs self.graph_output.clear_output(wait=True) - self.obj_m_output.clear_output(wait=True) + self.obj_output.clear_output(wait=True) # Create the figure - fig, ax = plt.subplots(1, 3, sharex='col', figsize=(16, 4)) + fig, ax = plt.subplots(1, 3, sharex='col', figsize=(14, 4)) # for each object currently selected - for o in self.objs: - # get mass - m = self.objects_list.at[o,'mass'] - # get color - c = self.objects_list.at[o,'color'] - + for o_name in self.selected_objs_names: + # Get the selected object + obj = self.objects_list.loc[o_name] + # Recompute equations with parameters set by the user - h_t = self.height_time(self.g, self.h_0, self.v_0, m, self.t) - v_t = self.veloc_time(self.g, self.h_0, self.v_0, m, self.t) - a_t = self.accel_time(self.g, self.h_0, self.v_0, m, self.t) - + h_t = self.height_time(obj, self.g, self.h_0, self.v_0, self.t) + v_t = self.veloc_time(obj, self.g, self.h_0, self.v_0, self.t) + a_t = self.accel_time(obj, self.g, self.h_0, self.v_0, self.t) + # Plot equations ax[0].set_title('Height ($m$)') - ax[0].plot(self.t, h_t, color=c, label=o) - ax[0].set_ylim(bottom = 0, top = self.h_max+(self.v_max/2 if self.v_0 > 0 else 1)) + ax[0].plot(self.t, h_t, color=obj.color, label=o_name) + ax[0].set_ylim(bottom = 0, top = self.h_max+(self.v_max/2 if self.v_0 > 0 else 0.2)) ax[1].set_title('Velocity ($m.s^{-1}$)') - ax[1].plot(self.t, v_t, color=c, label=o) + ax[1].plot(self.t, v_t, color=obj.color, label=o_name) ax[1].set_ylim(top = self.v_max+1) ax[2].set_title('Acceleration ($m.s^{-2}$)') - ax[2].plot(self.t, a_t, color=c, label=o) - ax[2].set_ylim(top = 0) - - # Display weight of object selected - with self.obj_m_output: - print("Mass of the selected object (kg): ", m) + ax[2].plot(self.t, a_t, color=obj.color, label=o_name) + ax[2].set_ylim(top = 0, bottom = - self.g - 1) + + # If air resistance is activated, then compute the equations and plot them on top + if self.withair: + h_t_withair = self.height_time_withair(obj, self.g, self.h_0, self.v_0, self.t) + ax[0].plot(self.t, h_t_withair, color=obj.color, linestyle='dashed', label=o_name+" with air friction") + + v_t_withair = self.veloc_time_withair(obj, self.g, self.h_0, self.v_0, self.t) + ax[1].plot(self.t, v_t_withair, color=obj.color, linestyle='dashed', label=o_name+" with air friction") + + a_t_withair = self.accel_time_withair(obj, self.g, self.h_0, self.v_0, self.t) + ax[2].plot(self.t, a_t_withair, color=obj.color, linestyle='dashed', label=o_name+" with air friction") + + + # Display characteristics of object selected + with self.obj_output: + print(object_string(obj)) # Add time axis and legend for a in ax: a.set_xlabel('Time (s)') a.legend() fig.tight_layout() # Display graph with self.graph_output: plt.show(); - + + # EOF diff --git a/Welcome.ipynb b/Welcome.ipynb index a0d3541..01c32f5 100644 --- a/Welcome.ipynb +++ b/Welcome.ipynb @@ -1,79 +1,79 @@ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "![EPFL](https://inside.epfl.ch/corp-id/wp-content/uploads/2019/05/EPFL_Logo_Digital_RGB_PROD-300x130.png) ![NOTO](Images/noto_300x130.png)\n", "\n", "# Welcome to ![noto](Images/noto_86x25_inline_transparent.png)'s ![poc](Images/poc_45x25_red.png) notebooks" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Congratulations!\n", "\n", "You have just used `nbgitpuller` to **clone** a git repository (https://c4science.ch/source/noto-poc-notebooks/) and **pull** its content in your jupyter workspace.\n", "\n", "The aim of this repository is to give you some practical hints on both the pedagogical and technical aspects of notebook writing.\n", "\n", "### Share the link !\n", "\n", "Feel free to share the following link and give other people access to this git repository: https://go.epfl.ch/bDS" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Available notebooks\n", "\n", "\n", "| ![pedagogy](https://static1.squarespace.com/static/564f72ade4b0b0384379a293/t/5c7e8aefe79c701d7e5f4763/1551796980913/strategy.png) | Using notebooks for teaching: examples |   | ![technical](https://cdn4.iconfinder.com/data/icons/gnome-desktop-icons-png/PNG/64/Gnome-Preferences-System-64.png) | Technical notebooks |\n", "|:-|:-|--|:-|:-|\n", - "| ![question](https://cdn0.iconfinder.com/data/icons/super-mono-reflection/red/question-balloon_red.png) | Examples of notebooks for [virtual demonstrations](Demonstrations/Demonstrations.ipynb) in class |   | ![python](http://www.techteachers.co.za/wp-content/uploads/python-logo64.png) | How to [organize](HowTos/OrganizeCode/OrganizeCode.ipynb) your Python code?|\n", + "| ![question](https://cdn0.iconfinder.com/data/icons/super-mono-reflection/red/question-balloon_red.png) | Examples of notebooks for [virtual demonstrations](TeachingExamples/Demonstrations.ipynb) in class |   | ![python](http://www.techteachers.co.za/wp-content/uploads/python-logo64.png) | How to [organize](HowTos/OrganizeCode/OrganizeCode.ipynb) your Python code?|\n", "|   |   |   | ![python](http://www.techteachers.co.za/wp-content/uploads/python-logo64.png) ![multimedia](https://images.sftcdn.net/images/t_app-logo-l,f_auto,dpr_auto/p/974baeec-42f5-405c-8bbc-fec81b7a2bf6/3217395839/focus-picture-gallery-icon.png) | How to embed [external resources](HowTos/EmbedExternalResources/EmbedExternalResources.ipynb) in your notebooks? |\n", "|   |   |   | ![git](https://www.file-extension.info/images/resource/64/git.png) | How to [share](HowTos/SharingYourNotebooks/SharingYourNotebooks.ipynb) your notebooks wih git? |\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Contact and support\n", "\n", "For any question, feel free to contact ![noto](Images/noto_inline_transparent.png) support: [noto-support@groupes.epfl.ch](mailto:noto-support@groupes.epfl.ch)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**End of the notebook**" ] } ], "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.6.8" } }, "nbformat": 4, "nbformat_minor": 2 }