The physical python module

_images/falling.png

A python package aimed at teaching students physics through having them program using 3d simulation. A key goal is to provide clear error messages for mistakes common among intro physics students. Physical is inspired by the visual package, but aims to provide improved error messages and assignment semantics.

physical.check_units(err, *vals)

Verifies that the arguments have the same units.

Parameters:err – a string giving the error message when units fail to match.
Raises:Exception – the units do not match
physical.dimensionless(err)

A decorator for declaring that a function expects dimensionless input, such as \(\sin\) and \(\cos\). The single argument is the error message to be presented to a user who accidentally provides this function with a value having units.

@dimensionless('arguments to myfunction should be dimensionless')
def myfunction(x):
    return 4*x
>>> myfunction(4)
16
>>> myfunction(4*meter)
Traceback (most recent call last):
  ...
Exception: arguments to myfunction should be dimensionless: 4 meter
physical.sqrt(v)

Compute \(\sqrt{x}\).

>>> sqrt(4*second**2)
2.0 second
physical.exp(*args, **kwargs)

Compute \(e^x\).

Raises:Exception – x is not dimensionless
>>> exp(0)
1.0
>>> exp(2*second) # bad units!
Traceback (most recent call last):
  ...
Exception: argument to exp must be dimensionless: 2 second
physical.sin(*args, **kwargs)

Compute \(\sin(x)\).

Raises:Exception – x is not dimensionless
>>> sin(pi/2)
1.0
>>> sin(2*second) # bad units!
Traceback (most recent call last):
  ...
Exception: argument to sin must be dimensionless: 2 second
physical.cos(*args, **kwargs)

Compute \(\cos(x)\).

Raises:Exception – x is not dimensionless
>>> cos(pi)
-1.0
>>> cos(2*second) # bad units!
Traceback (most recent call last):
  ...
Exception: argument to cos must be dimensionless: 2 second
physical.tan(*args, **kwargs)

Compute \(\tan(x)\).

Raises:Exception – x is not dimensionless
>>> print('%g' % tan(pi/4))
1
>>> tan(2*second) # bad units!
Traceback (most recent call last):
  ...
Exception: argument to tan must be dimensionless: 2 second
physical.atan2(*args, **kwargs)

Compute \(\tan^{-1}\left(\frac{y}{x}\right)\).

Parameters:
  • y – the “vertical” component of a vector
  • x – the “horizontal” component of the vector
Raises:

Exception – x and y do not have the same dimensions

You should almost always prefer ‘atan2’ over any other inverse trig functions, because it can (and does) properly determine the quadrant of the point described by the angle, so it can give you an unambiguous answer. For this reason we do not export any of the other inverse trig functions.

>>> atan2(5.0*meter, 0.0*meter)
1.5707963267948966
>>> atan2(2*second, 3) # units don't match!
Traceback (most recent call last):
  ...
Exception: arguments to atan2 must have the same units: 3 vs 2 second
physical.sphere(pos=<0, 0, 0> meter, radius=1.0 meter, color=color.RGB(1, 1, 1))

Create a sphere object.

_images/sphere.png
Parameters:
  • pos – the initial position of the sphere in meters (defaults to the origin)
  • radius – the radius of the sphere in meters
  • color – the color of the sphere
Raises:

Exception – the dimensions are not distances

s = sphere(vector(-1,3,0)*meter, radius=1.5*meter, color=color.blue)
physical.helix(pos1, pos2, radius=0.1 meter, color=color.RGB(1, 1, 1), length=None, twists=5)

Create a helix object.

_images/helix.png
Parameters:
  • pos1 – the initial position of one end of the helix. This may be an object that has a position, in which case the helix will be attached to that object as it moves.
  • pos2 – the initial position of the other end of the helix. This may be an object that has a position, in which case the helix will be attached to that object as it moves.
  • radius – the radius of the wire in meters
  • color – the color of the helix
  • length – the length of the wire forming the helix. If not specified, this defaults to 2*twists*the distance between the two ends.
  • twists – the number of twists in the wire
Raises:

Exception – the dimensions are not distances

s1 = sphere(vector(-1,0,0)*meter, color=color.red)
s2 = sphere(vector( 1,0,0)*meter, color=color.green)
s2.pos = vector(2,0,0)*meter # the spring stretches
h = helix(s1, s2)
physical.cylinder(pos1, pos2, radius=0.1 meter, color=color.RGB(1, 1, 1))

Create a cylinder object.

_images/cylinder.png
Parameters:
  • pos1 – the initial position of one end of the cylinder. This may be an object that has a position, in which case the cylinder will be attached to that object as it moves.
  • pos2 – the initial position of the other end of the cylinder. This may be an object that has a position, in which case the cylinder will be attached to that object as it moves.
  • radius – the radius of the cylinder in meters
  • color – the color of the cylinder
Raises:

Exception – the dimensions are not distances

The properties of the cylinder may be accessed and later modified as member variables of the object returned.

c = cylinder(vector(0,0,0)*meter, vector(1,0,0)*meter, radius=1*meter)
c.pos2 = vector(.4,.3,-.3)*meter
physical.box(pos, wx, wy, wz, color=color.RGB(1, 1, 1))

Create a box object.

_images/box.png
Parameters:
  • pos – the initial position of the center of the box
  • wx – the width of the box in the x direction
  • wy – the width of the box in the y direction
  • wz – the width of the box in the z direction
  • color – the color of the cylinder
Raises:

Exception – the dimensions are not distances

# create a box that is 1x1x0.1 meters in dimension,
# centered at the origin.
b = box(vector(0,0,0)*meter, 1*meter, 1*meter, 0.2*meter)
camera.position = vector(.5,1.5,1)*meter
physical.trail(object, duration=None, dash_time=0.2 second)

Add a trail to an object.

_images/trail.png
Parameters:
  • object – the object that is trailed, which must have a “pos” attribute
  • duration – how long in seconds the trail should last before disappearing
  • dash_time – time between when the trail turns on and off, leading to a dashed-line effect
Raises:

Exception – the duration or dash_time are not times.

s = sphere(vector(-1,0,16)*meter, radius=1.5*meter)
s.velocity = vector(2,0,0)*meter/second
trail(s, duration=4*second, dash_time=0.1*second)
g = vector(0,0,-9.8)*meter/second**2
t = 0*second
dt = 0.001*second
while t < 5*second:
    s.pos += s.velocity*dt
    s.velocity += g*dt
    if s.pos.z < 0*meter:
        s.velocity.z = abs(s.velocity.z)
    timestep(dt)
    t += dt
physical.plot(color)

Create a plot object.

_images/plot.png
Parameters:color – the color of the curve
Raises:Exception – the color is not a color

This function returns a plot object. You can add values to the plot as \(xy\) pairs using code such as:

quadratic = plot(color.green)
linear = plot(color.red)
x = 0
while x < 1:
    quadratic.plot(x, x**2)
    linear.plot(x,x)
    x = x+0.01
physical.hline(y, color)

Create a horizontal line object.

Parameters:
  • y – the y value of the line
  • color – the color of the line
Raises:

Exception – the color is not a color

# the y value must have same units as any other quantities
# plotted on vertical axis (e.g. example code for `plot`)
hline(0*Joule, color.blue)
physical.timestep(dt)

Advance the simulation by time dt.

Parameters:dt – the time in seconds (as a scalar) to advance
Raises:Exception – dt is not a time

You must call timestep regularly in order for your simulation to be animated. timestep also performs a number of cleanup tasks, such as allowing user interaction with the visualization.

t = 0*second
dt = 0.01*second
while t < 5*second:
    # do something useful here
    t += dt
    timestep(dt)
physical.savepng(fname)

Save the current image to a file.

This is useful for creating documentation, or for creating instructional materials. If you are using this command, you may also be interested in rendering without displaying a window (for scripting), which can be done with:

PYOPENGL_PLATFORM=osmesa python3 helix.py

provided you have libosmesa installed, and PyOpenGL >= 3.1.0.

physical.minimum_fps = 0.1 second**(-1)

the minimum frames per second that the renderer will draw.

class physical.Camera

The camera

center

the position at which the camera points

s = sphere(vector(3,3,3)*meter, color=color.yellow)
camera.center = s
position

the position of the camera.

s = sphere(vector(3,3,3)*meter, color=color.yellow)
camera.position = s
range

the distance between the camera and the center

The distance can be assigned to, which has the effect of shifting the camera towards or away from the center.

camera.range = 5*meter
up

the vertical direction of the camera.

camera.up = vector(0,1,0)
windowsize

the size of the window in pixels

The windowsize can be assigned to, but only prior to creating any objects.

camera.windowsize = (200,200)

Indices and tables