class HMMEditor(SAGraphEditor): def __init__(self, master=None): SAGraphEditor.__init__(self, master) self.G = Graph() self.G.directed = 1 self.G.euclidian = 0 self.G.simple = 0 self.HMM = HMM(self, self.G) def CreateWidgets(self): toolbar = Frame(self, cursor='hand2', relief=FLAT) toolbar.pack(side=LEFT, fill=Y) # Allows horizontal growth extra = Frame(toolbar, cursor='hand2', relief=SUNKEN, borderwidth=2) extra.pack(side=TOP) # Allows horizontal growth extra.rowconfigure(6, weight=1) extra.bind("<Enter>", lambda e, gd=self: gd.DefaultInfo()) px = 0 py = 3 self.toolVar = StringVar() import GatoIcons # Load Icons self.vertexIcon = PhotoImage(data=GatoIcons.vertex) self.edgeIcon = PhotoImage(data=GatoIcons.edge) self.deleteIcon = PhotoImage(data=GatoIcons.delete) self.swapIcon = PhotoImage(data=GatoIcons.swap) self.editIcon = PhotoImage(data=GatoIcons.edit) self.propIcon = PhotoImage(data=GatoIcons.edit) b = Radiobutton(extra, width=32, padx=px, pady=py, text='Add or move vertex', command=self.ChangeTool, var=self.toolVar, value='AddOrMoveVertex', indicator=0, image=self.vertexIcon) b.grid(row=0, column=0, padx=2, pady=2) b.bind("<Enter>", lambda e, gd=self: gd.UpdateInfo('Add or move vertex')) self.defaultButton = b # default doesnt work as config option b = Radiobutton(extra, width=32, padx=px, pady=py, text='Add edge', command=self.ChangeTool, var=self.toolVar, value='AddEdge', indicator=0, image=self.edgeIcon) b.grid(row=1, column=0, padx=2, pady=2) b.bind("<Enter>", lambda e, gd=self: gd.UpdateInfo('Add edge')) b = Radiobutton(extra, width=32, padx=px, pady=py, text='Delete edge or vertex', command=self.ChangeTool, var=self.toolVar, value='DeleteEdgeOrVertex', indicator=0, image=self.deleteIcon) b.grid(row=2, column=0, padx=2, pady=2) b.bind("<Enter>", lambda e, gd=self: gd.UpdateInfo('Delete edge or vertex')) b = Radiobutton(extra, width=32, padx=px, pady=py, text='Swap orientation', command=self.ChangeTool, var=self.toolVar, value='SwapOrientation', indicator=0, image=self.swapIcon) b.grid(row=3, column=0, padx=2, pady=2) b.bind("<Enter>", lambda e, gd=self: gd.UpdateInfo('Swap orientation')) b = Radiobutton(extra, width=32, padx=px, pady=py, text='Edit Weight', command=self.ChangeTool, var=self.toolVar, value='EditWeight', indicator=0, image=self.editIcon) b.grid(row=4, column=0, padx=2, pady=2) b.bind("<Enter>", lambda e, gd=self: gd.UpdateInfo('Edit Weight')) b = Radiobutton(extra, width=32, padx=px, pady=py, text='Edit Properties', command=self.ChangeTool, var=self.toolVar, value='EditProperties', indicator=0, image=self.editIcon) b.grid(row=5, column=0, padx=2, pady=2) b.bind("<Enter>", lambda e, gd=self: gd.UpdateInfo('Edit Properties')) # disable the EditProperties button ## b = Radiobutton(extra, width=32, padx=px, pady=py, ## text='Edit State', ## command=self.ChangeTool, ## var = self.toolVar, value='EditState', indicator=0, ## image=self.editIcon) ## b.grid(row=6, column=0, padx=2, pady=2) ## b.bind("<Enter>", lambda e, gd=self:gd.UpdateInfo('Edit State')) GraphEditor.CreateWidgets(self) #----- Tools Menu callbacks def ChangeTool(self): self.SetEditMode(self.toolVar.get()) def MouseUp(self, event): if self.mode == 'AddOrMoveVertex': self.AddOrMoveVertexUp(event) elif self.mode == 'AddEdge': self.AddEdgeUp(event) elif self.mode == 'DeleteEdgeOrVertex': self.DeleteEdgeOrVertexUp(event) elif self.mode == 'SwapOrientation': self.SwapOrientationUp(event) elif self.mode == 'EditWeight': self.EditWeightUp(event) elif self.mode == 'EditProperties': self.EditPropertiesUp(event) elif self.mode == 'EditState': # test EditObj self.EditHMMObj(event) def makeMenuBar(self): self.menubar = Menu(self, tearoff=0) # Add file menu self.fileMenu = Menu(self.menubar, tearoff=0) self.fileMenu.add_command(label='New', command=self.NewGraph) self.fileMenu.add_command(label='Open ...', command=self.OpenGraph) self.fileMenu.add_command(label='Save', command=self.SaveGraph) self.fileMenu.add_command(label='Save as ...', command=self.SaveAsGraph) self.fileMenu.add_separator() self.fileMenu.add_command(label='Export EPSF...', command=self.ExportEPSF) self.fileMenu.add_separator() self.fileMenu.add_command(label='Quit', command=self.Quit) self.menubar.add_cascade(label="File", menu=self.fileMenu, underline=0) self.graphMenu = Menu(self.menubar, tearoff=0) self.graphMenu.add_command(label='Edit HMM', command=self.EditHMM) self.graphMenu.add_command(label='Edit Class label', command=self.EditClassLabel) # XXX Note if we change alphabet, we have to change all emissions self.graphMenu.add_command(label='Edit Alphabet', command=self.EditAlphabet) self.graphMenu.add_command(label='Edit Prior', command=self.EditPrior) self.graphMenu.add_command(label='Edit Background Distributions', command=self.EditBackgroundDistributions) self.graphMenu.add_separator() self.graphMenu.add_checkbutton(label='Grid', command=self.ToggleGridding) self.menubar.add_cascade(label="HMM", menu=self.graphMenu, underline=0) self.master.configure(menu=self.menubar) def SetGraphMenuOptions(self): if not self.gridding: self.graphMenu.invoke(self.graphMenu.index('Grid')) ############################################################ # # Menu Commands # # The menu commands are passed as call back parameters to # the menu items. # def NewGraph(self, nrOfSymbols=0, newInput=1): self.DeleteDrawItems() # clear screen if self.hasGraph == 1: self.G.Clear() self.HMM.G.Clear() self.hasGraph = 0 self.HMM = HMM(self, self.G) self.graphName = "New" self.ShowGraph(self.HMM.G, self.graphName) self.RegisterGraphInformer(HMMInformer(self.HMM)) self.fileName = None self.SetTitle("HMMEd _VERSION_ - New Graph") self.SetGraphMenuOptions() if newInput: if nrOfSymbols == 0: nrOfSymbols = tkSimpleDialog.askinteger( "New HMM", "Enter the number of output symbols") for i in xrange(nrOfSymbols): self.HMM.G.vertexWeights[i] = VertexWeight(0.0) self.HMM.hmmAlphabet = DiscreteHMMAlphabet(nrOfSymbols) def OpenGraph(self): self.DeleteDrawItems() # clear screen if self.hasGraph == 1: self.G.Clear() self.HMM.G.Clear() self.HMM.Clear() self.hasGraph = 0 file = askopenfilename(title="Open HMM", defaultextension=".xml", filetypes=(("XML", ".xml"), )) if file is "": print "cancelled" else: self.fileName = file self.graphName = stripPath(file) e = extension(file) if e == 'xml': self.HMM.OpenXML(file) else: print "Unknown extension" return #self.HMM.hmmAlphabet ? #self.HMM.hmmClass ? self.ShowGraph(self.HMM.G, self.graphName) self.RegisterGraphInformer(HMMInformer(self.HMM)) self.SetTitle("HMMEd _VERSION_ - " + self.graphName) if not self.gridding: self.graphMenu.invoke(self.graphMenu.index('Grid')) def SaveGraph(self): if self.fileName != None: self.HMM.SaveAs(self.fileName) else: self.SaveAsGraph() def SaveAsGraph(self): file = asksaveasfilename(title="Save HMM", defaultextension=".xml", filetypes=( ("XML", ".xml"), ("GHMM", ".ghmm"), )) if file is "": print "cancelled" else: print file ext = string.lower(os.path.splitext(file)[1]) if ext == '.xml': self.fileName = file self.HMM.SaveAs(file) self.graphName = stripPath(file) self.SetTitle("HMMEd _VERSION_ - " + self.graphName) else: self.fileName = file self.HMM.SaveAsGHMM(file) self.graphName = stripPath(file) self.SetTitle("HMMEd _VERSION_ - " + self.graphName) def EditWeightUp(self, event): """ Need to have editors multiple sets of transition probability """ if event.widget.find_withtag(CURRENT): widget = event.widget.find_withtag(CURRENT)[0] tags = self.canvas.gettags(widget) if "edges" in tags: (tail, head) = self.edge[widget] transition_probabilities = ProbEditorBasics.ProbDict({}) for head in self.HMM.G.OutNeighbors(tail): weight = self.HMM.G.edgeWeights[0][(tail, head)] label = "-> %d" % head transition_probabilities.update({label: weight}) if transition_probabilities.sum == 0: key_list = transition_probabilities.keys() for key in key_list: transition_probabilities[key] = 1.0 / len(key_list) e = ProbEditorBasics.emission_data(transition_probabilities) d = ProbEditorDialogs.emission_dialog( self, e, "transition probs from state %d" % tail) if d.success(): # write back normalized probabilities for key in transition_probabilities.keys(): head = int(key[3:]) self.HMM.G.edgeWeights[0][( tail, head)] = transition_probabilities[ key] / transition_probabilities.sum else: # We have a vertex v = self.FindVertex(event) if v != None: state = self.HMM.state[v] if state.order > 0: print "Ooops. Cant edit higher order states" return if state.tiedto != '': msg = "The emission parameters of state %s you attempted to edit are tied to those of state %s." % ( state.id, state.tiedto) #print "Note:", msg if not askokcancel( "Edit Tied State", msg + "Edit those of state %s instead?" % state.tiedto): return else: state = self.HMM.state[state.tiedto] if state.emissions == []: state.emissions = [1.0 / self.HMM.hmmAlphabet.size() ] * self.HMM.hmmAlphabet.size() emission_probabilities = ProbEditorBasics.ProbDict({}) for code in self.HMM.hmmAlphabet.name.keys(): label = self.HMM.hmmAlphabet.name[code] weight = state.emissions[code] emission_probabilities.update({label: weight}) # Normalize ... should be member function if abs(emission_probabilities.sum - 1.0) > 0.01: key_list = emission_probabilities.keys() for key in key_list: emission_probabilities[key] = 1.0 / len(key_list) e = ProbEditorBasics.emission_data(emission_probabilities) d = ProbEditorDialogs.emission_dialog( self, e, "emission probs of state %s" % state.id) if d.success(): # write back normalized probabilities for key in emission_probabilities.keys(): code = self.HMM.hmmAlphabet.name2code[key] state.emissions[code] = emission_probabilities[ key] / emission_probabilities.sum def EditHMMObj(self, event): # register values editor.register_attr("itsEditor", None) editor.register_attr("G", None) editor.register_attr("Pi", None) editor.register_attr("id2index", None) editor.register_attr("hmmAlphabet", None) editor.register_attr("hmmClass", None) editor.register_attr("editableAttr", None) editor.register_attr("backgroundDistributions", None) editor.register_attr("state", editor.EntryEditor) # Edit this State with editobj widget editobj.edit(self.HMM) def EditStateUp(self, event): print 'Calling EditObj' if event.widget.find_withtag(CURRENT): widget = event.widget.find_withtag(CURRENT)[0] tags = self.canvas.gettags(widget) if not "edges" in tags: v = self.FindVertex(event) # print "Found Vertex " + "%s" % v # hidden attributes set to None editor.register_attr("state_class", None) editor.register_attr("emissions", None) # hidden editor.register_attr("itsHMM", None) editor.register_attr("desc", None) editor.register_attr("index", None) editor.register_attr("pos", None) editor.register_attr("id", None) editor.register_attr("order", None) editor.register_attr("tiedto", None) editor.register_attr("reading_frame", None) editor.register_attr("duration", None) editor.register_attr("background", None) # register values editor.register_attr("label", ValidStringEditor) # Edit this State with editobj widget editobj.edit(self.HMM.state[v]) def EditPropertiesUp(self, event): if event.widget.find_withtag(CURRENT): widget = event.widget.find_withtag(CURRENT)[0] tags = self.canvas.gettags(widget) if not "edges" in tags: v = self.FindVertex(event) # print "Found Vertex " + "%s" % v #XXX if self.HMM.state[v].state_class != -1: # we have attribute state_class #d = EditObjectAttributesDialog(self, self.HMM.state[v], HMMState.editableAttr + ['state_class']) #else: d = EditObjectAttributesDialog( self, self.HMM.state[v], HMMState.editableAttr + ['state_class']) # We only show the label out of the editable items self.HMM.G.labeling[v] = ValidatingString( "%s" % (self.HMM.state[v].label)) # XXX Hack Aaaargh! self.UpdateVertexLabel(v, 0) # self.HMM.id2index[self.HMM.state[v].id] = v def EditHMM(self): d = EditObjectAttributesDialog(self, self.HMM, self.HMM.editableAttr['HMM']) def EditClassLabel(self): self.HMM.hmmClass.edit(self) def EditAlphabet(self): self.HMM.hmmAlphabet.edit(self) def EditPrior(self): if self.HMM.G.Order() == 0: return key2id = {} emission_probabilities = ProbEditorBasics.ProbDict({}) for state in self.HMM.state.values(): label = state.id weight = state.initial emission_probabilities.update({str(label): weight}) key2id[str(label)] = state.id u = 1.0 / len(emission_probabilities.keys()) if emission_probabilities.sum == 0.0: for key in emission_probabilities.keys(): id = key2id[key] state = self.HMM.state[self.HMM.id2index[id]] state.initial = typed_assign(state.initial, u) emission_probabilities[key] = u if len(emission_probabilities.keys()) > 15: color_list = [ 'red', 'green', 'yellow', 'blue', 'black', 'grey', 'orange', 'pink', 'gold', 'brown', 'tan', 'purple', 'magenta', 'firebrick', 'deeppink', 'lavender', 'NavajoWhite', 'seagreen', 'violet', 'LightGreen' ] colors = color_list repeats = len(emission_probabilities.keys()) / 15 for i in range(repeats - 1): color_list += colors e = ProbEditorBasics.emission_data(emission_probabilities, color_list) else: e = ProbEditorBasics.emission_data(emission_probabilities) d = ProbEditorDialogs.emission_dialog(self, e, "initial probabilities") if d.success(): # write back normalized probabilities for key in emission_probabilities.keys(): id = key2id[key] state = self.HMM.state[self.HMM.id2index[id]] if emission_probabilities.sum == 0.0: state.initial = typed_assign(state.initial, u) else: state.initial = typed_assign( state.initial, emission_probabilities[key] / emission_probabilities.sum) def EditBackgroundDistributions(self): self.HMM.backgroundDistributions.editDistributions(self) def AddVertexCanvas(self, x, y): v = GraphDisplay.AddVertexCanvas(self, x, y) print "AddVertex ", v, "at ", x, y index = self.HMM.AddState(v) # return index to this state state = self.HMM.state[index] self.HMM.G.embedding[state.index] = self.G.embedding[v] def MoveVertex(self, v, x, y, doUpdate=None): GraphDisplay.MoveVertex(self, v, x, y, doUpdate) state = self.HMM.state[v] # transfer the coordinate self.HMM.G.embedding[state.index] = self.G.embedding[v] def AddEdge(self, tail, head): GraphDisplay.AddEdge(self, tail, head) self.HMM.G.edgeWeights[0][(tail, head)] = 1.0 def DeleteVertex(self, v): self.HMM.DeleteState(v) SAGraphEditor.DeleteVertex(self, v) def ShowCoords(self, event): pass
class HMM: def __init__(self, XMLFileName=None, G=None): # self.itsEditor = itsEditor if (G is None): self.G = Graph() else: self.G = G self.G.directed = 1 self.G.euclidian = 0 self.G.simple = 0 self.Pi = {} self.id2index = {} # self.hmmAlphabet = DiscreteHMMAlphabet() self.hmmClass = HMMClass() # in the case of pair HMMs we have several self.hmmAlphabets = {} self.transitionFunctions = {} self.editableAttr = {} self.editableAttr['HMM'] = ['desc'] self.desc = ValidatingString() self.state = {} self.modelType = 0 self.name = "NoName" self.backgroundDistributions = NamedDistributions(self) self.DocumentName = "graphml" if XMLFileName != None: self.OpenXML(XMLFileName) def Clear(self): self.G.Clear() self.Pi = {} self.id2index = {} # self.hmmAlphabet = DiscreteHMMAlphabet() self.hmmAlphabets = {} self.hmmClass = HMMClass() self.backgroundDistributions = NamedDistributions(self) self.editableAttr = {} self.editableAttr['HMM'] = ['desc'] self.desc = ValidatingString() self.state = {} self.DocumentName = "graphml" def AddState(self, index, label='None'): state = HMMState(-1, self) if self.id2index.keys() != []: state.id = max(self.id2index.keys()) + 1 else: state.id = 1 state.index = index self.id2index[state.id] = state.index self.state[state.index] = state # XXX Use canvas id state.label = typed_assign(state.label, state.id) self.G.labeling[state.index] = "%s" % (state.label) return state.index def DeleteState(self, index): """ The method only deletes a map between index and its state object. The caller must delete the corresponding vertex in the owner Graph self.G. """ del self.id2index[self.state[index].id] del self.state[index] def fromDOM(self, XMLNode): # self.hmmClass.fromDOM(XMLNode.getElementsByTagName("hmm:class")[0]) for tag in XMLNode.getElementsByTagName("hmm:class"): self.hmmClass.fromDOM(tag) nameNodes = XMLNode.getElementsByTagName("hmm:name") if (len(nameNodes) > 0): self.modelType = nameNodes[0].firstChild.nodeValue # model type node modelTypeNodes = XMLNode.getElementsByTagName("hmm:modeltype") if (len(modelTypeNodes) > 0): self.modelType = modelTypeNodes[0].firstChild.nodeValue if (self.modelType == "pairHMM"): alphabetNodes = XMLNode.getElementsByTagName("hmm:alphabet") for alphabetNode in alphabetNodes: alphabet = DiscreteHMMAlphabet() alphabet.fromDOM(alphabetNode) self.hmmAlphabets[alphabet.id] = alphabet transitionFunctionNodes = XMLNode.getElementsByTagName( "hmm:transitionfunction") for transitionFunctionNode in transitionFunctionNodes: transitionFunction = TransitionFunction() transitionFunction.fromDom(transitionFunctionNode) self.transitionFunctions[ transitionFunction.id] = transitionFunction else: # If it is no pair hmm One "hmm:alphabet" XML element self.hmmAlphabets[0] = DiscreteHMMAlphabet() self.hmmAlphabets[0].fromDOM( XMLNode.getElementsByTagName("hmm:alphabet")[0]) self.backgroundDistributions.fromDOM(XMLNode) nodes = XMLNode.getElementsByTagName("node") for n in nodes: state = HMMState(-1, self) state.fromDOM(n) self.state[state.index] = state # key must be string self.id2index[state.id] = state.index self.G.embedding[state.index] = state.pos self.G.labeling[state.index] = "%s\n%s" % (state.id, state.label ) # XXX Hack Aaaargh! edges = XMLNode.getElementsByTagName("edge") # nr_classes = int(self.hmmClass.high()-self.hmmClass.low())+1 nr_classes = 1 # search in all states for the maximal kclasses for s in self.state.values(): if (s.kclasses > nr_classes): nr_classes = s.kclasses for i in range(nr_classes): self.G.edgeWeights[i] = EdgeWeight(self.G) for edge in edges: i = self.id2index[int(edge.attributes['source'].nodeValue)] j = self.id2index[int(edge.attributes['target'].nodeValue)] source = self.state[i] datas = edge.getElementsByTagName("data") for data in datas: dataKey = data.attributes['key'].nodeValue # dataValue = data.firstChild.nodeValue if dataKey == 'prob': #p = float(dataValue) # collect all strings from childnodes dataValue = "" for child in data.childNodes: dataValue += child.nodeValue p = listFromCSV(dataValue, types.FloatType) self.G.AddEdge(i, j) if len(p) == 1: # only one class for cl in range(source.kclasses - 1): p.append(0.0) for cl in range(source.kclasses): self.G.edgeWeights[cl][(i, j)] = p[cl] def modelCheck(self): # Compute sums of initial probabilities for renormalization initial_sum = 0.0 for s in self.state: initial_sum = initial_sum + self.state[s].initial if initial_sum == 0.0: raise NotValidHMMType("Initial state is not specified.") if (len(self.hmmAlphabets) == 0): raise AlphabetErrorType( "Alphabet object is empty. You must create alphabet before saving." ) def toDOM(self, XMLDoc, XMLNode): graphml = XMLDoc.createElement("graphml") # define namespaces (proper XML and new expat needs it) graphml.setAttribute('xmlns', 'http://graphml.graphdrawing.org/xmlns') graphml.setAttribute('xmlns:gd', 'gdnamespace') # find the correct URI graphml.setAttribute('xmlns:hmm', 'http://www.ghmm.org/xml/') #arbitrary XMLNode.appendChild(graphml) # Create key elements hmmtype = XMLDoc.createElement("key") hmmtype.setAttribute('id', 'emissions') hmmtype.setAttribute('gd:type', 'HigherDiscreteProbDist') # what's your type? hmmtype.setAttribute('for', 'node') graphml.appendChild(hmmtype) self.hmmClass.toDOM(XMLDoc, graphml) if (self.modelType == "pairHMM"): modelType = XMLDoc.createElement("hmm:modeltype") modelType.appendChild(XMLDoc.createTextNode("pairHMM")) graphml.appendChild(modelType) for alphabet in self.hmmAlphabets.values(): alphabet.toDOM(XMLDoc, graphml) self.backgroundDistributions.toDOM(XMLDoc, graphml) if len(self.transitionFunctions.keys()) != 0: transitionFunctionsNode = XMLDoc.createElement( "hmm:transitionfunctions") for transitionFunction in self.transitionFunctions.values(): transitionFunction.toDom(XMLDoc, transitionFunctionsNode) graphml.appendChild(transitionFunctionsNode) graph = XMLDoc.createElement("graph") # Compute sums of initial probabilities for renormalization initial_sum = 0.0 for s in self.state.keys(): initial_sum = initial_sum + self.state[s].initial for s in self.state.keys(): self.state[s].toDOM(XMLDoc, graph, initial_sum) # Compute sums of outgoing probabilities for renormalization of transition probabilities # NOTE: need dictionaries here out_sum = {} nr_classes = int(self.hmmClass.high()) - int(self.hmmClass.low()) + 1 for v in self.G.vertices: out_sum[v] = [0.0] * nr_classes for cl in range(1): # XXX Assuming one transition class for e in self.G.Edges(): if self.G.edgeWeights[cl].has_key(e): out_sum[e[0]][cl] = out_sum[ e[0]][cl] + self.G.edgeWeights[cl][e] for e in self.G.Edges(): transitions = [] edge_elem = XMLDoc.createElement("edge") edge_elem.setAttribute('source', "%s" % self.state[e[0]].id) edge_elem.setAttribute('target', "%s" % self.state[e[1]].id) # writeData(XMLDoc, edge_elem, 'prob', self.G.edgeWeights[cl][e] / out_sum[e[0]]) # XXX Assuming one transition class for cl in range(nr_classes): for cl in range(1): if self.G.edgeWeights[cl].has_key(e) and out_sum[e[0]][cl]: transitions.append(self.G.edgeWeights[cl][e] / out_sum[e[0]][cl]) else: transitions.append(0.0) writeData(XMLDoc, edge_elem, 'prob', csvFromList(transitions)) graph.appendChild(edge_elem) graphml.appendChild(graph) def AlphabetType(self): """ return the type of emission domain XXX should call the method in HMMAlphabet """ return int def ClassType(self): pass def DistributionType(self): pass def getBackgroundDist(self): """ Return a pair of two dictionaries: (distribution, its orders): a distribution is a list of real values of length N^(order+1). """ return (self.backgroundDistributions.dist, self.backgroundDistributions.order, self.backgroundDistributions.code2name) def buildMatrices(self): """ return [alphabets_code, A, B, pi, state_orders] """ pi = [] B = [] A = [] nstates = len(self.state.keys()) orders = {} k = 0 # C style index for s in self.state.values(): # ordering from XML orders[s.index] = k k = k + 1 state_orders = [] for s in self.state.values(): # a list of indices pi.append(s.initial) state_orders.append(s.order) # state order size = self.hmmAlphabets[s.alphabet_id].size() if (self.modelType != "pairHMM" and size**(s.order + 1) != len(s.emissions)): raise ValueError # exception: inconsistency between ordering and emission B.append(s.emissions) # emission # transition probability v = s.index outprobs = [0.0] * nstates for outid in self.G.OutNeighbors(v)[:]: myorder = orders[outid] outprobs[myorder] = self.G.edgeWeights[0][(v, outid)] A.append(outprobs) alphabets = self.hmmAlphabets[0].name.values() # list of alphabets return [alphabets, A, B, pi, state_orders] def getStateAlphabets(self): alphabets = [] for s in self.state.values(): alphabets.append(self.hmmAlphabets[s.alphabet_id]) return alphabets def getAlphabets(self): return self.hmmAlphabets def getLabels(self): """ returns list of state labels and unique labels """ label_list = [] labels = {} for s in self.state.values(): # a list of indices label_list.append(self.hmmClass.code2name[s.state_class]) labels[label_list[-1]] = 0 return (label_list, labels.keys()) def getTiedStates(self): """ returns list of tied states, entry is None if a state isn't to any other state, returns an empty list, if no state is tied """ tiedstates = [] isTied = 0 orders = {} k = 0 # C style index for s in self.state.values(): # ordering from XML orders[s.id] = k k = k + 1 for s in self.state.values(): # a list of indices if s.tiedto == '': tiedstates.append(-1) else: tiedstates.append(orders[int(s.tiedto)]) isTied = 1 if not isTied: tiedstates = [] return tiedstates def getStateDurations(self): """ returns a list of the minimal number of times a state is evaluated before the HMM changes to another state.""" durations = [] hasduration = 0 for s in self.state.values(): # a list of indices if s.duration == 0: durations.append(1) else: durations.append(s.duration) hasduration = 1 if not hasduration: durations = [] return durations def OpenXML(self, fileName_file_or_dom): if (not isinstance(fileName_file_or_dom, xml.dom.minidom.Document)): dom = xml.dom.minidom.parse(fileName_file_or_dom) else: dom = fileName_file_or_dom if dom.documentElement.tagName == "ghmm": sys.stderr.write("Do not support ghmm format") raise FormatError dom.unlink() #self.DocumentName = "ghmm" #ghmmdom = dom #ghmml = GHMMXML() #dom = ghmml.GraphMLDOM(ghmmdom) #ghmmdom.unlink() else: assert dom.documentElement.tagName == "graphml" self.fromDOM(dom) # dom.unlink() def WriteXML(self, fileName): try: self.modelCheck() # raise exceptions here doc = xml.dom.minidom.Document() self.toDOM(doc, doc) file = open(fileName, 'w') # xml.dom.ext.PrettyPrint(doc, file) file.write(toprettyxml(doc)) # problem with white spaces file.close() doc.unlink() except HMMEdError: print "HMMEdError: No file was written due to errors in the model." def WriteGHMM(self, fileName): self.modelCheck() # raise exceptions here doc = xml.dom.minidom.Document() ghmm = doc.createElement("ghmm") doc.appendChild(ghmm) self.toGHMM(doc, ghmm) file = open(fileName, 'w') # xml.dom.ext.PrettyPrint(doc, file) file.write(toprettyxml(doc)) # problem with white spaces file.close() doc.unlink() def SaveAs(self, fileName): if (self.DocumentName == "graphml"): self.WriteXML(fileName) else: self.WriteGHMM(fileName) def SaveAsGHMM(self, fileName): self.WriteGHMM(fileName)