Dokumen - Tips - Python Tutorial Ets Tutorial
Dokumen - Tips - Python Tutorial Ets Tutorial
Intended Audience
Use Python to build interactive desktop
applications
Introduction
Outline
1 Introduction
ODE 101
2 Traits
3 TraitsUI
4 Chaco
5 Mayavi
6 Putting it all together
7 Note on Envisage
8 Summary
Introduction
Introduction
Approach
Introduction
Why?
Outline
1 Introduction
ODE 101
2 Traits
3 TraitsUI
4 Chaco
5 Mayavi
6 Putting it all together
7 Note on Envisage
8 Summary
ODE 101
Simple equation
dx
= f (x t ) , (1)
dt
x can be a vector with many components.
In []: plot(t, y)
Result
dx
= s (y − x )
dt
dy
= rx − y − xz
dt
dz
= xy − bz
dt
Solution
import numpy as np
from scipy.integrate import odeint
def lorenz(r, t s=10.,r=28., b=8./3.):
x, y, z = r
u = s*(y-x)
v = r*x - y - x*z
w = x*y - b*z
return np.array([u, v, w])
mlab.plot3d(x, y, z, t,
from mayavi import mlab
tube_radius=None)
Now what?
Miscellaneous libraries
Traits
Outline
1 Introduction
ODE 101
2 Traits
3 TraitsUI
4 Chaco
5 Mayavi
6 Putting it all together
7 Note on Envisage
8 Summary
Traits
Introduction to Traits
http://code.enthought.com/projects/
traits
http://github.enthought.com/traits/
tutorials
Traits
Trait features
Traits Example
from traits.api import (Delegate, HasTraits,
Instance, Int, Str)
class Parent(HasTraits):
# INITIALIZATION: ’last_name’ initialized to ’’
last_name = Str(’’)
class Child(HasTraits):
age = Int
# VALIDATION: ’father’ must be Parent instance
father = Instance(Parent)
# DELEGATION: ’last_name’ delegated to father’s
last_name = Delegate(’father’)
# NOTIFICATION: Method called when ’age’ changes
def _age_changed(self, old, new):
print ’Age changed from %s to %s ’ % (old, new)
Traits Example
from traits.api import (Delegate, HasTraits,
Instance, Int, Str)
class Parent(HasTraits):
# INITIALIZATION: ’last_name’ initialized to ’’
last_name = Str(’’)
class Child(HasTraits):
age = Int
# VALIDATION: ’father’ must be Parent instance
father = Instance(Parent)
# DELEGATION: ’last_name’ delegated to father’s
last_name = Delegate(’father’)
# NOTIFICATION: Method called when ’age’ changes
def _age_changed(self, old, new):
print ’Age changed from %s to %s ’ % (old, new)
Traits Example
10 m
Standard:
Bool, Int, Float, Str, Tuple, List, Dict
Constrained:
Range, Regex, Expression, ReadOnly
Special:
Either, Enum, Array, File, Color, Font
...
Static: def _<trait_name>_changed()
Decorator:
@on_trait_change(’extended.trait[].name’)
Dynamic:
obj.on_trait_change(handler,
[’extended.trait[].name’])
Notification Example
class Parent(HasTraits):
last_name = Str(’’)
class Child(HasTraits):
age = Int
father = Instance(Parent)
@on_trait_change(’father.last_name’)
def _dad_name_updated(self):
print self.father.last_name
c = Child(father=Parent(last_name=’Ram’))
c.on_trait_change(handler, [’father’, ’age’])
Notification Example
class Parent(HasTraits):
last_name = Str(’’)
class Child(HasTraits):
age = Int
father = Instance(Parent)
@on_trait_change(’father.last_name’)
def _dad_name_updated(self):
print self.father.last_name
c = Child(father=Parent(last_name=’Ram’))
c.on_trait_change(handler, [’father’, ’age’])
Traits
Think!
Traits
Think!
Traits
Object model
Lorenz Equation
import numpy as np
from traits.api import HasTraits, Float
class LorenzEquation(HasTraits):
s = Float(10)
r = Float(28)
b = Float(8./3)
class ODE(HasTraits):
""" An ODE of the form dX/dt = f(X) """
name = Str
vars = Either(List(Str), Str,
desc=’The names of variables’)
def eval(self, X, t):
""" Evaluate the derivative, f(X).
"""
raise NotImplementedError
class LorenzEquation(ODE):
name = ’Lorenz Equation’
vars = [’x’, ’y’, ’z’]
s = Float(10)
r = Float(28)
b = Float(8./3)
Or . . .
class LorenzEquation(HasTraits):
# ...
s = Range(0.0, 20.0, 10.0,
desc=’the parameter s’)
r = Range(0.0, 50.0, 28.0)
b = Range(0.0, 10.0, 8./3)
# ...
solution = Property(Array,
depends_on=’initial_state, t, ode’)
@cached_property
def _get_solution(self):
return self.solve()
def solve(self):
""" Solve the ODE and return the values
of the solution vector at specified times t.
"""
from scipy.integrate import odeint
return odeint(self.ode.eval, self.initial_state,
self.t)
solution = Property(Array,
depends_on=’initial_state, t, ode’)
@cached_property
def _get_solution(self):
return self.solve()
def solve(self):
""" Solve the ODE and return the values
of the solution vector at specified times t.
"""
from scipy.integrate import odeint
return odeint(self.ode.eval, self.initial_state,
self.t)
solution = Property(Array,
depends_on=’initial_state, t, ode’)
@cached_property
def _get_solution(self):
return self.solve()
def solve(self):
""" Solve the ODE and return the values
of the solution vector at specified times t.
"""
from scipy.integrate import odeint
return odeint(self.ode.eval, self.initial_state,
self.t)
Testing
class TestLorenzEquation(unittest.TestCase):
def setUp(self):
self.ode = LorenzEquation()
self.solver = ODESolver(ode=self.ode)
self.solver.initial_state = [10.,50.,50.]
self.solver.t = numpy.linspace(0, 10, 1001)
def test_eval(self):
dX = self.ode.eval(self.solver.initial_state, 0.0)
self.assertAlmostEqual(dX[0], 400)
self.assertAlmostEqual(dX[1], -270)
self.assertAlmostEqual(dX[2], 1100/3.)
def test_solve(self):
soln = self.solver.solution[1,:]
self.assertAlmostEqual(soln[0], 13.65484958)
self.assertAlmostEqual(soln[1], 46.64090341)
self.assertAlmostEqual(soln[2], 54.35797299)
Exercise
Solve an ODE
Use the given skeleton code of the ODE equation
(solve_ode.py) and the solver. Put them together to
get a solution. Print the final solution.
TraitsUI
Outline
1 Introduction
ODE 101
2 Traits
3 TraitsUI
4 Chaco
5 Mayavi
6 Putting it all together
7 Note on Envisage
8 Summary
TraitsUI
TraitsUI
father = Parent(last_name=’Joe’)
child = Child(age=2, father=father)
child.configure_traits()
Declarative
Automatic UI creation with
configure_traits()
Sync with model
Sync between different views
father = Parent(last_name=’Joe’)
child = Child(age=2, father=father)
child.configure_traits()
Declarative
Automatic UI creation with
configure_traits()
Sync with model
Sync between different views
Simplest view
MVC?
view = View(Item(’s’),
Item(’r’),
Item(’b’))
eq = LorenzEquation()
eq.configure_traits(view=view)
Groups
Exercise
Chaco
Outline
1 Introduction
ODE 101
2 Traits
3 TraitsUI
4 Chaco
5 Mayavi
6 Putting it all together
7 Note on Envisage
8 Summary
Chaco
Chaco
2D plotting library
Embeddable in any wx/Qt application
Fast and interactive visualizations
Integrates well with Traits and TraitsUI
Easily extensible to create new types of plots and
interactions
Chaco
Chaco
Core Ideas
Chaco
class LinePlot(HasTraits):
plot = Instance(Plot)
traits_view = View(
Item(’plot’,editor=ComponentEditor(),
show_label=False),
width=500, height=500,
resizable=True,
title="Chaco Plot")
The Plot view, plot and the ODE solution. ODE can be
obtained from ODESolver, so it can be a property.
class ODEPlot(HasTraits):
""" A 2D plot of ode solution variables. """
plot = Instance(Component)
# We need to set data when solution changes
pd = Instance(ArrayPlotData, args=())
def _get_ode(self):
return self.solver and self.solver.ode
...
def _plot_default(self):
self.pd.set_data(’index’, self.solver.t)
# Set the first array as value array for plot.
self.pd.set_data(’value’,
self.solver.solution[:,0])
plot = Plot(self.pd)
plot.plot((’index’, ’value’))
return plot
Mayavi
Outline
1 Introduction
ODE 101
2 Traits
3 TraitsUI
4 Chaco
5 Mayavi
6 Putting it all together
7 Note on Envisage
8 Summary
Mayavi
Mayavi
A simple plot
1D data
>>> mlab.plot3d(x, y, z, t)
Embedding a 3D plot
from mayavi.core.ui.api import MayaviScene, \
MlabSceneModel, SceneEditor
class Plot3D(HasTraits):
scene = Instance(MlabSceneModel, args=())
view = View(Item(name=’scene’,
editor=SceneEditor(
scene_class=MayaviScene),
show_label=False, resizable=True,
height=500, width=500),
resizable=True)
@on_trait_change(’scene.activated’)
def generate_data(self):
# Create some data
X, Y = mgrid[-2:2:100j, -2:2:100j]
R = 1 0*sqrt(X**2 + Y**2)
Z = sin(R)/R
self.scene.mlab.surf(X,Y,Z,colormap=’gist_earth’)
Embedding a 3D plot
from mayavi.core.ui.api import MayaviScene, \
MlabSceneModel, SceneEditor
class Plot3D(HasTraits):
scene = Instance(MlabSceneModel, args=())
view = View(Item(name=’scene’,
editor=SceneEditor(
scene_class=MayaviScene),
show_label=False, resizable=True,
height=500, width=500),
resizable=True)
@on_trait_change(’scene.activated’)
def generate_data(self):
# Create some data
X, Y = mgrid[-2:2:100j, -2:2:100j]
R = 1 0*sqrt(X**2 + Y**2)
Z = sin(R)/R
self.scene.mlab.surf(X,Y,Z,colormap=’gist_earth’)
Exercise
Solution
Outline
1 Introduction
ODE 101
2 Traits
3 TraitsUI
4 Chaco
5 Mayavi
6 Putting it all together
7 Note on Envisage
8 Summary
The application
Exercise
ODE application
Given the existing code, in solve_ode.py and
embed_3d_ex.py create a UI for the Lorenz equation
along with the solver and a 3D or 2D plot.
So what?
What next?
Note on Envisage
Outline
1 Introduction
ODE 101
2 Traits
3 TraitsUI
4 Chaco
5 Mayavi
6 Putting it all together
7 Note on Envisage
8 Summary
Note on Envisage
Envisage
Extensible framework
Plugins
ExtensionPoints
Extensions
Similar to Eclipse
Note on Envisage
Application frameworks . . .
Central idea
Developer focuses on making a clean library
Framework API specifies how different pieces of
the app interact
Plugin writer exposes the library or objects
involved into the framework
Application writer uses plugins to create new
application easily
Note on Envisage
Application frameworks . . .
MPL
Matplotlib Plugin
library
TVTK
TVTK Plugin Envisage
Application END
wxPython
USER
Shell
Shell Framework
Plugin
Code editor
Editor
Plugin
Note on Envisage
Big picture
Note on Envisage
Big picture
Note on Envisage
Envisage application
Envisage application
Extension Registry
Extensions
Plugin Plugin
Services
Service Registry
Summary
Outline
1 Introduction
ODE 101
2 Traits
3 TraitsUI
4 Chaco
5 Mayavi
6 Putting it all together
7 Note on Envisage
8 Summary
Summary
Summary
Traits
TraitsUI
Chaco
Mayavi
Envisage