Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F83493211
fallingobjects.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Sep 17, 10:57
Size
7 KB
Mime Type
text/x-python
Expires
Thu, Sep 19, 10:57 (2 d)
Engine
blob
Format
Raw Data
Handle
20847366
Attached To
rNOTOPOCNB noto-poc-notebooks
fallingobjects.py
View Options
import
numpy
as
np
import
pandas
from
ipywidgets
import
interact
,
interactive
,
fixed
,
interact_manual
from
ipywidgets
import
HBox
,
VBox
,
Label
,
Layout
import
ipywidgets
as
widgets
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
):
'''
Computes the acceleration of the object as a function of time
a(t) = -g
:g: gravity constant
:h_0: initial height
:v_0: initial velocity
:m: mass
:t: time scale (array of time points at which to compute the equation)
:returns: array of values for acceleration, of same size as 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
):
'''
Computes the velocity of the object as a function of time
v(t) = -g.t + v_0
:g: gravity constant
:h_0: initial height
:v_0: initial velocity
:m: mass
:t: time scale (array of time points at which to compute the equation)
:returns: array of values for velocity, of same size as the time scale
'''
return
-
g
*
t
+
v_0
def
height_time
(
g
,
h_0
,
v_0
,
m
,
t
):
'''
Computes the height of the object as a function of time
h(t) = -1/2.g.t^2 + v_0.t + h_0
:g: gravity constant
:h_0: initial height
:v_0: initial velocity
:m: mass
:t: time scale (array of time points at which to compute the equation)
:returns: array of values for height, of same size as the time scale
'''
return
-
0.5
*
g
*
(
t
**
2
)
+
v_0
*
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
=
[{
'name'
:
'Bowling ball'
,
'mass'
:
5.0
,
'color'
:
'#DC143C'
},{
'name'
:
'Tennis ball'
,
'mass'
:
0.05
,
'color'
:
'#2E8B57'
},{
'name'
:
'Ostrich feather'
,
'mass'
:
0.005
,
'color'
:
'#483D8B'
}]
class
FallingObjectsLab
:
"""
This class embeds all the necessary code to create a virtual lab where the movement of falling objects is studied.
"""
def
__init__
(
self
,
g
=
9.81
,
h_0
=
5
,
v_0
=
0
,
objects
=
objects
,
accel_time
=
accel_time
,
veloc_time
=
veloc_time
,
height_time
=
height_time
,
show_v_0
=
False
):
###--- We define the parameters of our problem:
# 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
=
np
.
linspace
(
0
,
3
,
25
)
# time interval from 0 to x seconds, with n points in the interval
# Functions to compute movement equations
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
],]
###--- Then we define the elements of the ihm:
# parameters for sliders
self
.
h_min
=
0
self
.
h_max
=
10
self
.
v_min
=
0
self
.
v_max
=
5
# IHM input elements
input_layout
=
Layout
(
margin
=
'5px 10px'
)
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_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_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
(
options
=
self
.
objects_list
.
index
,
value
=
self
.
objs
,
disabled
=
False
,
layout
=
input_layout
)
self
.
obj_m_input
=
HBox
([
self
.
obj_m_label
,
self
.
obj_m_widget
])
# IHM output elements
self
.
obj_m_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'
)
# Organize layout
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
])
])
])
###--- 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
self
.
update_lab
()
# Display updated output function
def
update_lab
(
self
):
# Clear outputs
self
.
graph_output
.
clear_output
(
wait
=
True
)
self
.
obj_m_output
.
clear_output
(
wait
=
True
)
# Create the figure
fig
,
ax
=
plt
.
subplots
(
1
,
3
,
sharex
=
'col'
,
figsize
=
(
16
,
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'
]
# 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
)
# 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
))
# limit y axis to values >= 0
ax
[
1
]
.
set_title
(
'Velocity ($m.s^{-1}$)'
)
ax
[
1
]
.
plot
(
self
.
t
,
v_t
,
color
=
c
,
label
=
o
)
ax
[
1
]
.
set_ylim
(
top
=
self
.
v_max
+
1
)
# limit y axis to values >= 0
ax
[
2
]
.
set_title
(
'Acceleration ($m.s^{-2}$)'
)
ax
[
2
]
.
plot
(
self
.
t
,
a_t
,
color
=
c
,
label
=
o
)
ax
[
2
]
.
set_ylim
(
bottom
=
0
)
# limit y axis to values >= 0
# Display weight of object selected
with
self
.
obj_m_output
:
print
(
"Mass of the selected object (kg): "
,
m
)
# 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
Event Timeline
Log In to Comment