In [1]:
from IPython.display import Image
Image(filename='Figs_ipandcg_2014/2014_Session_1.png')
Out[1]:

In this exercise you will learn how to build simple application with Graphical User Interface (GUI). For this purpose wxPython libraries will be used. Presented examples base on the on-line tutorial.

In the cell below we import all needed packages.

In [49]:
import numpy as np
from scipy import misc
from IPython.display import Image
import matplotlib.pyplot as plt

Empty window

In the first task create an empty, blank window, as you can see at the figure below. To get more information see example.

In [38]:
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/1_empty_window.png")
Out[38]:

The source code is listed belove followes. There is an IPython magic command %reset in the first line. It should be added only wehen you are using IPython notebook as you editor. If case of regular Python script (with .py extention) this line is optional and can be omitted. It is (strongly) reccomended to use regular script while practicing with wxPython library.

In [35]:
%reset
# Empty window

#!/usr/bin/python
# simple.py

import wx

app = wx.App()
frame = wx.Frame(None, -1, 'simple.py')
frame.Show()
app.MainLoop()
Once deleted, variables cannot be recovered. Proceed (y/[n])? y

To get help with Keyboard Shortcuts of IPython notebook press "Ctrl+m h". Practice how to add, remove, delete and execute a new cell. You can turn on/off line numbers inside cell with the use of "Ctrl+m l" keys sequence.

Empty window - modifications (background colour, text)

To the existing window add a control to display text (wxStaticText). Place it in the center of the window. Change background color; use different manners of setting couour(use wx.Frame.SetBackgroundColour() function and wx.Colour class and String). Explain each line of the source code.

In [36]:
%reset
import wx

app = wx.App()  

frame = wx.Frame(None, -1, 'Name :D')
#frame.SetBackgroundColour(wx.Colour(255,255,255))
#frame.SetBackgroundColour((255,100,55))
frame.SetBackgroundColour("Red")
frame.Show()

text = wx.StaticText(frame, -1, "Some text ;-)",(110,50))
#text.Center()

app.MainLoop()
Once deleted, variables cannot be recovered. Proceed (y/[n])? y

In [39]:
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/1a_empty_window_modification.png")
Out[39]:

Application with 3 buttons

Based on tutorial write an application that contains three buttons. Use booth methods for layout your widgets:

In [40]:
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/2_buttons_manual.png")
Out[40]:
In [41]:
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/2_buttons_sizers.png")
Out[41]:

Remember! To get help use "?" mark

wx.Button?

Three buttons application without sizers

Use help and explain meaning of each line. What is the result when the window size is changed?

In [42]:
%reset
#!/usr/bin/python

# layout.py

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition)

        panel = wx.Panel(self, -1)
        wx.Button(panel, 1, "Button1", (0,0))
        wx.Button(panel, 2, "Button2", (80,0))
        wx.Button(panel, 3, "Button3", (180,0))
        self.SetSize((300,100))
        

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, -1, 'layout.py')
        frame.Show(True)
        frame.Centre()
        return True

app = MyApp(0)
app.MainLoop()
Once deleted, variables cannot be recovered. Proceed (y/[n])? y

How to connect some action with the buttons?

Based on tutorial observe and explain how to bind any action with your buttons.

Write this piece of code in the regular Python script.

In [43]:
%reset
#!/usr/bin/python

# layout.py

import wx
import numpy as np

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition)

        panel = wx.Panel(self, -1)
        wx.Button(panel, 1, "Button1", (0,0))
        wx.Button(panel, 2, label="Button2", pos=(80,0))
        wx.Button(panel, id=3, label="Button3", pos=(180,0))
        self.SetSize((300,100))
        
        self.Bind(wx.EVT_BUTTON, self.OnPrint, id=1)
        self.Bind(wx.EVT_BUTTON, self.OnPrint, id=2)
        self.Bind(wx.EVT_BUTTON, self.OnPrint, id=3)
        
        
    def OnPrint(self,event):
        #print  'button nr.', event.GetId()
        #print event.GetEventObject().GetLabel()
        event.GetEventObject().SetBackgroundColour(np.random.random_integers(0,255,3))
        

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, -1, 'layout.py')
        frame.Show(True)
        frame.Centre()
        return True

app = MyApp(0)
app.MainLoop()
Once deleted, variables cannot be recovered. Proceed (y/[n])? y

Check the usage of function random.random_integers from numpy package.

In [44]:
np.random.random_integers(0,10,3)
Out[44]:
array([1, 9, 4])

Three buttons application with a use of sizer

For volunteers: plaease find a very nice tutorial on sizers.

Use help and explain meaning of each line and every parameter. What is happend when the window size is changed?

In [45]:
% reset

#!/usr/bin/python

# wxboxsizer.py

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, (-1, -1), wx.Size(250, 50))
        panel = wx.Panel(self, -1)
        box = wx.BoxSizer(wx.HORIZONTAL)
        
        self.button1 = wx.Button(panel, id=wx.ID_ANY, label='Button nr 1')
        self.button2 = wx.Button(panel, id=wx.ID_ANY, label='Button 2')
        self.button3 = wx.Button(panel, id=wx.ID_ANY, label='Button 3 - very long name')
        
        box.Add(self.button1, 0, wx.EXPAND | wx.ALL, border=5 )
        box.Add(self.button2, 1, wx.EXPAND | wx.ALL, border=15 )
        box.Add(self.button3, 2, wx.EXPAND | wx.ALL, border=5 )
        
        
        panel.SetSizer(box)
        self.Centre()
        self.Fit()
        self.Layout()
        self.SetSize((400,100))

class MyApp(wx.App):
     def OnInit(self):
         frame = MyFrame(None, -1, 'wxboxsizer.py')
         frame.Show(True)
         return True

app = MyApp(0)
app.MainLoop()
Once deleted, variables cannot be recovered. Proceed (y/[n])? y

Different way to bind and identify pressed buttons

Write this piece of code in the Python regular script. Explain how it works.

In [1]:
% reset

#!/usr/bin/python

# wxboxsizer.py

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, (-1, -1), wx.Size(250, 50))
        panel = wx.Panel(self, -1)
        box = wx.BoxSizer(wx.HORIZONTAL)
        
        self.button1 = wx.Button(panel, id=wx.ID_ANY, label='Button nr 1')
        self.button2 = wx.Button(panel, id=wx.ID_ANY, label='Button 2')
        self.button3 = wx.Button(panel, id=wx.ID_ANY, label='Button 3 - very long name')
        
        self.Bind(wx.EVT_BUTTON, self.OnPrint, id=self.button1.GetId())
        self.Bind(wx.EVT_BUTTON, self.OnPrint, id=self.button2.GetId())
        self.Bind(wx.EVT_BUTTON, self.OnPrint, id=self.button3.GetId())
        
        box.Add(self.button1, 0, wx.EXPAND | wx.ALL, border=5 )
        box.Add(self.button2, 1, wx.EXPAND | wx.ALL, border=15 )
        box.Add(self.button3, 2, wx.EXPAND | wx.ALL, border=5 )
        
        
        panel.SetSizer(box)
        self.Centre()
        #self.Fit()
        #self.Layout()
        self.SetSize((400,100))
        
    def OnPrint(self, event):
        if event.GetId() == self.button1.GetId():
            print 'pressed button 1'
        elif event.GetId() == self.button2.GetId():
            print 'pressed button 2'
        elif event.GetId() == self.button3.GetId():
            print 'pressed button 3'
        else:
            print 'pressed some other button'

class MyApp(wx.App):
     def OnInit(self):
         frame = MyFrame(None, -1, 'wxboxsizer.py')
         frame.Show(True)
         return True

app = MyApp(0)
app.MainLoop()
Once deleted, variables cannot be recovered. Proceed (y/[n])? y

How to display a image with the use of wxPython?

In this section it is showed how to glue together numpy, matplotlib and wxPython librares in order to dispaly a image (array).

Let's load image into memory and print some of its parameters (minimum, maximum and average value).

In [40]:
from matplotlib.pyplot import imread, imshow
image = imread('images_2014/brain.bmp')
In [41]:
print image.min(), image.max(), image.mean() ,image.shape
0 255 47.0370941162 (384L, 512L)

To display image with the use of imshow() function from matplotlib library write line:

In [43]:
imshow(image, cmap='gray')
Out[43]:
<matplotlib.image.AxesImage at 0xbb11b70>

The sorce code of the application that enables to display image inside window of wxPython is as follows:

In [*]:
%reset
import wx
import numpy as np

from matplotlib.figure import Figure
from matplotlib.pyplot import imread
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanvas



class DisplayImage(wx.Frame):
    def __init__(self,parent,image):
        self.img = image 
        wx.Frame.__init__(self, parent, title="Brain", size=(wx.GetClientDisplayRect()[2], wx.GetClientDisplayRect()[3]) )
        self.CreatePanel()
        self.DrawFigure()
        
    def CreatePanel(self):
        self.fig = Figure()
        self.fig.subplots_adjust(left=0.01, right=0.99, top=0.99, bottom=0.01)
        self.canvas = FigCanvas(self, -1, self.fig)
        self.axes = self.fig.add_subplot(111)
        self.axes.get_xaxis().set_visible(False)    
        self.axes.get_yaxis().set_visible(False) 
 
        self.hbox = wx.BoxSizer(wx.VERTICAL) #main siezer
        self.hbox.Add(self.canvas, 1, wx.EXPAND | wx.ALL,1)

        self.SetSizer(self.hbox)
        self.SetAutoLayout(True)
        self.Fit()     
    
         
    def DrawFigure(self):
        self.axes.clear()
        self.imshow = self.axes.imshow(self.img,cmap="gray")
        self.canvas.draw()
        

image = imread('2014_Session_1-2-3_images_for_students/brain.bmp')
app = wx.App(False)
img = DisplayImage(None,image)
img.Show()
app.MainLoop()
Once deleted, variables cannot be recovered. Proceed (y/[n])? y

In [87]:
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/3_display_brain.png")
Out[87]:

Write a function to threshold a image

In [89]:
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/4_threshold_brain.png")
Out[89]:

With the use of for loops

In [75]:
def thresh1(im, th=125):
    img = im.copy()
    for y in range(img.shape[0]):
        for x in range(img.shape[1]):
            if img[y,x] >= th:
                img[y,x]= 255
            else:
                img[y,x] = 0 
    return img
In [60]:
img_th1 = thresh1(image, th=50)
plt.imshow(img_th1, plt.cm.gray)
Out[60]:
<matplotlib.image.AxesImage at 0xd622e80>

Matrix convention (1)

In [61]:
def thresh2(im, th=100):
    img = im.copy()
    img[img>=th] = 255 
    img[img<th] = 0    
    return img
In [68]:
img_th2 = thresh2(image, th=125)
plt.imshow(img_th2, plt.cm.gray)
Out[68]:
<matplotlib.image.AxesImage at 0x11a6d3c8>

Matrix convention (2)

In [71]:
th = 155
img_th3 = np.where(image>th, 255, 0)
In [72]:
plt.imshow(img_th3, plt.cm.gray)
Out[72]:
<matplotlib.image.AxesImage at 0x124d7a20>

with additional GUI elemetns

In this task ones have to add additional widgets (GUI elemetns) to our window. We will broaden our application by additional slider to do thresholding.

In [83]:
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/4_threshold_brain_slider.png")
Out[83]:
In [10]:
%reset
import wx
import numpy as np

from scipy import misc
from matplotlib.pyplot import imread
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanvas


class imageShow(wx.Frame):
    def __init__(self,parent,image):
        self.img = image
        wx.Frame.__init__(self, parent, title="Brain", size=(wx.GetClientDisplayRect()[2], wx.GetClientDisplayRect()[3]) )
        self.CreatePanel()
        self.DrawFigure()
        
    def CreatePanel(self):
        self.fig = Figure()
        self.fig.subplots_adjust(left=0.01, right=0.99, top=0.99, bottom=0.01)
        self.canvas = FigCanvas(self, -1, self.fig)
        self.axes = self.fig.add_subplot(111)
        self.axes.get_xaxis().set_visible(False)    
        self.axes.get_yaxis().set_visible(False) 

        self.slider1 = wx.Slider(self,id=wx.ID_ANY, value=125,minValue=0,maxValue=255,style=wx.SL_AUTOTICKS|wx.SL_HORIZONTAL|wx.SL_LABELS)
     
        self.Bind(wx.EVT_SLIDER, self.OnSlider)        
        
        self.hbox = wx.BoxSizer(wx.VERTICAL) #main siezer
        self.hbox.Add(self.canvas, 1, wx.EXPAND | wx.ALL,1)
        self.hbox.Add(self.slider1,0.5, wx.EXPAND | wx.ADJUST_MINSIZE |wx.ALL, 1)  
        self.SetSizer(self.hbox)
        self.SetAutoLayout(True)
        self.Fit()     

    def OnSlider(self,event):
        self.DrawFigure()        
         
    def DrawFigure(self,  minn = 0, maxx = 255):
        
        self.axes.clear()
        self.imshow = self.axes.imshow(np.where(self.img>self.slider1.GetValue(),255,0), cmap='gray')
        self.canvas.draw()
        
        
image = imread('2014_Session_1-2-3_images_for_students/brain.bmp')
app = wx.App(False)
img = imageShow(None,image)
img.Show()
app.MainLoop()
Once deleted, variables cannot be recovered. Proceed (y/[n])? y

For volunteers:

Create new script that allows the manipulation of the text. There should be a special place to enter a text (wx.TextCtrl) and function keys shown below:

In [32]:
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/5_text_manipulation.png")
Out[32]: