VPython GUIs: Difference between revisions

From Physics Book
Jump to navigation Jump to search
(Created page with "Adding interactivity to VPython simulations ==The Main Idea== VPython is the powerful tool for simulations used in this course. So far, we have seen how to create simulatio...")
 
No edit summary
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
Adding interactivity to VPython simulations
This article details how to add interactivity to VPython simulations.
 


==The Main Idea==
==The Main Idea==
Line 10: Line 9:
===Initialization===
===Initialization===
Apart from the basic import statements required for any VPython programs, i.e. …
Apart from the basic import statements required for any VPython programs, i.e. …
<code>
from __future__ import divison
from __future__ import divison
from visual import *
from visual import *
</code>


… we also need to add the following lines:
… we also need to add the following lines:
<code>
import wx
import wx
</code>


Here, “wx” imports wxPython, the library that allows us to create all of the interactivity GUI elements.
Here, “wx” imports wxPython, the library that allows us to create all of the interactivity GUI elements.


===New Functions===
===Motivation===
window(width, height, menus, title, style)
:Creates a new window of size width x height
 
===Example – Modified spacevoyage.py===


In some lab exercises, we were required to simulate a spring's motion. When we were testing multiple input constants – e.g. <math>k_s</math> (the spring constant), the mass of the ball, <math>L_0</math> (the spring's relaxed length), or the initial position of the spring, we had to update our Python code every time we wanted to change the initial values. With our interactivity elements, we can update initial conditions (constants) while the simulation is running, which is much easier and more intuitive – and might make lab work quicker by allowing you to update your simulation on the fly.
In some lab exercises, we were required to simulate a spring's motion. When we were testing multiple input constants – e.g. <math>k_s</math> (the spring constant), the mass of the ball, <math>L_0</math> (the spring's relaxed length), or the initial position of the spring, we had to update our Python code every time we wanted to change the initial values. With our interactivity elements, we can update initial conditions (constants) while the simulation is running, which is much easier and more intuitive – and might make lab work quicker by allowing you to update your simulation on the fly.
Line 28: Line 31:
===Creating the window===
===Creating the window===
To create the window, we'll write:
To create the window, we'll write:
<code>
myWindow = window(title='Spring Energy Simulation')
myWindow = window(title='Spring Energy Simulation')
</code>


Then, we need to get the contents of the panel inside the window:
Then, we need to get the contents of the panel inside the window:
<code>
myPanel = myWindow.panel
myPanel = myWindow.panel
</code>


Let's write a bit of text inside the panel window as well. Assume we don't want this text to change:
Let's write a bit of text inside the panel window as well. Assume we don't want this text to change:
<code>
wx.StaticText(myPanel, pos=(d,4), size=(L-2*d,d), label='Displayed below is the spring energy simulator:', style=wx.ALIGN_CENTRE)
wx.StaticText(myPanel, pos=(d,4), size=(L-2*d,d), label='Displayed below is the spring energy simulator:', style=wx.ALIGN_CENTRE)
</code>


Let's initialize some constants:
Let's initialize some constants:
<syntaxhighlight lang=”python”>
 
<code>
g = 9.8
g = 9.8
mball = 0.5
mball = 0.5
L0 = 0.3
L0 = 0.3
ks = 12
ks = 12
deltat  = 1e-13
deltat  = 1e-13
speed = 10
speed = 10
</syntaxhighlight>
</code>


We're familiar with most of these as constants, but the main difference when we are adding interactivity is that we will be able to change these constants while our simulation is running.  
We're familiar with most of these as constants, but the main difference when we are adding interactivity is that we will be able to change these constants while our simulation is running.  


Next, we have an option: we may either put our spring visualization in a separate window. In this case, we do nothing special. Otherwise, we may put itinside the same window we just created, along with the rest of the widgets. In the latter case, we can add the following line of code:
Next, we have an option: we may either put our spring visualization in a separate window. In this case, we do nothing special. Otherwise, we may put itinside the same window we just created, along with the rest of the widgets. In the latter case, we can add the following lines of code:
 
<code>
d = 20
d = 20
offset = 30
offset = 30
myDisplay = display(window=myWindow, x=offset, y=offset, width=L-2*d, height=L-2*d)
myDisplay = display(window=myWindow, x=offset, y=offset, width=L-2*d, height=L-2*d)
</code>
===Handling user input===
===Handling user input===
Now, we may create some input boxes that will allow us to change the value of our constants.
Now, we may create some input boxes that will allow us to change the value of our constants.


====Text input boxes====
====Text input boxes====
<syntaxhighlight lang=”python”>
<code>
textBoxDims=(150, 15)
textBoxDims=(150, 15)
gEntry = wx.TextCtrl(myPanel, pos=(1.4*L, 90), value=str(g), size=textBoxDims, style= TE_PROCESS_ENTER)
gEntry = wx.TextCtrl(myPanel, pos=(1.4*L, 90), value=str(g), size=textBoxDims, style= TE_PROCESS_ENTER)
mBallEntry = wx.TextCtrl(myPanel, pos=(1.4*L, 110), value=str(mball),
mBallEntry = wx.TextCtrl(myPanel, pos=(1.4*L, 110), value=str(mball),
size=textBoxDims, style=TE_PROCESS_ENTER)
size=textBoxDims, style=TE_PROCESS_ENTER)
Lentry = wx.TextCtrl(myPanel, pos=(1.4*L, 130), value=str(L0), size=textBoxDims, style=TE_PROCESS_ENTER)
Lentry = wx.TextCtrl(myPanel, pos=(1.4*L, 130), value=str(L0), size=textBoxDims, style=TE_PROCESS_ENTER)
ksEntry = wx.TextCtr(myPanel, pos=(1.4*L, 150), value=str(ks), size=textBoxDims, style=TE_PROCESS_ENTER)
ksEntry = wx.TextCtr(myPanel, pos=(1.4*L, 150), value=str(ks), size=textBoxDims, style=TE_PROCESS_ENTER)
</syntaxhighlight>
</code>


We'll also create a slider that will allow us to change the speed of our animation.
We'll also create a slider that will allow us to change the speed of our animation.


<code>
speedEntry = wx.Slider(myPanel, pos=(1.4*L, 190), size=(0.9*L, 20), minValue=50, maxValue=1e4)
speedEntry = wx.Slider(myPanel, pos=(1.4*L, 190), size=(0.9*L, 20), minValue=50, maxValue=1e4)
speedEntry.SetValue(50)
speedEntry.SetValue(50)
 
</code>


====Callback functions====
====Callback functions====
As mentioned before, putting new values into our input boxes allows us to update the values of the constants defined earlier. In order to do so, we need to define some functions that will update the values of our constants.  
As mentioned before, putting new values into our input boxes allows us to update the values of the constants defined earlier. In order to do so, we need to define some functions that will update the values of our constants. These are "callback" functions - i.e the content of the function will be executed if we click, press enter, or in some way modify our input elements.


<syntaxhighlight lang=”python”>
<code>
def updateG(evt):
def updateG(evt):
     global g
     global g
Line 110: Line 141:
     global speed
     global speed
     speed = speedEntry.GetValue()
     speed = speedEntry.GetValue()
</syntaxhighlight>
</code>


Here, what we are doing is telling VPython to update the “global” constants ks, G, mball, etc. We are then making sure that the user is not trying to set these numerical values to strings (a sequence of letters).
Here, what we are doing is telling VPython to update the “global” constants ks, G, mball, etc. We are then making sure that the user is not trying to set these numerical values to strings (a sequence of letters).


We also need to bind these functions to the input widgets as “listeners.”
We also need to bind these functions to the input widgets as “listeners.”
<syntaxhighlight lang=”python”>
<code>
 
gEntry.Bind(wx.EVT_TEXT_ENTER, updateG)
gEntry.Bind(wx.EVT_TEXT_ENTER, updateG)
mBallEntry.Bind(wx.EVT_TEXT_ENTER, updateMBall)
mBallEntry.Bind(wx.EVT_TEXT_ENTER, updateMBall)
Lentry.Bind(wx.EVT_TEXT_ENTER, updateL0)
Lentry.Bind(wx.EVT_TEXT_ENTER, updateL0)
ksEntry.Bind(wx.EVT_TEXT_ENTER, updateKS)
ksEntry.Bind(wx.EVT_TEXT_ENTER, updateKS)
speedEntry.Bind(wx.EVT_SCROLL, updateSpeed)
speedEntry.Bind(wx.EVT_SCROLL, updateSpeed)
</syntaxhighlight>
</code>


Let's also add a function that reinitializes the entire animation.
Let's also add a function that reinitializes the entire animation.
<code>
def resetAnimation(evt):
def resetAnimation(evt):
ceiling.pos = initialCeilingPos
ceiling.pos = initialCeilingPos
Line 130: Line 167:
ball.p = mball*vector(0,0,0)
ball.p = mball*vector(0,0,0)
vball = initialBallVelocity
vball = initialBallVelocity
<code>


Finally, we will add a button calling that function.
Finally, we will add a button calling that function.
<code>
resetBtn = wx.Button(myPanel, label=”Reset animation”, pos=(1.4*L, 170))
resetBtn = wx.Button(myPanel, label=”Reset animation”, pos=(1.4*L, 170))
resetBtn.Bind(EVT_BUTTON, resetAnimation)
resetBtn.Bind(EVT_BUTTON, resetAnimation)
</code>


===Running the simulation===
===Running the simulation===
Line 140: Line 182:
===Sample code===
===Sample code===


Some sample code for the spring application is located [https://github.com/raghavkaul/vpythonexamples/blob/master/vpythondemo.py here]
Some sample code for the spring application may be found [https://github.com/raghavkaul/vpythonexamples/blob/master/vpythondemo.py here]


==Connectedness==
==Connectedness==
#How is this topic connected to something that you are interested in?
#How is this topic connected to something that you are interested in?
I try to make my own work easier. GUIs always help me, and hopefully other users, manipulate physics simulations more easily than changing hard-coded variables and make VPython a more user-friendly tool.


#How is it connected to your major?
#How is it connected to your major?
As a CS major, I try to make my own work easier. GUIs always help me, and hopefully other users, manipulate physics simulations more easily than changing hard-coded variables and make VPython a more user-friendly tool.
As a CS major, applications programming is a big component of the discipline.


#Is there an interesting industrial application?
#Is there an interesting industrial application?
Line 154: Line 197:


wxPython is a GUI library for the Python programming languages that allows users to quickly deploy desktop applications. The wx toolkit was included as part of VPython 6, allowing users to easily write GUIs for VPython programs instead of using the VPython default window displays.
wxPython is a GUI library for the Python programming languages that allows users to quickly deploy desktop applications. The wx toolkit was included as part of VPython 6, allowing users to easily write GUIs for VPython programs instead of using the VPython default window displays.
== See also ==
Are there related


===Further reading and external links===
===Further reading and external links===


Books, Articles or other print media on this topic
[http://www.wxpython.org/docs/api/ WxPython API]
 
 
==References==
 
This section contains the the references you used while writing this page


[[Category:Which Category did you place this in?]]
[https://github.com/BruceSherwood/vpython-wx/blob/master/site-packages/visual/examples/ Additional Vpython GUI examples]

Latest revision as of 23:57, 5 December 2015

This article details how to add interactivity to VPython simulations.

The Main Idea

VPython is the powerful tool for simulations used in this course. So far, we have seen how to create simulations that visualize a physical system/surroundings based on a given input. However, VPython is powerful enough to add several GUI features for interactivity, such as buttons, sliders, menus, and text input that allow the user to modify simulations as they run.

One important note is that these features are newly introduced in VPython 6, and may require you to update your VPython version before usage.

Initialization

Apart from the basic import statements required for any VPython programs, i.e. …

from __future__ import divison

from visual import *

… we also need to add the following lines:

import wx

Here, “wx” imports wxPython, the library that allows us to create all of the interactivity GUI elements.

Motivation

In some lab exercises, we were required to simulate a spring's motion. When we were testing multiple input constants – e.g. [math]\displaystyle{ k_s }[/math] (the spring constant), the mass of the ball, [math]\displaystyle{ L_0 }[/math] (the spring's relaxed length), or the initial position of the spring, we had to update our Python code every time we wanted to change the initial values. With our interactivity elements, we can update initial conditions (constants) while the simulation is running, which is much easier and more intuitive – and might make lab work quicker by allowing you to update your simulation on the fly.

Creating the window

To create the window, we'll write:

myWindow = window(title='Spring Energy Simulation')

Then, we need to get the contents of the panel inside the window:

myPanel = myWindow.panel

Let's write a bit of text inside the panel window as well. Assume we don't want this text to change:

wx.StaticText(myPanel, pos=(d,4), size=(L-2*d,d), label='Displayed below is the spring energy simulator:', style=wx.ALIGN_CENTRE)

Let's initialize some constants:

g = 9.8

mball = 0.5

L0 = 0.3

ks = 12

deltat = 1e-13

speed = 10

We're familiar with most of these as constants, but the main difference when we are adding interactivity is that we will be able to change these constants while our simulation is running.

Next, we have an option: we may either put our spring visualization in a separate window. In this case, we do nothing special. Otherwise, we may put itinside the same window we just created, along with the rest of the widgets. In the latter case, we can add the following lines of code:

d = 20

offset = 30

myDisplay = display(window=myWindow, x=offset, y=offset, width=L-2*d, height=L-2*d)

Handling user input

Now, we may create some input boxes that will allow us to change the value of our constants.

Text input boxes

textBoxDims=(150, 15)

gEntry = wx.TextCtrl(myPanel, pos=(1.4*L, 90), value=str(g), size=textBoxDims, style= TE_PROCESS_ENTER)

mBallEntry = wx.TextCtrl(myPanel, pos=(1.4*L, 110), value=str(mball),

size=textBoxDims, style=TE_PROCESS_ENTER)

Lentry = wx.TextCtrl(myPanel, pos=(1.4*L, 130), value=str(L0), size=textBoxDims, style=TE_PROCESS_ENTER)

ksEntry = wx.TextCtr(myPanel, pos=(1.4*L, 150), value=str(ks), size=textBoxDims, style=TE_PROCESS_ENTER)

We'll also create a slider that will allow us to change the speed of our animation.

speedEntry = wx.Slider(myPanel, pos=(1.4*L, 190), size=(0.9*L, 20), minValue=50, maxValue=1e4)

speedEntry.SetValue(50)

Callback functions

As mentioned before, putting new values into our input boxes allows us to update the values of the constants defined earlier. In order to do so, we need to define some functions that will update the values of our constants. These are "callback" functions - i.e the content of the function will be executed if we click, press enter, or in some way modify our input elements.

def updateG(evt):

   global g
   newG = gEntry.GetValue()
   try:
       g = float(newG)
   except ValueError:
       pass
   

def updateMBall(evt):

   global mball
   newMBall = mBallEntry.GetValue()
   try:
       mball = float(newMBall)
   except ValueError:
       pass

def updateL0(evt):

   global L0
   newL0 = Lentry.GetValue()
   try:
       L0 = float(newL0)
   except ValueError:
       pass

def updateKS(evt):

   global ks
   newKS = ksEntry.GetValue()
   try:
       ks = float(newKS)
   except ValueError:
       pass

def updateSpeed(evt):

   global speed
   speed = speedEntry.GetValue()

Here, what we are doing is telling VPython to update the “global” constants ks, G, mball, etc. We are then making sure that the user is not trying to set these numerical values to strings (a sequence of letters).

We also need to bind these functions to the input widgets as “listeners.”

gEntry.Bind(wx.EVT_TEXT_ENTER, updateG)

mBallEntry.Bind(wx.EVT_TEXT_ENTER, updateMBall)

Lentry.Bind(wx.EVT_TEXT_ENTER, updateL0)

ksEntry.Bind(wx.EVT_TEXT_ENTER, updateKS)

speedEntry.Bind(wx.EVT_SCROLL, updateSpeed)

Let's also add a function that reinitializes the entire animation. def resetAnimation(evt): ceiling.pos = initialCeilingPos ball.pos = initialBallPos spring.length = initialBallLength ball.p = mball*vector(0,0,0) vball = initialBallVelocity

Finally, we will add a button calling that function.

resetBtn = wx.Button(myPanel, label=”Reset animation”, pos=(1.4*L, 170))

resetBtn.Bind(EVT_BUTTON, resetAnimation)

Running the simulation

In order to run the simulation, we essentially do the same thing we have done previously – we use a while loop and put all of our variables/updates into the while loop. However, we actually need to nest the entire while loop in a secondary while loop

Sample code

Some sample code for the spring application may be found here

Connectedness

  1. How is this topic connected to something that you are interested in?

I try to make my own work easier. GUIs always help me, and hopefully other users, manipulate physics simulations more easily than changing hard-coded variables and make VPython a more user-friendly tool.

  1. How is it connected to your major?

As a CS major, applications programming is a big component of the discipline.

  1. Is there an interesting industrial application?

There are many applications of GUIs – they make physics simulations more accessible to people with no programming background, and can speed up lab work and support quick modifications.

History

wxPython is a GUI library for the Python programming languages that allows users to quickly deploy desktop applications. The wx toolkit was included as part of VPython 6, allowing users to easily write GUIs for VPython programs instead of using the VPython default window displays.

Further reading and external links

WxPython API

Additional Vpython GUI examples