183 lines
5.9 KiB
Python
183 lines
5.9 KiB
Python
from sys import exit
|
|
from colour import *
|
|
|
|
class ReactionSystem(object):
|
|
|
|
def __init__(self):
|
|
|
|
self.reactions = []
|
|
self.background_set = []
|
|
|
|
#self.reactions_by_agents = [] # each element is 'reactions_by_prod'
|
|
self.reactions_by_prod = None
|
|
|
|
## legacy:
|
|
self.init_contexts = []
|
|
self.context_entities = []
|
|
|
|
def assume_not_in_bgset(self, name):
|
|
if self.is_in_background_set(name):
|
|
raise RuntimeError("The entity " + name + " is already on the list")
|
|
|
|
def add_bg_set_entity(self, name):
|
|
self.assume_not_in_bgset(name)
|
|
self.background_set.append(name)
|
|
|
|
def ensure_bg_set_entity(self, name):
|
|
if not self.is_in_background_set(name):
|
|
self.background_set.append(name)
|
|
|
|
def add_bg_set_entities(self, elements):
|
|
for e in elements:
|
|
self.add_bg_set_entity(e)
|
|
|
|
def is_in_background_set(self, entity):
|
|
"""Checks if the given name is valid wrt the background set="""
|
|
if entity in self.background_set:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def get_entity_id(self, name):
|
|
try:
|
|
return self.background_set.index(name)
|
|
except ValueError:
|
|
print("Undefined background set entity: " + repr(name))
|
|
exit(1)
|
|
|
|
def get_state_ids(self, state):
|
|
ids = []
|
|
for entity in state:
|
|
ids.append(self.get_entity_id(entity))
|
|
|
|
return ids
|
|
|
|
def get_entity_name(self, entity_id):
|
|
"""Returns the string corresponding to the entity"""
|
|
return self.background_set[entity_id]
|
|
|
|
def add_reaction(self, R, I, P):
|
|
"""Adds a reaction"""
|
|
|
|
if R == [] or P == []:
|
|
raise RuntimeError("No reactants or products defined")
|
|
|
|
reactants = []
|
|
for entity in R:
|
|
reactants.append(self.get_entity_id(entity))
|
|
|
|
inhibitors = []
|
|
for entity in I:
|
|
inhibitors.append(self.get_entity_id(entity))
|
|
|
|
products = []
|
|
for entity in P:
|
|
products.append(self.get_entity_id(entity))
|
|
|
|
self.reactions.append((reactants, inhibitors, products))
|
|
|
|
def add_initial_context_set(self, context_set):
|
|
if context_set == []:
|
|
print("Empty context set is not allowed")
|
|
raise
|
|
|
|
integers = []
|
|
for entity in context_set:
|
|
if not entity in self.background_set:
|
|
print("The entity", entity, "is not in the background set")
|
|
raise
|
|
else:
|
|
integers.append(self.get_entity_id(entity))
|
|
|
|
self.init_contexts.append(integers)
|
|
|
|
def set_context_entities(self, entities):
|
|
|
|
for entity in entities:
|
|
entity_id = self.get_entity_id(entity)
|
|
self.context_entities.append(entity_id)
|
|
|
|
def entities_names_set_to_str(self, entities):
|
|
s = ""
|
|
for entity in entities:
|
|
s += entity + ", "
|
|
s = s[:-2]
|
|
return s
|
|
|
|
def entities_ids_set_to_str(self, entities):
|
|
s = ""
|
|
for entity in entities:
|
|
s += self.get_entity_name(entity) + ", "
|
|
s = s[:-2]
|
|
return s
|
|
|
|
def state_to_str(self, state):
|
|
return self.entities_ids_set_to_str(state)
|
|
|
|
def show_reactions(self, soft=False):
|
|
print(C_MARK_INFO + " Reactions:")
|
|
if soft and len(self.reactions) > 50:
|
|
print(" -> there are more than 50 reactions (" + str(len(self.reactions)) + ")")
|
|
else:
|
|
print(" "*4 + "{0: ^35}{1: ^25}{2: ^15}".format("reactants"," inhibitors"," products"))
|
|
for reaction in self.reactions:
|
|
# print("\t( R={" + self.state_to_str(reaction[0]) + "}, I={" + self.state_to_str(reaction[1]) + "}, P={" + self.state_to_str(reaction[2]) + "} )")
|
|
print(" " + "- {0: ^35}{1: ^25}{2: ^15}".format("{ " + self.state_to_str(reaction[0]) + " }",
|
|
" { " + self.state_to_str(reaction[1]) + " }",
|
|
" { " + self.state_to_str(reaction[2]) + " }"))
|
|
|
|
def show_background_set(self):
|
|
print(C_MARK_INFO + " Background set: {" + self.entities_names_set_to_str(self.background_set) + "}")
|
|
|
|
def show_initial_contexts(self):
|
|
if len(self.init_contexts) > 0:
|
|
print(C_MARK_INFO + " Initial context sets:")
|
|
for ctx in self.init_contexts:
|
|
print(" - {" + self.entities_ids_set_to_str(ctx) + "}")
|
|
|
|
def show_context_entities(self):
|
|
if len(self.context_entities) > 0:
|
|
print(C_MARK_INFO + " Context entities: " + self.entities_ids_set_to_str(self.context_entities))
|
|
|
|
def show(self, soft=False):
|
|
|
|
self.show_background_set()
|
|
self.show_initial_contexts()
|
|
self.show_reactions(soft)
|
|
self.show_context_entities()
|
|
|
|
def get_reactions_by_product(self):
|
|
"""Sorts reactions by their products and returns a dictionary of products"""
|
|
|
|
if self.reactions_by_prod != None:
|
|
return self.reactions_by_prod
|
|
|
|
producible_entities = set()
|
|
|
|
for reaction in self.reactions:
|
|
producible_entities = producible_entities.union(set(reaction[2]))
|
|
|
|
reactions_by_prod = {}
|
|
|
|
for prod_entity in producible_entities:
|
|
reactions_by_prod[prod_entity] = []
|
|
for reaction in self.reactions:
|
|
if prod_entity in reaction[2]:
|
|
reactions_by_prod[prod_entity].append([reaction[0],reaction[1]])
|
|
|
|
# save in cache
|
|
self.reactions_by_prod = reactions_by_prod
|
|
|
|
return reactions_by_prod
|
|
|
|
def sanity_check(self):
|
|
"""Performs a sanity check on the defined reaction system"""
|
|
|
|
if self.reactions == []:
|
|
print("No reactions defined")
|
|
exit(1)
|
|
|
|
if self.background_set == []:
|
|
print("Empty background set")
|
|
exit(1)
|