diff --git a/TeachingExamples/01_Demonstrations.ipynb b/TeachingExamples/01_Demonstrations.ipynb index 83fc4ac..aae6cbb 100644 --- a/TeachingExamples/01_Demonstrations.ipynb +++ b/TeachingExamples/01_Demonstrations.ipynb @@ -1,154 +1,155 @@ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Virtual demonstrations - Using digital artefacts to illustrate explanations\n", "\n", "Classroom demonstrations, i.e. showing phenomena in class, make great illustrations that 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 make sure that your demonstrations are **more than just entertainment**?\n", "\n", "A few simple ingredients can transform your virtual demonstrations into *powerful teaching and learning tools*. On this page, we summarize briefly some of the [ideas from research on the impact of demonstrations on students learning](#Ingredients-for-effective-virtual-demonstrations-in-class) and share with you [example notebooks](#Examples) which implement these ideas in practice.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ingredients for effective virtual demonstrations in class\n", "\n", "### Questions\n", "\n", - "Questionning students can really help students engage actively with your demonstration: \n", - "* Catherine Crouch and her colleagues from Harvard University for instance, have shown that having students **predict the outcome of a demonstration before observing it** makes an essential difference in terms of what students remember and understand from a demonstration [(Crouch et al., 2004)](https://aapt.scitation.org/doi/10.1119/1.1707018). This result has been reproduced in a number of other studies, and the reason why this technique works so well seems to be fundamentally linked to how our brain works, according to relatively recent models [(Dehaene, 2011)](https://www.college-de-france.fr/site/en-stanislas-dehaene/course-2011-2012.htm). \n", + "Questions can really help students engage actively with your demonstration: \n", + "* Catherine Crouch and her colleagues from Harvard University have shown that having students **predict the outcome of a demonstration before observing it** makes an essential difference in terms of what students remember and understand from a demonstration [(Crouch et al., 2004)](https://aapt.scitation.org/doi/10.1119/1.1707018). This result has been reproduced in a number of other studies, and the reason why this technique works so well seems to be fundamentally linked to how our brain works, according to relatively recent models [(Dehaene, 2011)](https://www.college-de-france.fr/site/en-stanislas-dehaene/course-2011-2012.htm). \n", "* When observing a demonstration, it can be hard for students to focus their attention at the right place at the right time. Asking them **questions that drive them to observe specific features** of what you are showing can greatly help them see what you want them to see. \n", "* Very often, students have a hard time identifying what they need to remember from a demonstration. Asking them **questions at the end of a demonstration to reflect on the important points** which have been illustrated is a very effective way to draw their attention to the right elements.\n", "\n", "

\n", "Key points:
\n", " For a maximized impact on learning, ask students questions before (prediction questions), during (observation questions) and after (reflection questions) your demonstrations with notebooks.\n", "

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Discussions with peers\n", "\n", "Usually, the \"why\" things happen is more important than the \"what\" happens in a demonstration. However, it is very difficult for students with a prior misconception to really change their understanding if they do not realize that they have a misconception.\n", - "A key to effective demonstrations is therefore to give students an opportunity to **formulate** why they think things happen that way, as a mean for them to clarify their own thinking.\n", + "A key to effective demonstrations is therefore to give students an opportunity to **formulate** why they think things happen that way, as a mean for them to clarify their own thinking before hearing your own explanation.\n", "\n", "A simple tool to do this is peer discussion. By encouraging students to **discuss the \"why\" with others**, you give them a chance to put words on the implicit model they have in mind and to confront it to the reasoning of others. After verbalizing their understanding of the concepts, students will be better able to assess it against your own explanations, which will then have much more impact.\n", "\n", "

\n", "Key points:
\n", " To help students develop their reasoning, have them discuss \"why\" things happen this way in the virtual demonstration with their peers before presenting your own explanation.\n", "

\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Multiple representations\n", "\n", "Presenting students with multiple representations of concepts has been shown to have positive effects on learning [(Mayer, 2009)](http://dx.doi.org/10.1017/CBO9780511811678). Graphical visualizations play an important role in this, but it has been shown that it is the combination of the representations which actually is efficient, which means that *text, equations, tables, videos* or other types of embedded media also are important.\n", "\n", "Two key elements are worth considering particularly in virtual demonstrations:\n", "* Showing explicitely (through visual cues, text, arrows, etc.) **how the different representations relate to each other** is a great way to illustrate different ways of modeling the same reality, which is essential for students to develop their modeling skills.\n", "* Presenting students with the **type of representations that they need to use** when they solve problems in your discipline (for instance when they need to analyze the situation, when they need to choose a model or when they need to check their solution) can help your students develop their problem solving skills \n", "\n", "\n", "

\n", "Key points:
\n", " Virtual demonstrations can serve as a bridge to develop problem solving skills if you design your notebooks with multiple connected representations, which match the representations you want students to use when solving problems.\n", "

\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "\n", "## Examples\n", "\n", "The following examples show how using the above elements in demonstrations can look like, in different formats:\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
What is involved?Show me an example
\"Low tech\"Ask students questions which they have to answer on a piece of paper.

Show visualizations that you want students to use when they solve problems.
Have a look at the falling objects demo
Interactive questionsUse the notebook to poll students using interactive questions where students vote for the answer of their choice.

Combine and synchronize interactively a diagram and different function plots.
[WORK IN PROGRESS]
Have a look at the suspended objects demo
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "\n", "## Sharing your demonstration notebooks with students\n", "\n", "Making the virtual demonstrations available to the students can be a good idea. But how will students know (or remember) which parameters to change and what to observe? \n", "By **including questions and instructions** into the notebook together with the virtual demonstration, you will ensure that students can use them effectively in autonomy.\n", "\n", - "Have a look at the examples of notebooks for exercises or assignements.\n" + "Have a look at the examples of notebooks for exercises or assignements.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \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", "Dehaen, S. (2011). The Statistician Brain: The Bayesian Revolution in Cognitive Sciences. Lectures at Collège de France. \n", "https://www.college-de-france.fr/site/en-stanislas-dehaene/course-2011-2012.htm\n", "\n", "Mayer, R. E. (2009). Multimedia learning (2nd ed.). Cambridge University Press. \n", "http://dx.doi.org/10.1017/CBO9780511811678\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": 4 } diff --git a/TeachingExamples/03_Assignments.ipynb b/TeachingExamples/02_Assignments.ipynb similarity index 100% rename from TeachingExamples/03_Assignments.ipynb rename to TeachingExamples/02_Assignments.ipynb diff --git a/TeachingExamples/02_Textbooks.ipynb b/TeachingExamples/03_Textbooks.ipynb similarity index 100% rename from TeachingExamples/02_Textbooks.ipynb rename to TeachingExamples/03_Textbooks.ipynb diff --git a/TeachingExamples/FallingObjects-demo.ipynb b/TeachingExamples/FallingObjects-demo.ipynb index c4cba24..3d6bcc5 100644 --- a/TeachingExamples/FallingObjects-demo.ipynb +++ b/TeachingExamples/FallingObjects-demo.ipynb @@ -1,181 +1,189 @@ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "

Use case scenario
\n", " This notebook is made to be used in class as a virtual demonstration which is operated by the teacher (the notebook is not meant to be used by students).

\n", "

Features
\n", " This notebook embeds different types of questions to engage students with the virtual demonstration and uses the type of visualisations that students will be asked to use when solving similar problems (i.e. in this case graphing height, velocity and acceleration as functions of time).
\n", " The example chosen is voluntarily simple so that anyone can understand what is illustrated and focus the pedagogical features of the example.

\n", "

More information on using notebooks for virtual demonstrations.

\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Falling objects\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Problem\n", "\n", "Present the following problem to your students:\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 your 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? **Discuss your explanations with your neighbour.**\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 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 **reflection questions**:\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: `FallingObjectsLab(show_withair=True);`\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(show_withair=False);" ] }, { "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, start=171)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "\n", "---\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, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Object `FallingObjectsLab` not found.\n" + ] + } + ], "source": [ "FallingObjectsLab?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Utility computation functions\n", "\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": [ "height_time??" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "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": 4 } diff --git a/TeachingExamples/SuspendedObjects-exercise.ipynb b/TeachingExamples/SuspendedObjects-exercise.ipynb index 244541a..4fc6de9 100644 --- a/TeachingExamples/SuspendedObjects-exercise.ipynb +++ b/TeachingExamples/SuspendedObjects-exercise.ipynb @@ -1,240 +1,249 @@ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " WORK IN PROGRESS  This notebook is under development, please bear with us...\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "

Use case scenario
\n", " This notebook is made to be used by students as an assignment or exercise, in autonomy (at home or in an exercise session).

\n", "

Features
\n", " This notebook embeds auto-corrected quizzes to engage students with the virtual demonstration and uses different types of visualisations to help students understand the phenomena.
\n", " The example chosen is voluntarily simple so that anyone can understand what is illustrated and focus the pedagogical features of the example.

\n", "

More information on using notebooks for exercises or assignements.

\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Suspended objects\n", "\n", "\n", "\n", "## The problem\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", - "The focus of this problem is the counterweight.\n", "\n", "## Initial questions\n", "\n", "Execute the cell below to activate the interactive quizz." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import IFrame\n", - "IFrame('https://h5p.org/h5p/embed/583522', 1024, 360)" + "IFrame('https://h5p.org/h5p/embed/583522', 1024, 550)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Virtual lab\n", "\n", "The virtual demonstration below illustrates position of the clothesline for different counterweights. \n", - "Execute the cell below to launch the virtual demonstration, then *answer the questions below*." + "Execute the cell below to launch the virtual demonstration, then *answer the series of questions below*." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "from lib.suspendedobjects import *\n", - "SuspendedObjectsLab();" + "SuspendedObjectsLab();\n", + "\n", + "IFrame('https://h5p.org/h5p/embed/584119', 1024, 400)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### TODO here add observation questions in the form of auto-corrected quizzes.\n", - "\n", - " \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).*\n", "\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Analytic explanation\n", + "## Analytic solution\n", + "\n", + "### Goal\n", + "\n", + "The question is which counterweight allows to suspend wet jeans (3kg) on the cable so that the cable is taut as shown on the diagram. \n", + "We are therefore looking for the expression of the **mass of the counterweight $m_{cw}$ as a function of the other parameters of the problem**. \n", "\n", - "### Hypotheses and simplifications:\n", + "### Method\n", "\n", + "Given that the system is in static equilibrium, the sum of external forces exerted on the system will be zero, so using Newton's second law should be easy. The force that the counterweight exerts on the system will involve the mass of the counterweight so we should be able to rewrite Newton's second law to get an expression of the form $m_{cw} = ...$.\n", + "\n", + "### Hypotheses and simplifications\n", + "\n", + "We make the following assumptions and simplifications:\n", "* the jeans are considered as positioned exactly mid-way between the poles so the tension is equal on both sides of the cable\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", - "Given that the system is in static equilibrium, using Newton's second law should be easy (sum of external forces will be zero) and we will have the mass of the counterweight involved in the expression of the force it exerts on the system.\n", - "\n", "First, let's draw a diagram and represent the different forces involved.\n", "\n", "\n", - "The *forces applied on the jeans* are the following:\n", + "The *forces applied on the jeans* are:\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", "With the forces on the jeans we get: $\\vec F_j + \\vec T_r = 0$ \n", "Using the fact that the tension is equal on both sides of the jeans we get: $\\vec F_j + 2.\\vec T = 0$\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", "$\\left\\{\\begin{matrix} T_x = 0 \\\\ F_{jy} + 2.T_y = 0\\end{matrix}\\right. $\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", "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", - "$T = \\frac{m_j.g}{2.sin(\\alpha)}$ $(1)$\n", + "From there we can get $T$, and this is equation number $(1)$: \n", + "$T = \\frac{m_j.g}{2.sin(\\alpha)}$\n", "\n", " \n", "\n", "We now want to make the mass of the counterweight appear in this expression. \n", "So we will now look at the forces applied on the *counterweight*.\n", "\n", " \n", "\n", "The forces applied on the *counterweight* are:\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", "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", + "We replace the weight by its detailed expression: $-m_{cw}.g + T = 0$ \n", + "Now we can express $T$ as a function of the other parameters, which is equation number $(2)$: $T = m_{cw}.g$ \n", "\n", " \n", "\n", - "From equations $(1)$ and $(2)$ we get: \n", + "Let's now summarize what we have so far with equations $(1)$ and $(2)$: \n", "\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", + "These two equations combined give us:\n", + "\n", + "$\\frac{m_j.g}{2.sin(\\alpha)} = m_{cw}.g$\n", + "\n", + "This allow 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", "$m_{cw} = \\frac{m_j}{2.sin(\\alpha)}$\n", "\n", " \n", "\n", "### Conclusion\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", " \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:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - " 3 / (2 * np.sin(np.pi / 45))" + "mcw = 3 / (2 * np.sin(np.pi / 45))\n", + "print(mcw)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can **check that you get a similar result** with the virtual lab above!" ] }, { "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": 4 } diff --git a/TeachingExamples/lib/fallingobjects.py b/TeachingExamples/lib/fallingobjects.py index ca5dc73..e876bfc 100644 --- a/TeachingExamples/lib/fallingobjects.py +++ b/TeachingExamples/lib/fallingobjects.py @@ -1,345 +1,345 @@ import numpy as np import pandas from ipywidgets import interact, interactive, fixed, interact_manual 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 ###--- 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 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 :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(o, g, h_0, v_0, t): ''' 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 :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(o, g, h_0, v_0, t): ''' 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 :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), 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.0567, 'k': (6*np.pi*0.032) * 1.8*10**-5, 'color':'#2E8B57' },{ '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} kg/s'.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. + This class embeds all the necessary code to create a virtual lab to study the movement of falling 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, 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) + :objects: nested dictionnary with the objects to display, which should come with at least the following properties: a name, a mass (in kg) 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) :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 - free fall (no air resistance) self.accel_time = accel_time self.veloc_time = veloc_time self.height_time = height_time # 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: # parameters for sliders self.h_min = 0 self.h_max = 3 self.v_min = 0 self.v_max = 3 # IHM input elements 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,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,value=self.v_0, layout=input_layout) self.v_input = HBox([self.v_label, self.v_widget]) self.obj_label = Label('Choice of object(s):', layout=input_layout) self.obj_widget = widgets.SelectMultiple( options = self.objects_list.index, value = self.selected_objs_names, disabled = False, layout=input_layout ) 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_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_widget.observe(self.obj_event_handler, names='value') self.air_widget.observe(self.air_event_handler, names='value') # 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_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_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() # Update output function def update_lab(self): # Clear outputs self.graph_output.clear_output(wait=True) self.obj_output.clear_output(wait=True) # Create the figure fig, ax = plt.subplots(1, 3, sharex='col', figsize=(14, 4)) # for each object currently selected 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(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=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=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=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