Learning Python: Getting Results For Beamlines and Scientific Programming
Learning Python: Getting Results For Beamlines and Scientific Programming
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
1.
2.
3.
4.
5.
6.
Note
that
code
used
in
examples
in
this
talk
are
posted
in
a
le
oct19Examples.zip
on
the
Python
Interest
Group
(PIG)
web
page.
The
Advanced
Photon
Source
is
an
Oce
of
Science
User
Facility
operated
for
the
U.S.
Department
of
Energy
Oce
of
Science
by
Argonne
NaBonal
Laboratory
10/19/11
REVIEW
OF WXPYTHON
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
Create
App
Create
Frame
Start
event
loop
import wx!
class mywxframe(wx.Frame):!
def __init__(self):!
wx.Frame.__init__(self, None)!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
w = wx.StaticText(!
pnl,wx.ID_ANY,'Widget #1')!
sizer.Add(w,0,wx.ALL,10)!
w = wx.StaticText(!
pnl,wx.ID_ANY,'... Widget #2')!
sizer.Add(w,0,wx.ALL,10)!
sizer.Fit(self)!
self.Show()!
!
app = wx.PySimpleApp() # create the App!
frm = mywxframe()!
wx4.py
app.MainLoop()!
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
wx.BoxSizer(wx.HORIZONTAL)
wx.BoxSizer(wx.VERTICAL)
10/19/11
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
wx8.py
wx8a.py
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
Widget ids
Every
widget
in
a
window
(frame)
must
have
a
unique
id
code.
Usually
this
is
done
by
sehng
the
id
parameter
when
a
widget
is
created
to
be
wx.ID_ANY
(which
is
-1).
This
is
oien
the
default.
If
wx.ID_ANY
is
used,
wxPython
creates
a
unique
id.
w = wx.StaticText(pnl,wx.ID_ANY,'Widget #1')
Most
of
the
Bme
one
does
not
care
about
the
id
value.
When
you
do
need
to
know
the
Id
of
a
widget,
it
can
be
obtained
using
<widget>.GetID().
id = w.GetID()!
One
excepBon,
(to
be
shown
later)
there
are
some
commonly
used
widgets,
such
as
Exit
in
menus,
Yes
&
No
bucons
in
dialogs,
wx.Python
denes
standard
Ids
for
these
and
it
is
best
to
use
them.
The
Advanced
Photon
Source
is
an
Oce
of
Science
User
Facility
operated
for
the
U.S.
Department
of
Energy
Oce
of
Science
by
Argonne
NaBonal
Laboratory
10/19/11
RESPONDING
TO EVENTS
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
class mywxframe(wx.Frame):!
def __init__(self):!
wx.Frame.__init__(self, None)!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
btn = wx.Button(pnl, -1,!
"sample button")!
btn.Bind(wx.EVT_BUTTON, self.OnClick)!
sizer.Add(btn,0,wx.ALL,10)!
!
sizer.Fit(self)!
self.Show()!
!
def OnClick(self, event):!
print 'Button pressed'!
wx9.py
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
wx.EVT_BUTTON
wx.EVT_CHECKBOX
wx.EVT_COMBOBOX
wx.EVT_SLIDER
wx.EVT_RADIOBOX!
wx.EVT_MENU!
wx.EVT_CLOSE
wx.EVT_SIZE!
wx.EVT_TEXT_ENTER
wx.EVT_KILL_FOCUS
wx.EVT_SET_FOCUS!
wx.EVT_KEY_UP
wx.EVT_MOUSEWHEEL!
wx.EVT_LEFT_DOWN
wx.EVT_MOTION!
!
!bucon
press
!!
!
!typing
in
a
TextCtrl
! !generated
when
a
widget
is
entered
or
lei
!when
a
keyboard
key
is
released
!
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
10
10/19/11
11
10/19/11
12
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
13
import wx!
class mycalc:!
def __init__(self):!
self.myvar = None!
def SetVar(self,val):!
self.myvar = val!
!
class myframe(wx.Frame):!
This
code
has
two
classes:
def __init__(self):!
wx.Frame.__init__(self, None)!
mycalc
(for
data/computaBon)
&
pnl = wx.Panel(self)!
myframe
(GUI
implementaBon)
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
we
really
want
them
separate
btn = wx.Button(pnl, -1,"read")!
btn.Bind(wx.EVT_BUTTON, self.OnClick)!
sizer.Add(btn,0,wx.ALL,10)!
My
hokey
GUI
example:
pressing
self.tc = wx.TextCtrl(pnl, -1,!
bucon
reads
TextCtrl
and
then
'xxx',size=(100,-1))!
disables
it
so
it
cant
be
changed.
sizer.Add(self.tc,0,wx.ALL,10)
!
sizer.Fit(self)!
self.Show()!
!
The
GUI
part
of
this
is
implemented
def OnClick(self, event):!
here,
but
I
need
to
get
the
value
I
print 'Value = ',self.tc.GetValue()!
read
into
the
mycalc
object.
# but how do I get value into CalcObj?!
self.tc.Disable() # disable the TextCtrl!
How
can
I
do
this?
!
app = wx.PySimpleApp() # create the App!
CalcObj = mycalc()!
frm =of
Energy
myframe()!
The
Advanced
Photon
Source
is
an
Oce
of
Science
User
Facility
operated
for
the
U.S.
Department
Oce
of
Science
by
Argonne
NaBonal
Laboratory
app.MainLoop()!
14
wx10.py
Example of the
information routing
problem
10/19/11
!
class myframe(wx.Frame):!
def __init__(self,DataObj):!
wx.Frame.__init__(self, None)!
self.DataObj = DataObj!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
btn = wx.Button(pnl, -1,"read")!
btn.Bind(wx.EVT_BUTTON, self.OnClick)!
sizer.Add(btn,0,wx.ALL,10)!
self.tc = wx.TextCtrl(pnl, -1,!
'xxx',size=(100,-1))!
sizer.Add(self.tc,0,wx.ALL,10)
!
sizer.Fit(self)!
self.Show()!
!
def OnClick(self, event):!
# here I put the value into CalcObj:!
self.DataObj.SetVar(self.tc.GetValue())!
self.tc.Disable() # disable the TextCtrl!
!
app = wx.PySimpleApp() # create the App!
CalcObj = mycalc()!
frm = myframe(CalcObj)!
app.MainLoop()!
print 'saved val = ',CalcObj.myvar!
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
wx10a.py
15
Save
info
in
dict(s)
indexed
by
widget
Id
or
by
widget
object
that
will
be
used
to
determine
what
the
event
handler
will
do
If
the
event
handler
will
need
to
do
dierent
things
based
on
what
type
of
event
occurred,
also
look
up
the
event
type
Id
(for
example
tId = wx.EVT_BUTTON.typeId).
Use
a
nested
dict?
In
the
event
handler
use
event
parameter
to
get
informaBon
on
the
widget
causing
the
event
and
the
event
type:
event.GetId():
provides
the
Id
of
the
widget
that
generated
the
event
event.GetEventObject():
provides
the
object
that
generated
the
event
event.GetEventType():
provides
the
event
type
Id
10/19/11
16
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
17
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
18
Validators
Validators
are
classes
that
can
be
associated
with
TextCtrl
widgets.
The
validator
can
check
each
character
as
it
is
typed
into
the
box
(and
possibly
ignore
invalid
characters)
or
it
can
check
if
the
contents
is
valid.
I
have
a
pair
of
sample
validators
on
the
PIG
web
page
(le
validators.py:
hcps://conuence.aps.anl.gov/download/acachments/2523138/validators.py)
One
enforces
that
the
values
entered
match
that
of
a
unsigned
or
opBonally
signed
integer.
Any
other
character
is
ignored.
When
the
box
loses
focus,
the
enBre
contents
is
checked
to
make
sure
it
is
a
valid
integer.
If
not,
the
widget
is
highlighted
OpBonally
a
funcBon
can
be
supplied
to
execute
on
a
valid
integer
Minimum
and
maximum
values
can
be
specied
10/19/11
19
Validator example
import wx!
import validators!
class mycalc:!
def __init__(self):!
self.myvar = None!
def SetVar(self,val,obj):!
self.myvar = val!
class mywxframe(wx.Frame):!
def __init__(self,DataObj):!
wx.Frame.__init__(self, None)!
self.DataObj = DataObj!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
!
w = wx.StaticText(pnl, -1,!
"Only integers here")!
sizer.Add(w,0,wx.ALL,10)!
tc = wx.TextCtrl(!
pnl, -1, size=(100,-1),!
validator=validators.IntValidator(!
positiveonly=False))!
sizer.Add(tc,0,wx.ALL,5)!
!
w = wx.StaticText(pnl, -1,"Floats here")!
sizer.Add(w,0,wx.ALL,10)!
tc = wx.TextCtrl(!
pnl, -1,size=(100,-1),!
validator=validators.FloatValidator(!
DataObj.SetVar))!
sizer.Add(tc,0,wx.ALL,5)!
!
sizer.Fit(self)!
self.Show()!
wx11.py
hcps://conuence.aps.anl.gov/download/
acachments/2523138/validators.py)
10/19/11
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
20
Modal dialogs
Modal
dialogs
are
used
to
display
informaBon
to
the
user
(such
as
an
error
message)
or
get
input
from
the
user
via
a
new
window;
the
program
does
not
allow
anything
else
to
occur
unBl
the
user
has
closed
the
new
window.
The
easiest
way
to
implement
a
modal
dialog
is
to
use
one
of
the
many
stock
widgets
in
wxPython,
such
as
DirDialog,
FIleDialog,
MessageDialog,
TextEntryDialog
(~15
choices
in
total)
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
21
MessageDialog Example
class mywxframe(wx.Frame):!
def __init__(self):!
wx.Frame.__init__(self, None)!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
btn = wx.Button(pnl, -1,!
"Show message")!
btn.Bind(wx.EVT_BUTTON,!
self.OnClick)!
sizer.Add(btn,0,wx.ALL,10)!
self.Show()!
!
def OnClick(self, event):!
dlg = wx.MessageDialog(self,!
"Prompt:\n\tYou rang?",!
'Title: Waddayawant?',!
wx.OK | wx.CANCEL |!
wx.ICON_QUESTION)!
if dlg.ShowModal() == wx.ID_OK:!
print "OK!"!
dlg.Destroy()!
wx12.py
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
22
FileDialog Example
class mywxframe(wx.Frame):!
def __init__(self):!
wx.Frame.__init__(self, None)!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
btn = wx.Button(pnl, -1,!
"Get file")!
btn.Bind(wx.EVT_BUTTON, self.OnClick)!
sizer.Add(btn,0,wx.ALL,10)!
sizer.Fit(self)!
self.Show()!
!
def OnClick(self, event):!
wildcard = "pickle files (*.pkl)|*.pkl"!
dlg = wx.FileDialog(!
self, message="Save as...", !
defaultDir="/tmp", !
defaultFile="test.pkl",!
wildcard=wildcard,!
#style=wx.FD_OPEN!
style=wx.FD_SAVE)!
if dlg.ShowModal() == wx.ID_OK:!
print 'path = ',dlg.GetPath()!
else:!
print 'Cancelled!'!
wx12a.py
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
23
10/19/11
24
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
25
Non-modal windows
import wx!
class mywxframe(wx.Frame):!
def __init__(self,parent,lbl):!
wx.Frame.__init__(self, parent)!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
w = wx.StaticText(pnl, -1, lbl)!
sizer.Add(w,0,wx.ALL,10)!
sizer.Fit(self)!
self.Show()!
!
app = wx.PySimpleApp() # create the App!
frm1 = mywxframe(None, '1st window')!
frm2 = mywxframe(None, '2nd window')!
frm3 = mywxframe(None, '3rd window')!
app.MainLoop()!
print 'event loop done'!
wx13.py
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
26
Child windows
import wx!
class mywxframe(wx.Frame):!
def __init__(self,parent,lbl):!
wx.Frame.__init__(self, parent)!
pnl = wx.Panel(self)!
sizer = wx.BoxSizer(wx.VERTICAL)!
pnl.SetSizer(sizer)!
w = wx.StaticText(pnl, -1, lbl)!
sizer.Add(w,0,wx.ALL,10)!
sizer.Fit(self)!
self.Show()!
!
app = wx.PySimpleApp() # create the App!
frm1 = mywxframe(None, '1st window')!
frm2 = mywxframe(frm1, '2nd window\nchild of 1st')!
frm3 = mywxframe(frm2, '3rd window\nchild of 2nd')!
app.MainLoop()!
print 'event loop done!
wx13a.py
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
27
Homework
Create
a
small
wxPython
program
to
do
something
useful.
Let
me
know
what
you
did
or
where
you
get
stuck.
The Advanced Photon Source is an Oce of Science User Facility operated for the U.S. Department of Energy Oce of Science by Argonne NaBonal Laboratory
10/19/11
28