Appendix B - An Introduction to Visual Python
B.1Overview¶
This appendix gives a very brief introduction to calculus with a focus on the tools needed in physics.
B.2Code in this textbook¶
When referring to general ideas or something very brief, Visual Python code may be written in-line. For example, this is a general code statement
. When giving explicit code to be implemented, Visual Python code will be written in “display mode”. For example,
print("This code is meant to be implemented into a trinket.")
The distinction should become clear as you work through this appendix. We hope to provide in this textbook all of the instruction necessary to create physics simulations using Visual Python in the trinket platform. In the event that more information is desired, a good reference is https://
B.3The trinket.io platform¶
Trinket.io is web-based programming platform with a few different programming languages available,e.g., Python, Visual Python, R, Java, and HTML5. In this textbook, we will use primarily Visual Python, which is a language built on Python that allows Python programming to manipulate simulated objects in three-dimensional space. The trinket Figure B.1 is a Visual Python program that simulates a moon-like mass orbiting an Earth-like mass. Click the play button to see the simulation.
A few notes about the embedded trinkets in this book:
- The menu in the upper left corner allows full-screen viewing.
- The center bar between the code and the simulation can be adjusted to make the either consume more of the screen for easier viewing.
- The right mouse button allows rotation of the view.
- The mouse wheel allows zooming in and out of the view.
- If signed into trinket, readers should be able to click “Remix” in the upper right corner to save a trinket to their own account.
B.3.1Trinket accounts¶
The website trinket.io offers a variety of accounts. You can learn more about these at https://
- with free accounts for everyone where the instructor shares pre-written shells for students to complete
- with free accounts for students and a pay account for the instructor. This allows the instructor to build trinket courses with assignments.
- with pay accounts for everyone that offers the most options.
B.3.2What is a trinket?¶
A trinket is a Visual Python program written in the trinket.io web platform. When starting a new program, a trinket will look like Figure B.2. The Web Vpython
line indicates the language. This line should always be in a trinket that uses the Visual Python language. The version number may change as updates are made to the Visual Python language.
Trinkets in this book are interactive. Readers can enter code and run the code while reading the textbook. Give it a try. Enter the following code and click the play button.
print("Hello World! This is my first trinket.")
If you wish, you can Remix the trinket to your own account. It will appear in your account as “BlankTrinket”. You may rename your trinkets from the trinket.io website.
B.4Programming in Visual Python¶
B.4.1Create objects in a trinket¶
The choice of Visual Python is so that readers can visualize the physics being discussed in the book. Therefore, almost every program will be focused on manipulating Visual Python objects. It is important for readers to become comfortable with creating these objects. In the following examples, we will demonstrate spheres and cylinders. All Visual Python objects have “attributes” such as position, color, and size. lists common objects and their attributes. Notice the attributes vary in definition such as vector, scalar, or some text-based variable. It is also possible to create new, user-defined attributes, which will be discussed below.
Table B.1:A quick reference for a few commonly used objects and their attributes
Object | Attributes |
---|---|
sphere | pos (vector) – Position of center. Default (0,0,0). |
radius (scalar) – Default 1. | |
color (vector) – Default color.white | |
size (vector) – Dimensions of a box surrounding the sphere. Default (2,2,2). | |
axis (vector) – Default (1,0,0) | |
box | pos (vector) – Position of center. Default (0,0,0). |
axis (vector) – Extends from left to right end. Default <1,0,0>. | |
color (vector) – Default color.white. | |
length (scalar) – Length of box. Default 1. | |
height (scalar) – Height of box. Default 1. | |
width (scalar) – Width of box. Default 1. | |
size (vector) – Length, width, and height in one vector. An alternative to length, height, width. | |
arrow | pos (vector) – Position of tail. Default (0,0,0). |
axis (vector) – Extends from tail to tip. Default (1,0,0). | |
color (vector) – Default is color.white | |
round (boolean) – Makes shaft and head round instead of square. Default is False. | |
shaftwidth (scalar) – Width of tail. Default 0.1*(length of arrow) | |
headwidth (scalar) – Default 2*shaftwidth | |
headlength (scalar) – Default 3*shaftwidth | |
cylinder | pos (vector) – Position of left end. Default (0,0,0). |
axis (vector) – Extends from pos to end. Default (1,0,0). | |
color (vector) – Default color.white. | |
radius – Radius of the cylinder. Default is 1. | |
length (scalar) – Length of axis. Setting length sets magnitude of axis. Default is 1. | |
size (vector) – Length, height, width of a box surrounding the cylinder. Default is (1,1,1). |
B.4.1.1Spheres¶
To create a sphere at the origin of a cartesian coordinate system, enter the following code.
ball = sphere(pos=vec(0,0,0), color=color.green, radius=0.1)
One can think of the spatial coordinate system being in meters so that all lengths are denoted in meters. Of course, this is arbitrary, and the scale could be considered any length desired, and the programming would need to match the chosen scale. Notice the color is defined with color=color.green
. It is important to define colors this way, i.e., with the “color-dot” format. Readily available colors are red, green, blue, cyan, magenta, yellow, orange, purple, and white. The radius
variable is often chosen based on the scale of motion that will be simultated. For example, if the sphere is going to be moved centimeters, the radius should be smaller than 1 cm, and if the sphere is going to move meters, the radius would be smaller than 1 meter.
B.4.1.2Cylinders¶
To create a magenta cylinder 5 meters long, radius 0.1 meter, named cyl
, with one end at the origin and along the -axis, enter the following code.
cyl = cylinder(pos=vec(0,0,0), axis=vec(1,0,0), radius=0.1, length=5, size=2, color=color.magenta)
The axis can easily be changed to orient a cylinder along the cartesian axes. If it desired for the cylinder to be oriented at an angle, one would use the Pythagorean Theorem or trigonometry to determine the unit vector pointed in the desired direction. Then, this would become the axis vector. For example, a cylinder oriented at in the -plane would be found by
Since we want a unit vector (), and . In Python power are expressed using **
rather than ^
. The command to orient a cylinder at is
cyl = cylinder(pos=vec(0,0,0), axis=vec(0.5**0.5,0.5**0.5,0), radius=0.1, length=5, size=2, color=color.magenta)
However, we may also use trigonometric functions.
cyl = cylinder(pos=vec(0,0,0), axis=vec(cos(pi/4),sin(pi/4),0), radius=0.1, length=5, size=2, color=color.magenta)
B.4.1.3for
loops¶
It is possible to simplify the code using a for
loop. This loop will increment through the desired angles to create the clock face with a single cylinder object command. The advantage is streamlined code. The disadvantage is that the cylinder objects cannot be manipulated unless we complicate the program by tracking the object names. This kind of programming is beyond the scope of this textbook. Figure B.5 shows the code using a for
loop. In this program, we define the number of cylinders we want numcyl
. This number is used to divide into that many angle segments. The for
loop uses the Python range()
function, which is an “inclusive-exclusive” list. That is, for i in range(N):
would increment i
from 0 to N-1. Notice the tabbing after the line beginning the loop indicates which commands are inside the loop.
B.4.1.4User-defined attributes¶
Object attributes are accessed using the “dot” notation. For example, the position of a sphere named ball
can be accessed with ball.pos
. It is possible to add user-defined attributes to an object. Assigning attributes is a simple way to keep track of variables and constants associated with objects. These attributes do not affect the visualization of the object. Some examples of assigning attributes to a sphere named ball
are shown in Table B.2. Users are free to choose the names of the attributes they assign. Rembember that computer code is unit agnostic. The units are whatever the programmer decides, and it is up to the programmer to keep track of units. In this book, we will primarily use SI (or mks) units.
Table B.2:Some examples of user-defined object attributes.
Attribute | Visual Python |
---|---|
mass | ball.m = 5 |
velocity | ball.vel = vec(1,1,1) |
acceleration | ball.acc = vec(0,0,-9.8) |
momentum | ball.p = ball.m * ball.vel |
B.5Move objects using code and physics¶
Once we have objects, we can apply physical principles to make them move. One way to make the ball move is to repeatedly update the position using kinematic descriptions of motion. If we define an object’s position as , the object will change position over time as
Suppose we want to model a situation where there is not acceleration. We could write lines of code that take the current position and update it with some amount . Since we are in a 3D world, we must do this with vectors. For simplicity, let’s assume the velocity is only the -direction that is a speed of , i.e., ball.vel=vec(0.5,0,0)
. Suppose we want to update every second, i.e., t = 0, 1, 2, 3,...
or . To update the position of our object we could write code to position the ball each second that passes.
ball = sphere(pos=vec(0,0,0), radius=0.1, color=color.red)
ball.vel=vec(0.5, 0, 0)
dt = 1
ball.pos = ball.pos + ball.vel * dt #move ball after 1s
ball.pos = ball.pos + ball.vel * dt #move ball after 2s
ball.pos = ball.pos + ball.vel * dt #move ball after 3s
ball.pos = ball.pos + ball.vel * dt # move ball after 4s
ball.pos = ball.pos + ball.vel * dt # move ball after 5s
The statements at the end of the lines after #
are comments that are ignored by the computer. Copy the code above run these lines in the trinket below.
You will see that your program runs all of the lines instantly, and you do not see the motion. Slow the computation down by adding the command rate(1)
between each line updating the ball’s position. This will delay each line by 1 second. For example,
ball.pos = ball.pos + ball.vel * dt
rate(1)
ball.pos = ball.pos + ball.vel * dt
rate(1)
It might also be helpful to keep track of the time and position. To do this, create a variable for time, t
, and add print statements between each move. Notice below that we can access the position with ball.pos.x
.
ball = sphere(pos=vec(0,0,0), radius=0.1, color=color.red)
ball.vel=vec(0.5, 0, 0)
t = 0
dt = 1
print(t, ball.pos.x)
rate(1)
ball.pos = ball.pos + ball.vel * dt #move ball after 1s
t = t + dt #increase the total time
print(t, ball.pos.x)
rate(1)
ball.pos = ball.pos + ball.vel * dt #move ball after 2s
t = t + dt #increase the total time
print(t, ball.pos.x)
rate(1)
ball.pos = ball.pos + ball.vel * dt #move ball after 3s
t = t + dt #increase the total time
print(t, ball.pos.x)
rate(1)
ball.pos = ball.pos + ball.vel * dt # move ball after 4s
t = t + dt #increase the total time
print(t, ball.pos.x)
rate(1)
ball.pos = ball.pos + ball.vel * dt # move ball after 5s
t = t + dt #increase the total time
print(t, ball.pos.x)
Finally, let’s make the ball’s motion obvious by adding a trail to it. In the definition of the ball add make_trail = True
.
ball = sphere(pos=vec(0,0,0), radius=0.1, color=color.red, make_trail=True)
B.5.1while
loops¶
Hopefully it is clear to you this is an inefficient way to write a program, especially if we want to run many iterations of changing the ball’s position. To make the process more streamlined, we use loops. In this case, we will use a while
loop. The while loop runs “while” a condition is met. For example, we can run the ball simulation while the time is less than 5 seconds. Because the loop streamlines the computation, we can get higher time resolution and update the position every 0.1 second. A while
loop looks similar to a for
loop.
while t < 5:
Since we are using the total time as the condition for the while
loop, it is important to keep track of the total time as we did in the previous section. To implement a while
loop, we first initialize variables and objects. Then, every command inside the while
loop will repeat until the condition is met.
#Initialization of objects and variables
ball = sphere(pos=vec(0,0,0), radius=0.1, color=color.red, make_trail=True)
ball.vel=vec(0.5, 0, 0)
t = 0
dt = 0.1
while t < 5:
rate(1)
ball.pos = ball.pos + ball.vel * dt #move ball after dt
t = t + dt #increase the total time
print(t, ball.pos.x) #print time and position
Copy and paste this code to replace the code from the previous section. It will appear to run very slowly. Increase the rate until the motion looks continuous.