wx.callafter interface freeze

hi

i am trying to code an wx-interface with multithreading and i read
something about the wx.callafter function. so i tryed to solve it with
this nice tool.
the program is a main program with a gui, if i press the start button
the program should run an algorithm and return the different
result-steps in a graphical window. this means i would like to get a
graphical update after each iteration

my problem is, if i start it the interface got freezed, and a got only
two graphical updates, one at the beginning and on at the end. So could
anyone
help me ?

sorry for my bad description, i am a quite new programmer and in python
as well

here is the code i talking about

######## imports ###########

···

#
import matplotlib
matplotlib.use("WXAgg")
matplotlib.interactive(True)
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
from matplotlib.figure import Figure
from matplotlib.axes import Subplot
import matplotlib.pyplot as plt

import numpy as np

import pylab as pl
import math

import wx

from threading import Thread
import threading
import time

#
###########################
wx.SetDefaultPyEncoding("iso-8859-15")

####################################################################################
#

def normal_pdf(mu, sigma, x_array):
    first_term = 1 / math.sqrt(2*math.pi * sigma * sigma)
    second_term = np.exp(-0.5 * (x_array - mu) * (x_array - mu) / (sigma
* sigma))
    return first_term * second_term

####################################################################################
#

class Theta:
    def __init__(self, count_of_gaussians):
        # create array for each parameter and init by default-value
        self.mu = np.zeros(count_of_gaussians)
        self.sigma = np.ones(count_of_gaussians)
        self.pi = np.zeros(count_of_gaussians)
        self.pi[:] = 1.0 / count_of_gaussians
        self.count_of_gaussians = count_of_gaussians

####################################################################################
#
########### testing threads #############
#
class ThreadedAction(Thread):
    def __init__(self, em_obj, **kwargs):
        Thread.__init__(self, **kwargs)
        self.em_obj = em_obj

    def run(self):
        print "Performing expensive calculation in %s..."%self.getName()

        while (not self.em_obj._converged and not self.em_obj.stop):
            self.em_obj.iterate()
            wx.CallAfter(self.em_obj.updateGUI)
        print 'done.'

##################################################

# probability-functions with the convention to read:
# for example: p_c_G_x_theta should be read as:
# probability of c Given x (all datapoints n=1 to N) and theta
# note: instead of defining a function for every datapoint xn we define
a function for all datapoints

# conditional probability of data x given class c and parameters theta
(MoG: the gaussian with parameters mu_c, sigma_c)
def p_x_G_c_theta(x, c, theta):
    return normal_pdf(theta.mu[c], theta.sigma[c], x)

# marginal probability of class c given parameters theta (MoG: prior =
const. mixture-parameter pi)
def p_c_G_theta(c, theta):
    return theta.pi[c]

# joint probability of data x and class c given parameters theta
def p_x_c_G_theta(x, c, theta):
    # product-rule: conditional times marginal
    return p_x_G_c_theta(x, c, theta) * p_c_G_theta(c, theta)

# marginal probability of data x given parameters theta
def p_x_G_theta(x, theta):
    # sum-rule: sum of all joints
    sum_of_joints = np.zeros(x.shape[0])
    for cs in xrange(theta.count_of_gaussians):
        sum_of_joints += p_x_c_G_theta(x, cs, theta)
    return sum_of_joints

def p_c_G_x_theta(c, x, theta):
    # applying bayes theorem using joint-probability and marginal
    joint = p_x_c_G_theta(x, c, theta)
    marginal = p_x_G_theta(x, theta)
    return joint / marginal

def generate_data(theta, N):
    data = np.zeros(N)
    for n in xrange(N):
        c = c = np.random.uniform(0, 1)
        offset = 0
        for i in xrange(theta.count_of_gaussians):
            if c < theta.pi[i] + offset:
                data[n] = np.random.normal(theta.mu[i], theta.sigma[i])
                break
            else:
                offset += theta.pi[i]
    return data

def update_mu(x, expectation, theta_new):
    for c in xrange(theta_new.count_of_gaussians):
        numerator = expectation[c,:] * x
        numerator = numerator.sum()
        denominator = expectation[c,:].sum()
        theta_new.mu[c] = numerator / denominator

def update_sigma(x, expectation, theta_new):
    for c in xrange(theta_new.count_of_gaussians):
        numerator = expectation[c,:] * (x - theta_new.mu[c])**2
        numerator = numerator.sum()
        denominator = expectation[c,:].sum()
        theta_new.sigma[c] = math.sqrt(numerator / denominator)

def update_pi(x, expectation, theta_new):
    N = x.shape[0]
    for c in xrange(theta_new.count_of_gaussians):
        theta_new.pi[c] = expectation[c,:].sum() / N

####################################################################################
#
class EM_MoG(wx.Frame):
    def __init__(self, task):
        wx.Frame.__init__(self, None, -1, "Interactive Frame v1.0")

        self.fig = Figure((10,10), 75)
        self.canvas = FigureCanvasWxAgg(self, -1, self.fig)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 1, wx.TOP)

        self._task = task

        # A: generate datapoints with given parameters
        self._theta_gen = Theta(2)
        self._theta_gen.mu[0] = -2
        self._theta_gen.mu[1] = 4
        self._theta_gen.sigma[0] = 1
        self._theta_gen.sigma[1] = math.sqrt(10)
        self._theta_gen.pi[0] = 0.4
        self._theta_gen.pi[1] = 1 - self._theta_gen.pi[0]

        self._data_count = 200
        if self._task == 'c':
            self._data_count = 5

        self._data = generate_data(self._theta_gen, self._data_count)

        # B/D: initialize theta with given initial values
        self._x_min = -20
        self._x_max = 20
        self._theta_old = Theta(2)
        if self._task <> 'd':
            self._theta_old.mu[0] = - 5
            self._theta_old.mu[1] = 5
            self._theta_old.sigma[0] = 1
            self._theta_old.sigma[1] = math.sqrt(10)
            self._theta_old.pi[0] = 0.5
            self._theta_old.pi[1] = 1 - self._theta_old.pi[0]
        else:
            self._theta_old.mu = np.random.uniform(self._x_min,
self._x_max, self._theta_old.count_of_gaussians)
            self._theta_old.sigma = np.random.uniform(0, self._x_max/2,
self._theta_old.count_of_gaussians)
            self._theta_old.pi[0] = np.random.uniform(0, 1)
            self._theta_old.pi[1] = 1 - self._theta_old.pi[0]

###############################################################################

        # some preparation for plotting pdfs, plot generating pdf directly
        count = 500.0
        # create x-array for plotting
        self._pdf_x = np.zeros(count)
        step = (self._x_max - self._x_min) / count
        for x in xrange(count):
            self._pdf_x[x] = self._x_min + x * step
        # create y-array for generating pdf
        self._y_gen = p_x_G_theta(self._pdf_x, self._theta_gen)

################################################################################

        self.a = self.fig.add_subplot(221)
        self.a.axes.plot(self._pdf_x, self._y_gen)

        # initialisiere die plot-frames
        self.b = self.fig.add_subplot(223)
        self.c = self.fig.add_subplot(222)
        self.d = self.fig.add_subplot(224)
#################################################################################

        # run EM-algorithm
        self._max_iterations = 1000
        self._expectation =
np.zeros((self._theta_old.count_of_gaussians, self._data.shape[0]))
        self._log_likelihood = np.zeros((self._max_iterations))
        self._theta_history = np.zeros((self._max_iterations,
3*self._theta_old.count_of_gaussians))
        self._converged = False
        self._counter = 0
        self._epsilon = 0.001

        ################### Controller ######################
        #
        # create start/stop buttons
        self.button_start = wx.Button(self,-1, " Start ", size=(-1,-1))
        self.button_stop = wx.Button(self,-1, " Stop ", size=(-1,-1))
        self.button_exit = wx.Button(self,-1, " Exit ", size=(-1,-1))
        self.cb1 = wx.CheckBox(self, -1, "Show title" )

        # bind actions to the buttons
        self.button_start.Bind(wx.EVT_BUTTON,self.OnStart)
        self.button_stop.Bind(wx.EVT_BUTTON, self.OnStop)
        self.button_exit.Bind(wx.EVT_BUTTON, self.OnExit)

        # pack the buttons in the Sizer
        btnsizer = wx.BoxSizer(wx.HORIZONTAL)
        btnsizer.Add(self.button_start, 1, wx.LEFT)
        btnsizer.Add(self.button_stop, 1, wx.LEFT)
        btnsizer.Add(self.button_exit, 1, wx.RIGHT)

        btnsizer1 = wx.BoxSizer(wx.VERTICAL)
        btnsizer1.Add(self.cb1, 1, wx.DOWN)

        sizer.Add(btnsizer, 0, wx.TOP)
        sizer.Add(btnsizer1, 0, wx.TOP)
        self.SetSizer(sizer)
        self.Fit()
        #
        #####################################################

        # create stop-flag for multithreading
        self.stop = False

    def iterate(self):
        time.sleep(0.1)

        # store parameters to history-array
        for t in xrange(self._theta_old.count_of_gaussians):
            self._theta_history[self._counter, t] = self._theta_old.mu[t]
            self._theta_history[self._counter, 2+ t] =
self._theta_old.sigma[t]
            self._theta_history[self._counter, 4+ t] = self._theta_old.pi[t]

        # get data for y-axis of estimated pdf
        self._y_em = p_x_G_theta(self._pdf_x, self._theta_old)

        # TODO: add legend
        #pl.legend()

        # E-step
        for c in xrange(self._theta_old.count_of_gaussians):
            self._expectation[c, :] = p_c_G_x_theta(c, self._data,
self._theta_old)

        # M-step
        theta_new = Theta(2)
        update_mu(self._data, self._expectation, theta_new)
        update_sigma(self._data, self._expectation, theta_new)
        update_pi(self._data, self._expectation, theta_new)

        # compute log-likelihood
        # log-likelihood of initial theta is not logged because it is
very low
        # and the curve gets ugly :wink:
        # to try including the initial theta just move this block to
first line of the loop
        ll = p_x_G_theta(self._data, theta_new)
        ll = np.log(ll)
        ll = ll.sum()
        self._log_likelihood[self._counter] = ll

        # check convergence
        if self._counter > 0:
            if self._log_likelihood[self._counter] -
self._log_likelihood[self._counter-1] < self._epsilon:
                # idea of Gervasio: also check if parameters don't
change anymore:
                if np.abs(theta_new.mu - self._theta_old.mu).max() <
self._epsilon and np.abs(theta_new.sigma - self._theta_old.sigma).max()
< self._epsilon and np.abs(theta_new.pi - self._theta_old.pi).max() <
self._epsilon:
                    self._converged = True
            elif self._counter >= self._max_iterations:
                self._converged = True

        # increment counter
        self._counter += 1

        # update theta
        self._theta_old = theta_new

    def updateGUI(self):
        # plot pdf obtained by em-step
        self.b.axes.plot(self._pdf_x, self._y_em)
        self.canvas.draw()

        # plot history of parameters (idea of Omid!!)
        #self.d.axes.plot(self._theta_history[:self._counter-1, :])
        #self.canvas.draw()

         # plot history of likelihood
        #self.c.axes.plot(self._log_likelihood[:self._counter])
        #self.canvas.draw()
        pass

    def OnStop(self,event=None):
# self.timer.Stop()
# self.stop = True
        pass

    def OnStart(self,event=None):
# self.iterate()
################################
        self.stop = False
        action = ThreadedAction(self)
        action.start()

################################

    def OnExit(self,event=None):
        self.Destroy()

    def iterate_until_converged(self):
        while (not self._converged):
            self.iterate()

#
######################################################################################

if __name__ == '__main__':
    app = wx.PySimpleApp(0)
    frame = EM_MoG('d')
    frame.Show(True)
    app.MainLoop()

Timo,

I'm not sure what's going on here, but please read the wiki's
excellent write-up on this topic:

http://wiki.wxpython.org/LongRunningTasks

Hopefully one of the methods mentioned in that article will light the
way.

-Mike

···

On Jul 23, 4:02 am, Timo Spielmann <spielm...@th.physik.uni- frankfurt.de> wrote:

hi

i am trying to code an wx-interface with multithreading and i read
something about the wx.callafter function. so i tryed to solve it with
this nice tool.
the program is a main program with a gui, if i press the start button
the program should run an algorithm and return the different
result-steps in a graphical window. this means i would like to get a
graphical update after each iteration

my problem is, if i start it the interface got freezed, and a got only
two graphical updates, one at the beginning and on at the end. So could
anyone
help me ?

sorry for my bad description, i am a quite new programmer and in python
as well

here is the code i talking about

######## imports ###########
#
import matplotlib
matplotlib.use("WXAgg")
matplotlib.interactive(True)
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
from matplotlib.figure import Figure
from matplotlib.axes import Subplot
import matplotlib.pyplot as plt

import numpy as np

import pylab as pl
import math

import wx

from threading import Thread
import threading
import time

#
###########################
wx.SetDefaultPyEncoding("iso-8859-15")

####################################################################################
#

def normal_pdf(mu, sigma, x_array):
first_term = 1 / math.sqrt(2*math.pi * sigma * sigma)
second_term = np.exp(-0.5 * (x_array - mu) * (x_array - mu) / (sigma
* sigma))
return first_term * second_term

####################################################################################
#

class Theta:
def __init__(self, count_of_gaussians):
# create array for each parameter and init by default-value
self.mu = np.zeros(count_of_gaussians)
self.sigma = np.ones(count_of_gaussians)
self.pi = np.zeros(count_of_gaussians)
self.pi[:] = 1.0 / count_of_gaussians
self.count_of_gaussians = count_of_gaussians

####################################################################################
#
########### testing threads #############
#
class ThreadedAction(Thread):
def __init__(self, em_obj, **kwargs):
Thread.__init__(self, **kwargs)
self.em_obj = em_obj

def run\(self\):
    print &quot;Performing expensive calculation in %s\.\.\.&quot;%self\.getName\(\)

    while \(not self\.em\_obj\.\_converged and not self\.em\_obj\.stop\):
        self\.em\_obj\.iterate\(\)
        wx\.CallAfter\(self\.em\_obj\.updateGUI\)
    print &#39;done\.&#39;

##################################################

# probability-functions with the convention to read:
# for example: p_c_G_x_theta should be read as:
# probability of c Given x (all datapoints n=1 to N) and theta
# note: instead of defining a function for every datapoint xn we define
a function for all datapoints

# conditional probability of data x given class c and parameters theta
(MoG: the gaussian with parameters mu_c, sigma_c)
def p_x_G_c_theta(x, c, theta):
return normal_pdf(theta.mu[c], theta.sigma[c], x)

# marginal probability of class c given parameters theta (MoG: prior =
const. mixture-parameter pi)
def p_c_G_theta(c, theta):
return theta.pi[c]

# joint probability of data x and class c given parameters theta
def p_x_c_G_theta(x, c, theta):
# product-rule: conditional times marginal
return p_x_G_c_theta(x, c, theta) * p_c_G_theta(c, theta)

# marginal probability of data x given parameters theta
def p_x_G_theta(x, theta):
# sum-rule: sum of all joints
sum_of_joints = np.zeros(x.shape[0])
for cs in xrange(theta.count_of_gaussians):
sum_of_joints += p_x_c_G_theta(x, cs, theta)
return sum_of_joints

def p_c_G_x_theta(c, x, theta):
# applying bayes theorem using joint-probability and marginal
joint = p_x_c_G_theta(x, c, theta)
marginal = p_x_G_theta(x, theta)
return joint / marginal

def generate_data(theta, N):
data = np.zeros(N)
for n in xrange(N):
c = c = np.random.uniform(0, 1)
offset = 0
for i in xrange(theta.count_of_gaussians):
if c < theta.pi[i] + offset:
data[n] = np.random.normal(theta.mu[i], theta.sigma[i])
break
else:
offset += theta.pi[i]
return data

def update_mu(x, expectation, theta_new):
for c in xrange(theta_new.count_of_gaussians):
numerator = expectation[c,:] * x
numerator = numerator.sum()
denominator = expectation[c,:].sum()
theta_new.mu[c] = numerator / denominator

def update_sigma(x, expectation, theta_new):
for c in xrange(theta_new.count_of_gaussians):
numerator = expectation[c,:] * (x - theta_new.mu[c])**2
numerator = numerator.sum()
denominator = expectation[c,:].sum()
theta_new.sigma[c] = math.sqrt(numerator / denominator)

def update_pi(x, expectation, theta_new):
N = x.shape[0]
for c in xrange(theta_new.count_of_gaussians):
theta_new.pi[c] = expectation[c,:].sum() / N

####################################################################################
#
class EM_MoG(wx.Frame):
def __init__(self, task):
wx.Frame.__init__(self, None, -1, "Interactive Frame v1.0")

    self\.fig = Figure\(\(10,10\), 75\)
    self\.canvas = FigureCanvasWxAgg\(self, \-1, self\.fig\)

    sizer = wx\.BoxSizer\(wx\.VERTICAL\)
    sizer\.Add\(self\.canvas, 1, wx\.TOP\)

    self\.\_task = task

    \# A: generate datapoints with given parameters
    self\.\_theta\_gen = Theta\(2\)
    self\.\_theta\_gen\.mu\[0\] = \-2
    self\.\_theta\_gen\.mu\[1\] = 4
    self\.\_theta\_gen\.sigma\[0\] = 1
    self\.\_theta\_gen\.sigma\[1\] = math\.sqrt\(10\)
    self\.\_theta\_gen\.pi\[0\] = 0\.4
    self\.\_theta\_gen\.pi\[1\] = 1 \- self\.\_theta\_gen\.pi\[0\]

    self\.\_data\_count = 200
    if self\.\_task == &#39;c&#39;:
        self\.\_data\_count = 5

    self\.\_data = generate\_data\(self\.\_theta\_gen, self\.\_data\_count\)

    \# B/D: initialize theta with given initial values
    self\.\_x\_min = \-20
    self\.\_x\_max = 20
    self\.\_theta\_old = Theta\(2\)
    if self\.\_task &lt;&gt; &#39;d&#39;:
        self\.\_theta\_old\.mu\[0\] = \- 5
        self\.\_theta\_old\.mu\[1\] = 5
        self\.\_theta\_old\.sigma\[0\] = 1
        self\.\_theta\_old\.sigma\[1\] = math\.sqrt\(10\)
        self\.\_theta\_old\.pi\[0\] = 0\.5
        self\.\_theta\_old\.pi\[1\] = 1 \- self\.\_theta\_old\.pi\[0\]
    else:
        self\.\_theta\_old\.mu = np\.random\.uniform\(self\.\_x\_min,

self._x_max, self._theta_old.count_of_gaussians)
self._theta_old.sigma = np.random.uniform(0, self._x_max/2,
self._theta_old.count_of_gaussians)
self._theta_old.pi[0] = np.random.uniform(0, 1)
self._theta_old.pi[1] = 1 - self._theta_old.pi[0]

###############################################################################

    \# some preparation for plotting pdfs, plot generating pdf directly
    count = 500\.0
    \# create x\-array for plotting
    self\.\_pdf\_x = np\.zeros\(count\)
    step = \(self\.\_x\_max \- self\.\_x\_min\) / count
    for x in xrange\(count\):
        self\.\_pdf\_x\[x\] = self\.\_x\_min \+ x \* step
    \# create y\-array for generating pdf
    self\.\_y\_gen = p\_x\_G\_theta\(self\.\_pdf\_x, self\.\_theta\_gen\)

################################################################################

    self\.a = self\.fig\.add\_subplot\(221\)
    self\.a\.axes\.plot\(self\.\_pdf\_x, self\.\_y\_gen\)

    \# initialisiere die plot\-frames
    self\.b = self\.fig\.add\_subplot\(223\)
    self\.c = self\.fig\.add\_subplot\(222\)
    self\.d = self\.fig\.add\_subplot\(224\)

#################################################################################

    \# run EM\-algorithm
    self\.\_max\_iterations = 1000
    self\.\_expectation =

np.zeros((self._theta_old.count_of_gaussians, self._data.shape[0]))
self._log_likelihood = np.zeros((self._max_iterations))
self._theta_history = np.zeros((self._max_iterations,
3*self._theta_old.count_of_gaussians))
self._converged = False
self._counter = 0
self._epsilon = 0.001

    \#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\# Controller \#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#
    \#
    \# create start/stop buttons
    self\.button\_start = wx\.Button\(self,\-1, &quot; Start &quot;, size=\(\-1,\-1\)\)
    self\.button\_stop = wx\.Button\(self,\-1, &quot; Stop &quot;, size=\(\-1,\-1\)\)
    self\.button\_exit = wx\.Button\(self,\-1, &quot; Exit &quot;, size=\(\-1,\-1\)\)
    self\.cb1 = wx\.CheckBox\(self, \-1, &quot;Show title&quot; \)

    \# bind actions to the buttons
    self\.button\_start\.Bind\(wx\.EVT\_BUTTON,self\.OnStart\)
    self\.button\_stop\.Bind\(wx\.EVT\_BUTTON, self\.OnStop\)
    self\.button\_exit\.Bind\(wx\.EVT\_BUTTON, self\.OnExit\)

    \# pack the buttons in the Sizer
    btnsizer = wx\.BoxSizer\(wx\.HORIZONTAL\)
    btnsizer\.Add\(self\.button\_start, 1, wx\.LEFT\)
    btnsizer\.Add\(self\.button\_stop, 1, wx\.LEFT\)
    btnsizer\.Add\(self\.button\_exit, 1, wx\.RIGHT\)

    btnsizer1 = wx\.BoxSizer\(wx\.VERTICAL\)
    btnsizer1\.Add\(self\.cb1, 1, wx\.DOWN\)

    sizer\.Add\(btnsizer, 0, wx\.TOP\)
    sizer\.Add\(btnsizer1, 0, wx\.TOP\)
    self\.SetSizer\(sizer\)
    self\.Fit\(\)
    \#
    \#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#

    \# create stop\-flag for multithreading
    self\.stop = False

def iterate\(self\):
    time\.sleep\(0\.1\)

    \# store parameters to history\-array
    for t in xrange\(self\.\_theta\_old\.count\_of\_gaussians\):
        self\.\_theta\_history\[self\.\_counter, t\] = self\.\_theta\_old\.mu\[t\]
        self\.\_theta\_history\[self\.\_counter, 2\+ t\] =

self._theta_old.sigma[t]
self._theta_history[self._counter, 4+ t] = self._theta_old.pi[t]

    \# get data for y\-axis of estimated pdf
    self\.\_y\_em = p\_x\_G\_theta\(self\.\_pdf\_x, self\.\_theta\_old\)

    \# TODO: add legend
    \#pl\.legend\(\)

    \# E\-step
    for c in xrange\(self\.\_theta\_old\.count\_of\_gaussians\):
        self\.\_expectation\[c, :\] = p\_c\_G\_x\_theta\(c, self\.\_data,

self._theta_old)

    \# M\-step
    theta\_new = Theta\(2\)
    update\_mu\(self\.\_data, self\.\_expectation, theta\_new\)
    update\_sigma\(self\.\_data, self\.\_expectation, theta\_new\)
    update\_pi\(self\.\_data, self\.\_expectation, theta\_new\)

    \# compute log\-likelihood
    \# log\-likelihood of initial theta is not logged because it is

very low
# and the curve gets ugly :wink:
# to try including the initial theta just move this block to
first line of the loop
ll = p_x_G_theta(self._data, theta_new)
ll = np.log(ll)
ll = ll.sum()
self._log_likelihood[self._counter] = ll

    \# check convergence
    if self\.\_counter &gt; 0:
        if self\.\_log\_likelihood\[self\.\_counter\] \-

self._log_likelihood[self._counter-1] < self._epsilon:
# idea of Gervasio: also check if parameters don't
change anymore:
if np.abs(theta_new.mu - self._theta_old.mu).max() <
self._epsilon and np.abs(theta_new.sigma - self._theta_old.sigma).max()
< self._epsilon and np.abs(theta_new.pi - self._theta_old.pi).max() <
self._epsilon:
self._converged = True
elif self._counter >= self._max_iterations:
self._converged = True

    \# increment counter
    self\.\_counter \+= 1

    \# update theta
    self\.\_theta\_old = theta\_new

def updateGUI\(self\):
    \# plot pdf obtained by em\-step
    self\.b\.axes\.plot\(self\.\_pdf\_x, self\.\_y\_em\)
    self\.canvas\.draw\(\)

    \# plot history of parameters \(idea of Omid\!\!\)
    \#self\.d\.axes\.plot\(self\.\_theta\_history\[:self\.\_counter\-1, :\]\)
    \#self\.canvas\.draw\(\)

     \# plot history of likelihood
    \#self\.c\.axes\.plot\(self\.\_log\_likelihood\[:self\.\_counter\]\)
    \#self\.canvas\.draw\(\)
    pass

def OnStop\(self,event=None\):

# self.timer.Stop()
# self.stop = True
pass

def OnStart\(self,event=None\):

# self.iterate()
################################
self.stop = False
action = ThreadedAction(self)
action.start()

################################

def OnExit\(self,event=None\):
    self\.Destroy\(\)

def iterate\_until\_converged\(self\):
    while \(not self\.\_converged\):
        self\.iterate\(\)

#
######################################################################################

if __name__ == '__main__':
app = wx.PySimpleApp(0)
frame = EM_MoG('d')
frame.Show(True)
app.MainLoop()

Timo Spielmann wrote:

the program is a main program with a gui, if i press the start button
the program should run an algorithm and return the different
result-steps in a graphical window. this means i would like to get a
graphical update after each iteration

my problem is, if i start it the interface got freezed, and a got only
two graphical updates, one at the beginning and on at the end.

This looks right. to make sure, you might put a print statement in here,
to make sure it's getting called:

     def updateGUI(self):
         # plot pdf obtained by em-step
         self.b.axes.plot(self._pdf_x, self._y_em)
         self.canvas.draw()

However, if it is, then this is a MPL wx back-end issue -- I think I"ve
had troupble with it updating when I want it to in the past -- the call
to canvas.draw() should do it, but it may not.

YOu might try sprinkling:

self.canvas.Refresh()
self.canvas.Update()

In there, to force a refresh.

If that doesn't work, you may need to dig into the wx back-end code and
see what's not getting called when it should -- I've had this problem,
but I don't remember the solution at this point -- sorry!

If you're still stuck, I'd make a "simple as possible that shows the
issue" sample, and post it in the MPL list

-Chris

···

sorry for my bad description, i am a quite new programmer and in python
as well

here is the code i talking about

######## imports ###########
#
import matplotlib
matplotlib.use("WXAgg")
matplotlib.interactive(True)
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
from matplotlib.figure import Figure
from matplotlib.axes import Subplot
import matplotlib.pyplot as plt

import numpy as np

import pylab as pl
import math

import wx

from threading import Thread
import threading
import time

#
###########################
wx.SetDefaultPyEncoding("iso-8859-15")

####################################################################################
#

def normal_pdf(mu, sigma, x_array):
    first_term = 1 / math.sqrt(2*math.pi * sigma * sigma)
    second_term = np.exp(-0.5 * (x_array - mu) * (x_array - mu) / (sigma
* sigma))
    return first_term * second_term

####################################################################################
#

class Theta:
    def __init__(self, count_of_gaussians):
        # create array for each parameter and init by default-value
        self.mu = np.zeros(count_of_gaussians)
        self.sigma = np.ones(count_of_gaussians)
        self.pi = np.zeros(count_of_gaussians)
        self.pi[:] = 1.0 / count_of_gaussians
        self.count_of_gaussians = count_of_gaussians

####################################################################################
#
########### testing threads #############
#
class ThreadedAction(Thread):
    def __init__(self, em_obj, **kwargs):
        Thread.__init__(self, **kwargs)
        self.em_obj = em_obj

    def run(self):
        print "Performing expensive calculation in %s..."%self.getName()

        while (not self.em_obj._converged and not self.em_obj.stop):
            self.em_obj.iterate()
            wx.CallAfter(self.em_obj.updateGUI)
        print 'done.'

##################################################

# probability-functions with the convention to read:
# for example: p_c_G_x_theta should be read as:
# probability of c Given x (all datapoints n=1 to N) and theta
# note: instead of defining a function for every datapoint xn we define
a function for all datapoints

# conditional probability of data x given class c and parameters theta
(MoG: the gaussian with parameters mu_c, sigma_c)
def p_x_G_c_theta(x, c, theta):
    return normal_pdf(theta.mu[c], theta.sigma[c], x)

# marginal probability of class c given parameters theta (MoG: prior =
const. mixture-parameter pi)
def p_c_G_theta(c, theta):
    return theta.pi[c]

# joint probability of data x and class c given parameters theta
def p_x_c_G_theta(x, c, theta):
    # product-rule: conditional times marginal
    return p_x_G_c_theta(x, c, theta) * p_c_G_theta(c, theta)

# marginal probability of data x given parameters theta
def p_x_G_theta(x, theta):
    # sum-rule: sum of all joints
    sum_of_joints = np.zeros(x.shape[0])
    for cs in xrange(theta.count_of_gaussians):
        sum_of_joints += p_x_c_G_theta(x, cs, theta)
    return sum_of_joints

def p_c_G_x_theta(c, x, theta):
    # applying bayes theorem using joint-probability and marginal
    joint = p_x_c_G_theta(x, c, theta)
    marginal = p_x_G_theta(x, theta)
    return joint / marginal

def generate_data(theta, N):
    data = np.zeros(N)
    for n in xrange(N):
        c = c = np.random.uniform(0, 1)
        offset = 0
        for i in xrange(theta.count_of_gaussians):
            if c < theta.pi[i] + offset:
                data[n] = np.random.normal(theta.mu[i], theta.sigma[i])
                break
            else:
                offset += theta.pi[i]
    return data

def update_mu(x, expectation, theta_new):
    for c in xrange(theta_new.count_of_gaussians):
        numerator = expectation[c,:] * x
        numerator = numerator.sum()
        denominator = expectation[c,:].sum()
        theta_new.mu[c] = numerator / denominator

def update_sigma(x, expectation, theta_new):
    for c in xrange(theta_new.count_of_gaussians):
        numerator = expectation[c,:] * (x - theta_new.mu[c])**2
        numerator = numerator.sum()
        denominator = expectation[c,:].sum()
        theta_new.sigma[c] = math.sqrt(numerator / denominator)

def update_pi(x, expectation, theta_new):
    N = x.shape[0]
    for c in xrange(theta_new.count_of_gaussians):
        theta_new.pi[c] = expectation[c,:].sum() / N

####################################################################################
#
class EM_MoG(wx.Frame):
    def __init__(self, task):
        wx.Frame.__init__(self, None, -1, "Interactive Frame v1.0")

        self.fig = Figure((10,10), 75)
        self.canvas = FigureCanvasWxAgg(self, -1, self.fig)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 1, wx.TOP)

        self._task = task

        # A: generate datapoints with given parameters
        self._theta_gen = Theta(2)
        self._theta_gen.mu[0] = -2
        self._theta_gen.mu[1] = 4
        self._theta_gen.sigma[0] = 1
        self._theta_gen.sigma[1] = math.sqrt(10)
        self._theta_gen.pi[0] = 0.4
        self._theta_gen.pi[1] = 1 - self._theta_gen.pi[0]

        self._data_count = 200
        if self._task == 'c':
            self._data_count = 5

        self._data = generate_data(self._theta_gen, self._data_count)

        # B/D: initialize theta with given initial values
        self._x_min = -20
        self._x_max = 20
        self._theta_old = Theta(2)
        if self._task <> 'd':
            self._theta_old.mu[0] = - 5
            self._theta_old.mu[1] = 5
            self._theta_old.sigma[0] = 1
            self._theta_old.sigma[1] = math.sqrt(10)
            self._theta_old.pi[0] = 0.5
            self._theta_old.pi[1] = 1 - self._theta_old.pi[0]
        else:
            self._theta_old.mu = np.random.uniform(self._x_min,
self._x_max, self._theta_old.count_of_gaussians)
            self._theta_old.sigma = np.random.uniform(0, self._x_max/2,
self._theta_old.count_of_gaussians)
            self._theta_old.pi[0] = np.random.uniform(0, 1)
            self._theta_old.pi[1] = 1 - self._theta_old.pi[0]

###############################################################################

        # some preparation for plotting pdfs, plot generating pdf directly
        count = 500.0
        # create x-array for plotting
        self._pdf_x = np.zeros(count)
        step = (self._x_max - self._x_min) / count
        for x in xrange(count):
            self._pdf_x = self._x_min + x * step
        # create y-array for generating pdf
        self._y_gen = p_x_G_theta(self._pdf_x, self._theta_gen)

################################################################################

        self.a = self.fig.add_subplot(221)
        self.a.axes.plot(self._pdf_x, self._y_gen)

        # initialisiere die plot-frames
        self.b = self.fig.add_subplot(223)
        self.c = self.fig.add_subplot(222)
        self.d = self.fig.add_subplot(224)
#################################################################################

        # run EM-algorithm
        self._max_iterations = 1000
        self._expectation =
np.zeros((self._theta_old.count_of_gaussians, self._data.shape[0]))
        self._log_likelihood = np.zeros((self._max_iterations))
        self._theta_history = np.zeros((self._max_iterations,
3*self._theta_old.count_of_gaussians))
        self._converged = False
        self._counter = 0
        self._epsilon = 0.001

        ################### Controller ######################
        #
        # create start/stop buttons
        self.button_start = wx.Button(self,-1, " Start ", size=(-1,-1))
        self.button_stop = wx.Button(self,-1, " Stop ", size=(-1,-1))
        self.button_exit = wx.Button(self,-1, " Exit ", size=(-1,-1))
        self.cb1 = wx.CheckBox(self, -1, "Show title" )

        # bind actions to the buttons
        self.button_start.Bind(wx.EVT_BUTTON,self.OnStart)
        self.button_stop.Bind(wx.EVT_BUTTON, self.OnStop)
        self.button_exit.Bind(wx.EVT_BUTTON, self.OnExit)

        # pack the buttons in the Sizer
        btnsizer = wx.BoxSizer(wx.HORIZONTAL)
        btnsizer.Add(self.button_start, 1, wx.LEFT)
        btnsizer.Add(self.button_stop, 1, wx.LEFT)
        btnsizer.Add(self.button_exit, 1, wx.RIGHT)

        btnsizer1 = wx.BoxSizer(wx.VERTICAL)
        btnsizer1.Add(self.cb1, 1, wx.DOWN)

        sizer.Add(btnsizer, 0, wx.TOP)
        sizer.Add(btnsizer1, 0, wx.TOP)
        self.SetSizer(sizer)
        self.Fit()
        #
        #####################################################

        # create stop-flag for multithreading
        self.stop = False

    def iterate(self):
        time.sleep(0.1)

        # store parameters to history-array
        for t in xrange(self._theta_old.count_of_gaussians):
            self._theta_history[self._counter, t] = self._theta_old.mu[t]
            self._theta_history[self._counter, 2+ t] =
self._theta_old.sigma[t]
            self._theta_history[self._counter, 4+ t] = self._theta_old.pi[t]

        # get data for y-axis of estimated pdf
        self._y_em = p_x_G_theta(self._pdf_x, self._theta_old)

        # TODO: add legend
        #pl.legend()

        # E-step
        for c in xrange(self._theta_old.count_of_gaussians):
            self._expectation[c, :] = p_c_G_x_theta(c, self._data,
self._theta_old)

        # M-step
        theta_new = Theta(2)
        update_mu(self._data, self._expectation, theta_new)
        update_sigma(self._data, self._expectation, theta_new)
        update_pi(self._data, self._expectation, theta_new)

        # compute log-likelihood
        # log-likelihood of initial theta is not logged because it is
very low
        # and the curve gets ugly :wink:
        # to try including the initial theta just move this block to
first line of the loop
        ll = p_x_G_theta(self._data, theta_new)
        ll = np.log(ll)
        ll = ll.sum()
        self._log_likelihood[self._counter] = ll

        # check convergence
        if self._counter > 0:
            if self._log_likelihood[self._counter] -
self._log_likelihood[self._counter-1] < self._epsilon:
                # idea of Gervasio: also check if parameters don't
change anymore:
                if np.abs(theta_new.mu - self._theta_old.mu).max() <
self._epsilon and np.abs(theta_new.sigma - self._theta_old.sigma).max()
< self._epsilon and np.abs(theta_new.pi - self._theta_old.pi).max() <
self._epsilon:
                    self._converged = True
            elif self._counter >= self._max_iterations:
                self._converged = True

        # increment counter
        self._counter += 1

        # update theta
        self._theta_old = theta_new

    def updateGUI(self):
        # plot pdf obtained by em-step
        self.b.axes.plot(self._pdf_x, self._y_em)
        self.canvas.draw()

        # plot history of parameters (idea of Omid!!)
        #self.d.axes.plot(self._theta_history[:self._counter-1, :])
        #self.canvas.draw()

         # plot history of likelihood
        #self.c.axes.plot(self._log_likelihood[:self._counter])
        #self.canvas.draw()
        pass

    def OnStop(self,event=None):
# self.timer.Stop()
# self.stop = True
        pass

    def OnStart(self,event=None):
# self.iterate()
################################
        self.stop = False
        action = ThreadedAction(self)
        action.start()

################################

    def OnExit(self,event=None):
        self.Destroy()

    def iterate_until_converged(self):
        while (not self._converged):
            self.iterate()

#
######################################################################################

if __name__ == '__main__':
    app = wx.PySimpleApp(0)
    frame = EM_MoG('d')
    frame.Show(True)
    app.MainLoop()

>

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

hi

so i had just tryed your idear :slight_smile: but the interface is freezing
again... here is the new updateGUI function... maybe anyone have
another idear how to get this problem solved ...

def updateGUI(self):
   self.canvas.draw()
   self.b.axes.plot(self._pdf_x, self._y_em)

···

On Jul 23, 9:44 pm, Christopher Barker <Chris.Bar...@noaa.gov> wrote:

Timo Spielmann wrote:
> the program is a main program with a gui, if i press the start button
> the program should run an algorithm and return the different
> result-steps in a graphical window. this means i would like to get a
> graphical update after each iteration

> my problem is, if i start it the interface got freezed, and a got only
> two graphical updates, one at the beginning and on at the end.

This looks right. to make sure, you might put a print statement in here,
to make sure it's getting called:

 def updateGUI\(self\):
     \# plot pdf obtained by em\-step
     self\.b\.axes\.plot\(self\.\_pdf\_x, self\.\_y\_em\)
     self\.canvas\.draw\(\)

However, if it is, then this is a MPL wx back-end issue -- I think I"ve
had troupble with it updating when I want it to in the past -- the call
to canvas.draw() should do it, but it may not.

YOu might try sprinkling:

self.canvas.Refresh()
self.canvas.Update()

In there, to force a refresh.

If that doesn't work, you may need to dig into the wx back-end code and
see what's not getting called when it should -- I've had this problem,
but I don't remember the solution at this point -- sorry!

If you're still stuck, I'd make a "simple as possible that shows the
issue" sample, and post it in the MPL list

-Chris

> sorry for my bad description, i am a quite new programmer and in python
> as well

> here is the code i talking about

> ######## imports ###########
> #
> import matplotlib
> matplotlib.use("WXAgg")
> matplotlib.interactive(True)
> from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
> from matplotlib.figure import Figure
> from matplotlib.axes import Subplot
> import matplotlib.pyplot as plt

> import numpy as np

> import pylab as pl
> import math

> import wx

> from threading import Thread
> import threading
> import time

> #
> ###########################
> wx.SetDefaultPyEncoding("iso-8859-15")

> ####################################################################################
> #

> def normal_pdf(mu, sigma, x_array):
> first_term = 1 / math.sqrt(2*math.pi * sigma * sigma)
> second_term = np.exp(-0.5 * (x_array - mu) * (x_array - mu) / (sigma
> * sigma))
> return first_term * second_term

> ####################################################################################
> #

> class Theta:
> def __init__(self, count_of_gaussians):
> # create array for each parameter and init by default-value
> self.mu = np.zeros(count_of_gaussians)
> self.sigma = np.ones(count_of_gaussians)
> self.pi = np.zeros(count_of_gaussians)
> self.pi[:] = 1.0 / count_of_gaussians
> self.count_of_gaussians = count_of_gaussians

> ####################################################################################
> #
> ########### testing threads #############
> #
> class ThreadedAction(Thread):
> def __init__(self, em_obj, **kwargs):
> Thread.__init__(self, **kwargs)
> self.em_obj = em_obj

> def run(self):
> print "Performing expensive calculation in %s..."%self.getName()

> while (not self.em_obj._converged and not self.em_obj.stop):
> self.em_obj.iterate()
> wx.CallAfter(self.em_obj.updateGUI)
> print 'done.'

> ##################################################

> # probability-functions with the convention to read:
> # for example: p_c_G_x_theta should be read as:
> # probability of c Given x (all datapoints n=1 to N) and theta
> # note: instead of defining a function for every datapoint xn we define
> a function for all datapoints

> # conditional probability of data x given class c and parameters theta
> (MoG: the gaussian with parameters mu_c, sigma_c)
> def p_x_G_c_theta(x, c, theta):
> return normal_pdf(theta.mu[c], theta.sigma[c], x)

> # marginal probability of class c given parameters theta (MoG: prior =
> const. mixture-parameter pi)
> def p_c_G_theta(c, theta):
> return theta.pi[c]

> # joint probability of data x and class c given parameters theta
> def p_x_c_G_theta(x, c, theta):
> # product-rule: conditional times marginal
> return p_x_G_c_theta(x, c, theta) * p_c_G_theta(c, theta)

> # marginal probability of data x given parameters theta
> def p_x_G_theta(x, theta):
> # sum-rule: sum of all joints
> sum_of_joints = np.zeros(x.shape[0])
> for cs in xrange(theta.count_of_gaussians):
> sum_of_joints += p_x_c_G_theta(x, cs, theta)
> return sum_of_joints

> def p_c_G_x_theta(c, x, theta):
> # applying bayes theorem using joint-probability and marginal
> joint = p_x_c_G_theta(x, c, theta)
> marginal = p_x_G_theta(x, theta)
> return joint / marginal

> def generate_data(theta, N):
> data = np.zeros(N)
> for n in xrange(N):
> c = c = np.random.uniform(0, 1)
> offset = 0
> for i in xrange(theta.count_of_gaussians):
> if c < theta.pi[i] + offset:
> data[n] = np.random.normal(theta.mu[i], theta.sigma[i])
> break
> else:
> offset += theta.pi[i]
> return data

> def update_mu(x, expectation, theta_new):
> for c in xrange(theta_new.count_of_gaussians):
> numerator = expectation[c,:] * x
> numerator = numerator.sum()
> denominator = expectation[c,:].sum()
> theta_new.mu[c] = numerator / denominator

> def update_sigma(x, expectation, theta_new):
> for c in xrange(theta_new.count_of_gaussians):
> numerator = expectation[c,:] * (x - theta_new.mu[c])**2
> numerator = numerator.sum()
> denominator = expectation[c,:].sum()
> theta_new.sigma[c] = math.sqrt(numerator / denominator)

> def update_pi(x, expectation, theta_new):
> N = x.shape[0]
> for c in xrange(theta_new.count_of_gaussians):
> theta_new.pi[c] = expectation[c,:].sum() / N

> ####################################################################################
> #
> class EM_MoG(wx.Frame):
> def __init__(self, task):
> wx.Frame.__init__(self, None, -1, "Interactive Frame v1.0")

> self.fig = Figure((10,10), 75)
> self.canvas = FigureCanvasWxAgg(self, -1, self.fig)

> sizer = wx.BoxSizer(wx.VERTICAL)
> sizer.Add(self.canvas, 1, wx.TOP)

> self._task = task

> # A: generate datapoints with given parameters
> self._theta_gen = Theta(2)
> self._theta_gen.mu[0] = -2
> self._theta_gen.mu[1] = 4
> self._theta_gen.sigma[0] = 1
> self._theta_gen.sigma[1] = math.sqrt(10)
> self._theta_gen.pi[0] = 0.4
> self._theta_gen.pi[1] = 1 - self._theta_gen.pi[0]

> self._data_count = 200
> if self._task == 'c':
> self._data_count = 5

> self._data = generate_data(self._theta_gen, self._data_count)

> # B/D: initialize theta with given initial values
> self._x_min = -20
> self._x_max = 20
> self._theta_old = Theta(2)
> if self._task <> 'd':
> self._theta_old.mu[0] = - 5
> self._theta_old.mu[1] = 5
> self._theta_old.sigma[0] = 1
> self._theta_old.sigma[1] = math.sqrt(10)
> self._theta_old.pi[0] = 0.5
> self._theta_old.pi[1] = 1 - self._theta_old.pi[0]
> else:
> self._theta_old.mu = np.random.uniform(self._x_min,
> self._x_max, self._theta_old.count_of_gaussians)
> self._theta_old.sigma = np.random.uniform(0, self._x_max/2,
> self._theta_old.count_of_gaussians)
> self._theta_old.pi[0] = np.random.uniform(0, 1)
> self._theta_old.pi[1] = 1 - self._theta_old.pi[0]

> ###############################################################################

> # some preparation for plotting pdfs, plot generating pdf directly
> count = 500.0
> # create x-array for plotting
> self._pdf_x = np.zeros(count)
> step = (self._x_max - self._x_min) / count
> for x in xrange(count):
> self._pdf_x = self._x_min + x * step
> # create y-array for generating pdf
> self._y_gen = p_x_G_theta(self._pdf_x, self._theta_gen)

> ################################################################################

> self.a = self.fig.add_subplot(221)
> self.a.axes.plot(self._pdf_x, self._y_gen)

> # initialisiere die plot-frames
> self.b = self.fig.add_subplot(223)
> self.c = self.fig.add_subplot(222)
> self.d = self.fig.add_subplot(224)
> #################################################################################

> # run EM-algorithm
> self._max_iterations = 1000
> self._expectation =
> np.zeros((self._theta_old.count_of_gaussians, self._data.shape[0]))
> self._log_likelihood = np.zeros((self._max_iterations))
> self._theta_history = np.zeros((self._max_iterations,
> 3*self._theta_old.count_of_gaussians))
> self._converged = False
> self._counter = 0
> self._epsilon = 0.001

> ################### Controller ######################
> #
> # create start/stop buttons
> self.button_start = wx.Button(self,-1, " Start ", size=(-1,-1))
> self.button_stop = wx.Button(self,-1, " Stop ", size=(-1,-1))
> self.button_exit = wx.Button(self,-1, " Exit ", size=(-1,-1))
> self.cb1 = wx.CheckBox(self, -1, "Show title" )

> # bind actions to the buttons
> self.button_start.Bind(wx.EVT_BUTTON,self.OnStart)

...

read more »

ok

here is the changed code, but the interface is freezing again... maybe
you have another good idear or you remember how you solved it :slight_smile:

def updateGUI(self):
   self.canvas.draw()
   self.b.axes.plot(self._pdf_x, self._y_em)
   #here the other plots....
   self.canvas.Refresh()
   self.canvas.Update()

···

On Jul 23, 9:44 pm, Christopher Barker <Chris.Bar...@noaa.gov> wrote:

Timo Spielmann wrote:
> the program is a main program with a gui, if i press the start button
> the program should run an algorithm and return the different
> result-steps in a graphical window. this means i would like to get a
> graphical update after each iteration

> my problem is, if i start it the interface got freezed, and a got only
> two graphical updates, one at the beginning and on at the end.

This looks right. to make sure, you might put a print statement in here,
to make sure it's getting called:

 def updateGUI\(self\):
     \# plot pdf obtained by em\-step
     self\.b\.axes\.plot\(self\.\_pdf\_x, self\.\_y\_em\)
     self\.canvas\.draw\(\)

However, if it is, then this is a MPL wx back-end issue -- I think I"ve
had troupble with it updating when I want it to in the past -- the call
to canvas.draw() should do it, but it may not.

YOu might try sprinkling:

self.canvas.Refresh()
self.canvas.Update()

In there, to force a refresh.

If that doesn't work, you may need to dig into the wx back-end code and
see what's not getting called when it should -- I've had this problem,
but I don't remember the solution at this point -- sorry!

If you're still stuck, I'd make a "simple as possible that shows the
issue" sample, and post it in the MPL list

-Chris

> sorry for my bad description, i am a quite new programmer and in python
> as well

> here is the code i talking about

> ######## imports ###########
> #
> import matplotlib
> matplotlib.use("WXAgg")
> matplotlib.interactive(True)
> from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
> from matplotlib.figure import Figure
> from matplotlib.axes import Subplot
> import matplotlib.pyplot as plt

> import numpy as np

> import pylab as pl
> import math

> import wx

> from threading import Thread
> import threading
> import time

> #
> ###########################
> wx.SetDefaultPyEncoding("iso-8859-15")

> ####################################################################################
> #

> def normal_pdf(mu, sigma, x_array):
> first_term = 1 / math.sqrt(2*math.pi * sigma * sigma)
> second_term = np.exp(-0.5 * (x_array - mu) * (x_array - mu) / (sigma
> * sigma))
> return first_term * second_term

> ####################################################################################
> #

> class Theta:
> def __init__(self, count_of_gaussians):
> # create array for each parameter and init by default-value
> self.mu = np.zeros(count_of_gaussians)
> self.sigma = np.ones(count_of_gaussians)
> self.pi = np.zeros(count_of_gaussians)
> self.pi[:] = 1.0 / count_of_gaussians
> self.count_of_gaussians = count_of_gaussians

> ####################################################################################
> #
> ########### testing threads #############
> #
> class ThreadedAction(Thread):
> def __init__(self, em_obj, **kwargs):
> Thread.__init__(self, **kwargs)
> self.em_obj = em_obj

> def run(self):
> print "Performing expensive calculation in %s..."%self.getName()

> while (not self.em_obj._converged and not self.em_obj.stop):
> self.em_obj.iterate()
> wx.CallAfter(self.em_obj.updateGUI)
> print 'done.'

> ##################################################

> # probability-functions with the convention to read:
> # for example: p_c_G_x_theta should be read as:
> # probability of c Given x (all datapoints n=1 to N) and theta
> # note: instead of defining a function for every datapoint xn we define
> a function for all datapoints

> # conditional probability of data x given class c and parameters theta
> (MoG: the gaussian with parameters mu_c, sigma_c)
> def p_x_G_c_theta(x, c, theta):
> return normal_pdf(theta.mu[c], theta.sigma[c], x)

> # marginal probability of class c given parameters theta (MoG: prior =
> const. mixture-parameter pi)
> def p_c_G_theta(c, theta):
> return theta.pi[c]

> # joint probability of data x and class c given parameters theta
> def p_x_c_G_theta(x, c, theta):
> # product-rule: conditional times marginal
> return p_x_G_c_theta(x, c, theta) * p_c_G_theta(c, theta)

> # marginal probability of data x given parameters theta
> def p_x_G_theta(x, theta):
> # sum-rule: sum of all joints
> sum_of_joints = np.zeros(x.shape[0])
> for cs in xrange(theta.count_of_gaussians):
> sum_of_joints += p_x_c_G_theta(x, cs, theta)
> return sum_of_joints

> def p_c_G_x_theta(c, x, theta):
> # applying bayes theorem using joint-probability and marginal
> joint = p_x_c_G_theta(x, c, theta)
> marginal = p_x_G_theta(x, theta)
> return joint / marginal

> def generate_data(theta, N):
> data = np.zeros(N)
> for n in xrange(N):
> c = c = np.random.uniform(0, 1)
> offset = 0
> for i in xrange(theta.count_of_gaussians):
> if c < theta.pi[i] + offset:
> data[n] = np.random.normal(theta.mu[i], theta.sigma[i])
> break
> else:
> offset += theta.pi[i]
> return data

> def update_mu(x, expectation, theta_new):
> for c in xrange(theta_new.count_of_gaussians):
> numerator = expectation[c,:] * x
> numerator = numerator.sum()
> denominator = expectation[c,:].sum()
> theta_new.mu[c] = numerator / denominator

> def update_sigma(x, expectation, theta_new):
> for c in xrange(theta_new.count_of_gaussians):
> numerator = expectation[c,:] * (x - theta_new.mu[c])**2
> numerator = numerator.sum()
> denominator = expectation[c,:].sum()
> theta_new.sigma[c] = math.sqrt(numerator / denominator)

> def update_pi(x, expectation, theta_new):
> N = x.shape[0]
> for c in xrange(theta_new.count_of_gaussians):
> theta_new.pi[c] = expectation[c,:].sum() / N

> ####################################################################################
> #
> class EM_MoG(wx.Frame):
> def __init__(self, task):
> wx.Frame.__init__(self, None, -1, "Interactive Frame v1.0")

> self.fig = Figure((10,10), 75)
> self.canvas = FigureCanvasWxAgg(self, -1, self.fig)

> sizer = wx.BoxSizer(wx.VERTICAL)
> sizer.Add(self.canvas, 1, wx.TOP)

> self._task = task

> # A: generate datapoints with given parameters
> self._theta_gen = Theta(2)
> self._theta_gen.mu[0] = -2
> self._theta_gen.mu[1] = 4
> self._theta_gen.sigma[0] = 1
> self._theta_gen.sigma[1] = math.sqrt(10)
> self._theta_gen.pi[0] = 0.4
> self._theta_gen.pi[1] = 1 - self._theta_gen.pi[0]

> self._data_count = 200
> if self._task == 'c':
> self._data_count = 5

> self._data = generate_data(self._theta_gen, self._data_count)

> # B/D: initialize theta with given initial values
> self._x_min = -20
> self._x_max = 20
> self._theta_old = Theta(2)
> if self._task <> 'd':
> self._theta_old.mu[0] = - 5
> self._theta_old.mu[1] = 5
> self._theta_old.sigma[0] = 1
> self._theta_old.sigma[1] = math.sqrt(10)
> self._theta_old.pi[0] = 0.5
> self._theta_old.pi[1] = 1 - self._theta_old.pi[0]
> else:
> self._theta_old.mu = np.random.uniform(self._x_min,
> self._x_max, self._theta_old.count_of_gaussians)
> self._theta_old.sigma = np.random.uniform(0, self._x_max/2,
> self._theta_old.count_of_gaussians)
> self._theta_old.pi[0] = np.random.uniform(0, 1)
> self._theta_old.pi[1] = 1 - self._theta_old.pi[0]

> ###############################################################################

> # some preparation for plotting pdfs, plot generating pdf directly
> count = 500.0
> # create x-array for plotting
> self._pdf_x = np.zeros(count)
> step = (self._x_max - self._x_min) / count
> for x in xrange(count):
> self._pdf_x = self._x_min + x * step
> # create y-array for generating pdf
> self._y_gen = p_x_G_theta(self._pdf_x, self._theta_gen)

> ################################################################################

> self.a = self.fig.add_subplot(221)
> self.a.axes.plot(self._pdf_x, self._y_gen)

> # initialisiere die plot-frames
> self.b = self.fig.add_subplot(223)
> self.c = self.fig.add_subplot(222)
> self.d = self.fig.add_subplot(224)
> #################################################################################

> # run EM-algorithm
> self._max_iterations = 1000
> self._expectation =
> np.zeros((self._theta_old.count_of_gaussians, self._data.shape[0]))
> self._log_likelihood = np.zeros((self._max_iterations))
> self._theta_history = np.zeros((self._max_iterations,
> 3*self._theta_old.count_of_gaussians))
> self._converged = False
> self._counter = 0
> self._epsilon = 0.001

> ################### Controller ######################
> #
> # create start/stop buttons
> self.button_start = wx.Button(self,-1, " Start ", size=(-1,-1))
> self.button_stop = wx.Button(self,-1, " Stop ", size=(-1,-1))
> self.button_exit = wx.Button(self,-1, " Exit ", size=(-1,-1))
> self.cb1 = wx.CheckBox(self, -1, "Show title" )

> # bind actions to the buttons
> self.button_start.Bind(wx.EVT_BUTTON,self.OnStart)

...

read more »

ok

here is the changed code, but the interface is freezing again... maybe
you have another good idear or you remember how you solved it :slight_smile:

def updateGUI(self):
   self.canvas.draw()
   self.b.axes.plot(self._pdf_x, self._y_em)
   #here the other plots....
   self.canvas.Refresh()
   self.canvas.Update()

···

On Jul 23, 9:44 pm, Christopher Barker <Chris.Bar...@noaa.gov> wrote:

Timo Spielmann wrote:
> the program is a main program with a gui, if i press the start button
> the program should run an algorithm and return the different
> result-steps in a graphical window. this means i would like to get a
> graphical update after each iteration

> my problem is, if i start it the interface got freezed, and a got only
> two graphical updates, one at the beginning and on at the end.

This looks right. to make sure, you might put a print statement in here,
to make sure it's getting called:

 def updateGUI\(self\):
     \# plot pdf obtained by em\-step
     self\.b\.axes\.plot\(self\.\_pdf\_x, self\.\_y\_em\)
     self\.canvas\.draw\(\)

However, if it is, then this is a MPL wx back-end issue -- I think I"ve
had troupble with it updating when I want it to in the past -- the call
to canvas.draw() should do it, but it may not.

YOu might try sprinkling:

self.canvas.Refresh()
self.canvas.Update()

In there, to force a refresh.

If that doesn't work, you may need to dig into the wx back-end code and
see what's not getting called when it should -- I've had this problem,
but I don't remember the solution at this point -- sorry!

If you're still stuck, I'd make a "simple as possible that shows the
issue" sample, and post it in the MPL list

-Chris

> sorry for my bad description, i am a quite new programmer and in python
> as well

> here is the code i talking about

> ######## imports ###########
> #
> import matplotlib
> matplotlib.use("WXAgg")
> matplotlib.interactive(True)
> from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
> from matplotlib.figure import Figure
> from matplotlib.axes import Subplot
> import matplotlib.pyplot as plt

> import numpy as np

> import pylab as pl
> import math

> import wx

> from threading import Thread
> import threading
> import time

> #
> ###########################
> wx.SetDefaultPyEncoding("iso-8859-15")

> ####################################################################################
> #

> def normal_pdf(mu, sigma, x_array):
> first_term = 1 / math.sqrt(2*math.pi * sigma * sigma)
> second_term = np.exp(-0.5 * (x_array - mu) * (x_array - mu) / (sigma
> * sigma))
> return first_term * second_term

> ####################################################################################
> #

> class Theta:
> def __init__(self, count_of_gaussians):
> # create array for each parameter and init by default-value
> self.mu = np.zeros(count_of_gaussians)
> self.sigma = np.ones(count_of_gaussians)
> self.pi = np.zeros(count_of_gaussians)
> self.pi[:] = 1.0 / count_of_gaussians
> self.count_of_gaussians = count_of_gaussians

> ####################################################################################
> #
> ########### testing threads #############
> #
> class ThreadedAction(Thread):
> def __init__(self, em_obj, **kwargs):
> Thread.__init__(self, **kwargs)
> self.em_obj = em_obj

> def run(self):
> print "Performing expensive calculation in %s..."%self.getName()

> while (not self.em_obj._converged and not self.em_obj.stop):
> self.em_obj.iterate()
> wx.CallAfter(self.em_obj.updateGUI)
> print 'done.'

> ##################################################

> # probability-functions with the convention to read:
> # for example: p_c_G_x_theta should be read as:
> # probability of c Given x (all datapoints n=1 to N) and theta
> # note: instead of defining a function for every datapoint xn we define
> a function for all datapoints

> # conditional probability of data x given class c and parameters theta
> (MoG: the gaussian with parameters mu_c, sigma_c)
> def p_x_G_c_theta(x, c, theta):
> return normal_pdf(theta.mu[c], theta.sigma[c], x)

> # marginal probability of class c given parameters theta (MoG: prior =
> const. mixture-parameter pi)
> def p_c_G_theta(c, theta):
> return theta.pi[c]

> # joint probability of data x and class c given parameters theta
> def p_x_c_G_theta(x, c, theta):
> # product-rule: conditional times marginal
> return p_x_G_c_theta(x, c, theta) * p_c_G_theta(c, theta)

> # marginal probability of data x given parameters theta
> def p_x_G_theta(x, theta):
> # sum-rule: sum of all joints
> sum_of_joints = np.zeros(x.shape[0])
> for cs in xrange(theta.count_of_gaussians):
> sum_of_joints += p_x_c_G_theta(x, cs, theta)
> return sum_of_joints

> def p_c_G_x_theta(c, x, theta):
> # applying bayes theorem using joint-probability and marginal
> joint = p_x_c_G_theta(x, c, theta)
> marginal = p_x_G_theta(x, theta)
> return joint / marginal

> def generate_data(theta, N):
> data = np.zeros(N)
> for n in xrange(N):
> c = c = np.random.uniform(0, 1)
> offset = 0
> for i in xrange(theta.count_of_gaussians):
> if c < theta.pi[i] + offset:
> data[n] = np.random.normal(theta.mu[i], theta.sigma[i])
> break
> else:
> offset += theta.pi[i]
> return data

> def update_mu(x, expectation, theta_new):
> for c in xrange(theta_new.count_of_gaussians):
> numerator = expectation[c,:] * x
> numerator = numerator.sum()
> denominator = expectation[c,:].sum()
> theta_new.mu[c] = numerator / denominator

> def update_sigma(x, expectation, theta_new):
> for c in xrange(theta_new.count_of_gaussians):
> numerator = expectation[c,:] * (x - theta_new.mu[c])**2
> numerator = numerator.sum()
> denominator = expectation[c,:].sum()
> theta_new.sigma[c] = math.sqrt(numerator / denominator)

> def update_pi(x, expectation, theta_new):
> N = x.shape[0]
> for c in xrange(theta_new.count_of_gaussians):
> theta_new.pi[c] = expectation[c,:].sum() / N

> ####################################################################################
> #
> class EM_MoG(wx.Frame):
> def __init__(self, task):
> wx.Frame.__init__(self, None, -1, "Interactive Frame v1.0")

> self.fig = Figure((10,10), 75)
> self.canvas = FigureCanvasWxAgg(self, -1, self.fig)

> sizer = wx.BoxSizer(wx.VERTICAL)
> sizer.Add(self.canvas, 1, wx.TOP)

> self._task = task

> # A: generate datapoints with given parameters
> self._theta_gen = Theta(2)
> self._theta_gen.mu[0] = -2
> self._theta_gen.mu[1] = 4
> self._theta_gen.sigma[0] = 1
> self._theta_gen.sigma[1] = math.sqrt(10)
> self._theta_gen.pi[0] = 0.4
> self._theta_gen.pi[1] = 1 - self._theta_gen.pi[0]

> self._data_count = 200
> if self._task == 'c':
> self._data_count = 5

> self._data = generate_data(self._theta_gen, self._data_count)

> # B/D: initialize theta with given initial values
> self._x_min = -20
> self._x_max = 20
> self._theta_old = Theta(2)
> if self._task <> 'd':
> self._theta_old.mu[0] = - 5
> self._theta_old.mu[1] = 5
> self._theta_old.sigma[0] = 1
> self._theta_old.sigma[1] = math.sqrt(10)
> self._theta_old.pi[0] = 0.5
> self._theta_old.pi[1] = 1 - self._theta_old.pi[0]
> else:
> self._theta_old.mu = np.random.uniform(self._x_min,
> self._x_max, self._theta_old.count_of_gaussians)
> self._theta_old.sigma = np.random.uniform(0, self._x_max/2,
> self._theta_old.count_of_gaussians)
> self._theta_old.pi[0] = np.random.uniform(0, 1)
> self._theta_old.pi[1] = 1 - self._theta_old.pi[0]

> ###############################################################################

> # some preparation for plotting pdfs, plot generating pdf directly
> count = 500.0
> # create x-array for plotting
> self._pdf_x = np.zeros(count)
> step = (self._x_max - self._x_min) / count
> for x in xrange(count):
> self._pdf_x = self._x_min + x * step
> # create y-array for generating pdf
> self._y_gen = p_x_G_theta(self._pdf_x, self._theta_gen)

> ################################################################################

> self.a = self.fig.add_subplot(221)
> self.a.axes.plot(self._pdf_x, self._y_gen)

> # initialisiere die plot-frames
> self.b = self.fig.add_subplot(223)
> self.c = self.fig.add_subplot(222)
> self.d = self.fig.add_subplot(224)
> #################################################################################

> # run EM-algorithm
> self._max_iterations = 1000
> self._expectation =
> np.zeros((self._theta_old.count_of_gaussians, self._data.shape[0]))
> self._log_likelihood = np.zeros((self._max_iterations))
> self._theta_history = np.zeros((self._max_iterations,
> 3*self._theta_old.count_of_gaussians))
> self._converged = False
> self._counter = 0
> self._epsilon = 0.001

> ################### Controller ######################
> #
> # create start/stop buttons
> self.button_start = wx.Button(self,-1, " Start ", size=(-1,-1))
> self.button_stop = wx.Button(self,-1, " Stop ", size=(-1,-1))
> self.button_exit = wx.Button(self,-1, " Exit ", size=(-1,-1))
> self.cb1 = wx.CheckBox(self, -1, "Show title" )

> # bind actions to the buttons
> self.button_start.Bind(wx.EVT_BUTTON,self.OnStart)

...

read more »