def button_open(entry):
			d = gtk.FileChooserDialog(title='Open Hidden Markov Model',
			                          action=gtk.FILE_CHOOSER_ACTION_OPEN,
			                          buttons=(gtk.STOCK_CANCEL, \
			                                   gtk.RESPONSE_CANCEL, \
			                                   gtk.STOCK_OPEN, \
			                                   gtk.RESPONSE_OK),
			                          parent=self)
			d.set_select_multiple(False)
			d.set_default_response(gtk.RESPONSE_OK)

			filter = gtk.FileFilter()
			filter.set_name('Hidden Markov Model')
			#filter.add_mime_type('text/*')
			for ext1 in ('.txt', '.hmm'):
				for ext2 in ('', '.gz', '.bz2'):
					filter.add_pattern('*' + ext1 + ext2)
			d.add_filter(filter)

			filter = gtk.FileFilter()
			filter.set_name('All files')
			filter.add_mime_type('*/*')
			filter.add_pattern('*')
			d.add_filter(filter)

			response = d.run()
			if response != gtk.RESPONSE_OK:
				d.destroy()
				return
			file_name = d.get_filename()

			self.hmm = HiddenMarkovModel.load(open(file_name, 'rb'))
			d.destroy()
		def button_new(entry):
			d = NewHMMDialog(title='Create new Hidden Markov Model',
			                 buttons=(gtk.STOCK_CANCEL, \
			                          gtk.RESPONSE_CANCEL, \
			                          gtk.STOCK_OK, \
			                          gtk.RESPONSE_OK),
			                 parent=self)
			response = d.run()
			if response == gtk.RESPONSE_OK:
				self.state_list = d.state_list
				self.emission_list = d.emission_list
				d.destroy()
			else:
				d.destroy()
				return

			#generate default values for tables
			states_iter = self.state_list.get_iter_root()
			states = []
			while states_iter:
				states.append(self.state_list.get(states_iter, 0)[0])
				states_iter = self.state_list.iter_next(states_iter)

			emissions_iter = self.emission_list.get_iter_root()
			observations = []
			while emissions_iter:
				observations.append(self.emission_list.get(emissions_iter, 0)[0])
				emissions_iter = self.emission_list.iter_next(emissions_iter)

			N = len(states)
			M = len(observations)
			emissions = [x[:] for x in [[0] * M] * N]
			for i in xrange(N):
				emissions[i][i%M] = 1
			self.hmm = HiddenMarkovModel(states=states,
			                             observations=observations,
			                             transitions=[x[:] for x in [[1.0/N]*N]*N],
			                             emissions=emissions,
			                             initial=[1] + [0]*(N-1))
class HMMWindow(MainWindow):
	__gsignals__ = {
		'hmm_changed': (gobject.SIGNAL_RUN_FIRST, None, (HiddenMarkovModel,))
	}

	def __init_menu__(self):
		self.menu_bar = gtk.MenuBar()
		self.vbox_main.pack_start(self.menu_bar, False, False, 0)

		def menu(title, parent=None):
			if not parent:
				parent = self.menu_bar
			def decorator(callback):
				menu = gtk.Menu()
				menu_item = gtk.MenuItem(title)
				menu_item.set_submenu(menu)
				parent.append(menu_item)
				return menu
			return decorator

		def button(menu, title):
			def decorator(callback):
				b = gtk.MenuItem(title)
				b.connect('activate', callback)
				menu.append(b)
				return b
			return decorator

		# Model menu:

		@menu('Model')
		def menu_model():
			pass

		@button(menu_model, 'New …')
		def button_new(entry):
			d = NewHMMDialog(title='Create new Hidden Markov Model',
			                 buttons=(gtk.STOCK_CANCEL, \
			                          gtk.RESPONSE_CANCEL, \
			                          gtk.STOCK_OK, \
			                          gtk.RESPONSE_OK),
			                 parent=self)
			response = d.run()
			if response == gtk.RESPONSE_OK:
				self.state_list = d.state_list
				self.emission_list = d.emission_list
				d.destroy()
			else:
				d.destroy()
				return

			#generate default values for tables
			states_iter = self.state_list.get_iter_root()
			states = []
			while states_iter:
				states.append(self.state_list.get(states_iter, 0)[0])
				states_iter = self.state_list.iter_next(states_iter)

			emissions_iter = self.emission_list.get_iter_root()
			observations = []
			while emissions_iter:
				observations.append(self.emission_list.get(emissions_iter, 0)[0])
				emissions_iter = self.emission_list.iter_next(emissions_iter)

			N = len(states)
			M = len(observations)
			emissions = [x[:] for x in [[0] * M] * N]
			for i in xrange(N):
				emissions[i][i%M] = 1
			self.hmm = HiddenMarkovModel(states=states,
			                             observations=observations,
			                             transitions=[x[:] for x in [[1.0/N]*N]*N],
			                             emissions=emissions,
			                             initial=[1] + [0]*(N-1))

		@button(menu_model, 'Open …')
		def button_open(entry):
			d = gtk.FileChooserDialog(title='Open Hidden Markov Model',
			                          action=gtk.FILE_CHOOSER_ACTION_OPEN,
			                          buttons=(gtk.STOCK_CANCEL, \
			                                   gtk.RESPONSE_CANCEL, \
			                                   gtk.STOCK_OPEN, \
			                                   gtk.RESPONSE_OK),
			                          parent=self)
			d.set_select_multiple(False)
			d.set_default_response(gtk.RESPONSE_OK)

			filter = gtk.FileFilter()
			filter.set_name('Hidden Markov Model')
			#filter.add_mime_type('text/*')
			for ext1 in ('.txt', '.hmm'):
				for ext2 in ('', '.gz', '.bz2'):
					filter.add_pattern('*' + ext1 + ext2)
			d.add_filter(filter)

			filter = gtk.FileFilter()
			filter.set_name('All files')
			filter.add_mime_type('*/*')
			filter.add_pattern('*')
			d.add_filter(filter)

			response = d.run()
			if response != gtk.RESPONSE_OK:
				d.destroy()
				return
			file_name = d.get_filename()

			self.hmm = HiddenMarkovModel.load(open(file_name, 'rb'))
			d.destroy()

		@button(menu_model, 'Save')
		def button_save(entry):
			pass

		@button(menu_model, 'Save as …')
		def button_save_as(entry):
			d = gtk.FileChooserDialog(title=None,
			                          action=gtk.FILE_CHOOSER_ACTION_SAVE,
			                          buttons=(gtk.STOCK_CANCEL, \
			                                   gtk.RESPONSE_CANCEL, \
			                                   gtk.STOCK_SAVE, \
			                                   gtk.RESPONSE_OK),
			                          parent=self)
			d.set_select_multiple(False)
			d.set_default_response(gtk.RESPONSE_OK)

			response = d.run()
			if response != gtk.RESPONSE_OK:
				d.destroy()
				return
			file_name = d.get_filename()

			self.hmm.dump(fp=open(file_name, 'wb'), indent=2)
			d.destroy()

		menu_model.append(gtk.SeparatorMenuItem())

		@button(menu_model, 'Close')
		def button_save_as(entry):
			self.destroy(self, entry)

		# Settings menu:

		@menu('Settings')
		def menu_settings():
			pass

		@button(menu_settings, None)
		def button_use_matlab(entry):
			algorithm.use_next_backend()
			self.button_use_matlab.set_label("Use backend %s (currently %s)" % algorithm.get_cur_backend()[::-1])
		self.button_use_matlab = button_use_matlab
		self.button_use_matlab.set_label("Use backend %s (currently %s)" % algorithm.get_cur_backend()[::-1])

		# Operations menu:

		@menu('Operations')
		def menu_operations():
			pass

		def button_with_seq(title):
			def decorator(callback):
				def calc(file_name, seq):
					tlv = { 'status_id': self.statusbar.push(0, "Calculating %s" % title) }

					def status_cb(status):
						if type(status) is float:
							self.statusbar.set_fraction(status)
						new_status_id = self.statusbar.push(0, "Calculating %s: %s" %
								(title, "%.2f%%" % (status*100) if type(status) is float else status))
						self.statusbar.remove_message(0, tlv['status_id'])
						tlv['status_id'] = new_status_id

					callback(file_name, seq, status_cb)
					self.statusbar.remove_message(0, tlv['status_id'])
					self.statusbar.set_fraction(0)

				def action(entry):
					result = load_sequence(self, self.hmm.observations)
					if result:
						thread.start_new_thread(calc, result)

				return button(menu_operations, title)(action)
			return decorator
		
		@button_with_seq('Probability of an Observed Sequence')
		def menu_operations_prob_of_obs_seq(file_name, sequence, status_cb):
			result = backend.prob_of_observed_seq(self.hmm, sequence, status_cb)

			dialog = gtk.MessageDialog(
				parent = self,
				buttons = gtk.BUTTONS_OK,
				message_format = "Probability of this sequence:  %s" % (result),
			)
			dialog.format_secondary_text("Input Sequence:  %s" % abspath(file_name.split("/")[-1]))
			dialog.connect('response', lambda dialog, response: dialog.destroy())
			dialog.run()

		@button_with_seq('Viterbi')
		def menu_operations_viterbi(file_name, sequence, status_cb):
			(result,f_name) = backend.viterbi(self.hmm, sequence, status_cb)

			dialog = gtk.MessageDialog(
				parent = self,
				buttons = gtk.BUTTONS_OK,
				message_format = "Wrote file: %s" % abspath(f_name),
			)
			dialog.format_secondary_text("Input Sequence: %s\n\nSample of Result (first 10 states):  %s" %
					(abspath(file_name.split("/")[-1]), str(result).strip('[').strip(']')))
			dialog.connect('response', lambda dialog, response: dialog.destroy())
			dialog.run()

		@button_with_seq('Baum-Welch')
		def button_baum_welch_from_seq_file(file_name, sequence, status_cb):
			backend.baum_welch(self.hmm, sequence, status_cb)
			self.emit('hmm_changed', self._hmm)
			# TODO: some dialog

		# Help menu:

		@menu('Help')
		def menu_help():
			pass

		@button(menu_help, 'About')
		def button_save_as(entry):
			dialog = gtk.AboutDialog()

			pic = gtk.gdk.pixbuf_new_from_file(join(dirname(abspath(__file__)), 'about-icon.png'))

			dialog.set_logo(pic)
			dialog.set_name('Telematik Hidden Markov Tool')
			dialog.set_version('1.0')
			dialog.set_copyright("Copyright © 2012 René Kijewski\nCopyright © 2012 Stefan Friesel\nCopyright © 2012 Simon Putzke\nCopyright © 2012 Daniel Snider")
			dialog.set_comments("A tool for analyses of hidden Markov models\n\nSummer Semester 2012,  Prof. Dr. Katinka Wolter")
			dialog.set_website("http://kijewski.github.com/swp-telematik-2012-hidden-markov/")
			dialog.set_website_label("Development Website")

			dialog.run()
			dialog.destroy()

	def _display_widget_do_hmm_changed(self, hmm):
		self.notebook.display_widget.set_hmm(hmm)

	def __init_xdot__(self):
		self.notebook.display_widget = HMMDisplayWidget()
		self.notebook.append_page(self.notebook.display_widget, gtk.Label("graphical"))

		def on_url_clicked(widget, kind, index, event):
			dialog = gtk.MessageDialog(
				parent = self,
				buttons = gtk.BUTTONS_OK,
				message_format="You clicked on the %d. %s" % (index+1, kind)
			)
			dialog.connect('response', lambda dialog, response: dialog.destroy())
			dialog.run()
			return True
		self.notebook.display_widget.connect('hmm_clicked', on_url_clicked)

		self.connect_object('hmm_changed', HMMWindow._display_widget_do_hmm_changed, self)

	def __init_status_bar__(self):
		self.statusbar = StatusProgressBar()
		self.statusbar.push(0, 'Telehmmatic started …')
		self.vbox_main.pack_end(self.statusbar, False, True, 0)

	def on_initial_values_updated(self, table):
		assert(row == 0)
		try:
			initial = [float(table[0][i]) for i in xrange(len(self.hmm.initial))]
			s = sum(initial)
			self.hmm.initial = [x/s for x in initial]
		finally:
			self.emit('hmm_changed', self._hmm)

	def on_emission_values_updated(self, table):
		try:
			emissions = [[float(table[state, emission]) for emission in xrange(len(self.hmm.observations))] for state in xrange(len(self.hmm.states))]
			s = [sum(emissions[state]) for state in xrange(len(self.hmm.states))]
			self.hmm.emissions = [[emissions[state][emission]/s[state] for emission in xrange(len(self.hmm.observations))] for state in xrange(len(self.hmm.states))]
		finally:
			self.emit('hmm_changed', self._hmm)

	def on_transition_values_updated(self, table):
		try:
			transitions = [[float(table[current, next]) for next in xrange(len(self.hmm.states))] for current in xrange(len(self.hmm.states))]
			s = [sum(transitions[current]) for current in xrange(len(self.hmm.states))]
			self.hmm.transitions = [[transitions[current][next]/s[current] for next in xrange(len(self.hmm.states))] for current in xrange(len(self.hmm.states))]
		finally:
			self.emit('hmm_changed', self._hmm)

	def _init_notebook(self):
		self.notebook = gtk.Notebook()
		self.__init_xdot__()
		transition_tab = TransitionTab(self)
		self.connect('hmm_changed', transition_tab.on_hmm_changed)
		self.notebook.append_page(transition_tab, gtk.Label('transitions'))
		emission_tab = EmissionTab(self)
		self.connect('hmm_changed', emission_tab.on_hmm_changed)
		self.notebook.append_page(emission_tab, gtk.Label('emissions'))
		initial_tab = InitialTab(self)
		self.connect('hmm_changed', initial_tab.on_hmm_changed)
		self.notebook.append_page(initial_tab, gtk.Label('initial'))
		self.vbox_main.pack_start(self.notebook)

	def __init__(self):
		super(HMMWindow, self).__init__('Telehmmatic')

		self.__init_menu__()
		self.__init_status_bar__()
		self._init_notebook()

		#on startup, load a simple example hmm for testing and illustration
		self.hmm = load_default_hmm()

		self.show_all()

	@property
	def hmm(self):
		return self._hmm

	@hmm.setter
	def hmm(self, hmm):
		self._hmm = hmm
		self.emit('hmm_changed', self._hmm)
def load_default_hmm():
	return HiddenMarkovModel.load(open(join(dirname(abspath(__file__)),
			pardir, pardir, 'default_model.hmm'), 'rb'))