def addTypeOneError(self, mole1, mole2, reaction): """ Add Type I Error components to self.type_one_errors All components of resulting PathComponents are str :param Molecule mole1: :param Molecule mole2: :param Reaction reaction: :return bool flag: """ flag = False for component in self.type_one_errors: if (component.node1 == mole1.name) and (component.node2 == mole2.name): new_component = cn.PathComponents( node1=mole1.name, node2=mole2.name, reactions=component.reactions + [reaction.label]) self.type_one_errors.remove(component) self.type_one_errors.append(new_component) flag = True break if not flag: self.type_one_errors.append( cn.PathComponents(node1=mole1.name, node2=mole2.name, reactions=[reaction.label])) flag = True return flag
def addTypeThreeError(self, som1, som2, reaction): """ Add Type III Error components to self.type_three_errors All components of resulting PathComponents are str :param SOM som1: :param SOM som2: :param Reaction reaction: :return bool flag: """ flag = False for component in self.type_three_errors: if (component.node1 == som1) and (component.node2 == som2): new_component = cn.PathComponents( node1=som1, node2=som2, reactions=component.reactions + [reaction.label]) self.type_three_errors.remove(component) self.type_three_errors.append(new_component) flag = True break if not flag: self.type_three_errors.append( cn.PathComponents(node1=som1, node2=som2, reactions=[reaction.label])) flag = True return flag
def testReportTypeOneError(self): if IGNORE_TEST: return m = GAMES_PP(self.simple2) m.analyze(error_details=False) gr = GAMESReport(m) error = [ cn.PathComponents(node1=G2K, node2=G2R, reactions=[G2R_CREATION]) ] report, error_num = gr.reportTypeOneError(error, explain_details=True) self.assertEqual(error_num, [2]) extended_report = NULL_STR extended_report = extended_report + "\nG2K = G2R by reaction(s):\n1. Rum1DegInG2R: G2R -> G2K\n\n" extended_report = extended_report + "However, G2K < G2R by reaction(s):\n2. G2R_Creation: G2K + R -> G2R\n\n" extended_report = extended_report + "\n----------------------------------------------------------------------\n\n" extended_report = extended_report + "\n\n**********************************************************************\n\n" self.assertEqual(report, extended_report)
def getMoleculeEqualityPath(self, som, molecule1, molecule2): """ Create an undirected graph between two molecules within a SOM and find the shortest path :param SOM som: :param Molecule mole1: :param Molecule mole2: :return PathComponents: som_path """ # molecule1 = mole1.name # molecule2 = mole2.name # construct undirected graph subg = nx.Graph() # here, every reaction is 1-1 reaction for reaction in list(som.reactions): node1 = reaction.reactants[0].molecule.name node2 = reaction.products[0].molecule.name if subg.has_edge(node1, node2): reaction_label = subg.get_edge_data(node1, node2)[cn.REACTION] # if reaction.label is not included in the attribute, add its label if reaction.label not in set(reaction_label): reaction_label = reaction_label + [reaction.label] else: reaction_label = [reaction.label] subg.add_edge(node1, node2, reaction=reaction_label) path = [short_p for short_p in nx.shortest_path(subg, source=molecule1, target=molecule2 ) ] som_path = [] for idx in range(len(path)-1): edge_reactions = subg.get_edge_data(path[idx], path[idx+1])[cn.REACTION] som_path.append(cn.PathComponents(node1=path[idx], node2=path[idx+1], reactions=edge_reactions ) ) return som_path
def addTypeTwoError(self, cycle): """ Add Type II Error components to self.type_two_errors which is a list of lists All components of resulting PathComponents are str :param list-SOM cycle: """ # exceptionally, here PathComponents are # node1=[], node2=[], reactions=[] and their index # of each component will match. All elements within nodes # are in the same SOM error_cycle = [] for node_idx in range(len(cycle) - 1): som1 = cycle[node_idx] som2 = cycle[node_idx + 1] som1_moles = {mole.name for mole in list(som1.molecules)} som2_moles = {mole.name for mole in list(som2.molecules)} reactions = self.get_edge_data(som1, som2)[cn.REACTION] # all reactions (in an edge), should create a single PathComponent nodes1 = [] nodes2 = [] reaction_labels = [] for r in reactions: reaction = self.simple.getReaction(r) if reaction.category == cn.REACTION_n_1: sources = {r.molecule.name for r in reaction.reactants} destinations = {p.molecule.name for p in reaction.products} elif reaction.category == cn.REACTION_1_n: sources = {p.molecule.name for p in reaction.products} destinations = { r.molecule.name for r in reaction.reactants } # for any reaction that addes arcs, len(nodes2)==1 node2 = list(destinations.intersection(som2_moles))[0] for node1 in list(sources.intersection(som1_moles)): nodes1.append(node1) nodes2.append(node2) reaction_labels.append(reaction.label) error_cycle.append( cn.PathComponents(node1=nodes1, node2=nodes2, reactions=reaction_labels)) som1 = cycle[-1] som2 = cycle[0] som1_moles = {mole.name for mole in list(som1.molecules)} som2_moles = {mole.name for mole in list(som2.molecules)} reactions = self.get_edge_data(som1, som2)[cn.REACTION] # all reactions (in an edge), should create a single PathComponent nodes1 = [] nodes2 = [] reaction_labels = [] for r in reactions: reaction = self.simple.getReaction(r) if reaction.category == cn.REACTION_n_1: sources = {r.molecule.name for r in reaction.reactants} destinations = {p.molecule.name for p in reaction.products} elif reaction.category == cn.REACTION_1_n: sources = {p.molecule.name for p in reaction.products} destinations = {r.molecule.name for r in reaction.reactants} # for any reaction that addes arcs, len(nodes2)==1 node2 = list(destinations.intersection(som2_moles))[0] for node1 in list(sources.intersection(som1_moles)): nodes1.append(node1) nodes2.append(node2) reaction_labels.append(reaction.label) error_cycle.append( cn.PathComponents(node1=nodes1, node2=nodes2, reactions=reaction_labels)) self.type_two_errors.append(error_cycle)