Source code for maboss_test.MaBoSSTestCase

import unittest
import maboss
import math

[docs]class MaBoSSTestCase(unittest.TestCase): """ MaBoSSTestCase is the class used to verify model validity. It contains several methods to test various conditions """ def __init__(self, sim, verbose = True): """ Is the constructor of the class. :param sim: The simulation to link to the instance, it is a maboss simulation object. :param bool verbose: Variable to decide the format of the output. Through the generated instace it is possible to perform several tests on the model passed as maboss simulation. If verbose is set as 'True' the output will contain different information, otherwise it will be in the 'unit testing format'. """ unittest.TestCase.__init__(self) self.Simulation = sim.copy() self.Old_sim = (self.Simulation).copy() self.Old_result = None self.New_sim = (self.Simulation).copy() self.New_result = None self.VERBOSE = verbose #call at the end of the tests def resetSimulations(self): self.Old_sim = (self.Simulation).copy() self.Old_result = None self.New_sim = (self.Simulation).copy() self.New_result = None def checkNodes(self, state): for node in state: if node not in self.Simulation.network.keys(): print(node, 'is not present in the network.') return False return True #set output for save time when you run a simulation def setOutput(self, output): self.Old_sim.network.set_output(output) self.New_sim.network.set_output(output) def setInitialConditions(self, initial_conditions): if not initial_conditions and self.VERBOSE: print('Warning, you did not change any initial condition!') return if type(initial_conditions) is dict: for node in initial_conditions: self.Old_sim.network.set_istate(node, initial_conditions[node]) self.New_sim.network.set_istate(node, initial_conditions[node]) #input: list: list[0]=list of node, list[1] dictionary of prob elif type(initial_conditions) is list: self.Old_sim.network.set_istate(initial_conditions[0], initial_conditions[1]) self.New_sim.network.set_istate(initial_conditions[0], initial_conditions[1]) else: print('Invalid initial condition!') return #mutate New_simulation if a list of mutations is given def mutateSimulation(self, mutations={}): if mutations: for n in mutations: (self.New_sim).mutate(n,mutations[n]) elif self.VERBOSE: print('Warning, you did not insert mutations!') def runBothSimulations(self): self.Old_result = self.Old_sim.run() self.New_result = self.New_sim.run() #return the states of a sim with their probability def getProbtrajStates(self, sim_name): if sim_name == 'New': result = (self.New_result).get_last_states_probtraj() elif sim_name == 'Old': result = (self.Old_result).get_last_states_probtraj() states = result.columns probability_states = {} # dict----> key:probability value:state in list form for state in states: prob = result[state].values[0] probability_states[prob] = state.split(' -- ') return probability_states #return the stable states of a sim with their probability def getStableStates(self, sim_name): if sim_name == 'New': s_states_table = self.New_result.get_fptable() elif sim_name == 'Old': s_states_table = self.Old_result.get_fptable() if s_states_table is None: return None s_states = s_states_table['State'] s_states = [state.split(' -- ') for state in s_states] s_states_prob = s_states_table['Proba'] probability_states = dict(zip(s_states_prob,s_states)) return probability_states #return a dictionary with the states satisfing the condition with probability as key def checkForState(self, kind, condition={}, all_states={}): #check that the list of stable states of the model is not empty if all_states == None: return None #check if I'm looking for <nil> state only for last prob traj :CHECK CASE IN WICH ALL STATES ARE 0 if ( kind == 'last' and all(i == 0 for i in condition.values()) ): active_nodes = ['<nil>'] inactive_nodes = [] else: active_nodes = [x for x in condition if condition[x]==1] inactive_nodes = [x for x in condition if condition[x]==0] resulting_states = all_states.copy() #states that s for node in active_nodes: resulting_states = {x: resulting_states[x] for x in resulting_states if node in resulting_states[x]} for node in inactive_nodes: resulting_states = {x: resulting_states[x] for x in resulting_states if node not in resulting_states[x]} if resulting_states: return resulting_states #if there is not match the probability is 0 else: return None #{0: condition} def truncate(self, number, digits) -> float: stepper = 10.0 ** digits return math.trunc(stepper * number) / stepper def printStates(self, states): if states == None: print('None') else: for prob in states: print('\nProbability = ', prob, '\nState: ', str(states[prob])) return def compare(self, Old_p, New_p, direction, message, digits): Old_p = self.truncate(Old_p, digits) New_p = self.truncate(New_p, digits) #INCREASE? if direction == self.INCREASE: if self.VERBOSE: try: self.assertTrue(New_p > Old_p) print("True! ", message) except Exception as e: print("False! ", message) elif not self.VERBOSE: self.assertTrue(New_p > Old_p) print('...OK') #DECREASE? elif direction == self.DECREASE: if self.VERBOSE: try: self.assertTrue(New_p < Old_p) print("True! ", message) except Exception as e: print("False! ", message) elif not self.VERBOSE: self.assertTrue(New_p < Old_p) print('...OK') #STAY THE SAME? elif direction == self.CHANGE: if self.VERBOSE: try: self.assertAlmostEqual(Old_p, New_p) print("True! ", message) except Exception as e: print("False! ", message) elif not self.VERBOSE: self.assertAlmostEqual(Old_p, New_p) print('...OK') return ################################################################################################################## ############################################ ASSERTION FUNCTIONS ################################################# ##################################################################################################################
[docs] def assertStateProbabilityEvolution(self, mutations, I_C, state, direction, digits = 4): """ Assert the evolution of the probability of a given state after applying a mutation. :param dict mutations: The mutations to apply to the model :param I_C: Initial conditions with which to simulate the model, it may be a list or a dictionary :param dict state: The state to evaluate :param string direction: The direction of the evolution of the given state, it may be: 'increase', 'decrease' or 'stable' :param int digits: The number of digits you want to keep during the comparison This function will simulate the wild type model and the model with the given mutations, both with the initial conditions I_C. It will then compare simulation results and check if the given state is evolving in the indicated direction. If not correct, this test will fail by raising an exception. """ if not self.checkNodes(state): return output = list(state.keys()) self.setOutput(output) #set the output for Old/New_sim self.setInitialConditions(I_C) #set initial conditions self.mutateSimulation(mutations) #mutate New_sim self.runBothSimulations() all_Old_states = self.getProbtrajStates('Old') #dict: key:stateProb value:state (list form) all_New_states = self.getProbtrajStates('New') Old_states = self.checkForState('last', state, all_Old_states) #there should be prob_state:state_list_form New_states = self.checkForState('last', state, all_New_states) #if prob is not 0 if Old_states == None: Old_state_prob = 0 else: Old_state_prob = list(Old_states.keys())[0] #if possible invert keys and value if New_states == None: New_state_prob = 0 else: New_state_prob = list(New_states.keys())[0] #check it is all fine if (Old_states != None and New_states != None and len(Old_states)!=1 and len(Old_states)!=1): print('ERROR, TO MUTCH STATES') return message = '\nThe new probability of reaching the state is: {}' ' \nThe old one is: {}'.format(New_state_prob, Old_state_prob) self.compare(Old_state_prob, New_state_prob, direction, message, digits) #ad an output!!!!! self.resetSimulations() return
[docs] def assertStableStateProbabilityEvolution(self, mutations, I_C, state, direction, digits = 4): """ Assert the evolution of the probability of a given stable state after applying a mutation. :param dict mutations: The mutations to apply to the model :param I_C: Initial conditions with which to simulate the model, it may be a list or a dictionary :param dict state: The state to evaluate :param string direction: The direction of the evolution of the given state, it may be: 'increase', 'decrease' or 'stable' :param int digits: The number of digits you want to keep during the comparison This function will simulate the wild type model and the model with the given mutations, both with the initial conditions I_C. It will then compare simulation results and check if the given stable state is evolving in the indicated direction. If not correct, this test will fail by raising an exception. """ if not self.checkNodes(state): return #if the nodes in states are not in the nodes list arrest self.setInitialConditions(I_C) #set initial conditions self.mutateSimulation(mutations) #mutate New_sim self.runBothSimulations() all_Old_stable_states = self.getStableStates('Old') all_New_stable_states = self.getStableStates('New') Old_states = self.checkForState('stable', state, all_Old_stable_states) New_states = self.checkForState('stable', state, all_New_stable_states) Old_state_prob = 0 if Old_states != None: for prob in Old_states.keys(): Old_state_prob += prob New_state_prob = 0 if New_states != None: for prob in New_states.keys(): New_state_prob += prob message = '\nThe new probability of reaching the stable state is: {}' ' \nThe old one is: {}'.format(New_state_prob, Old_state_prob) self.compare(Old_state_prob, New_state_prob, direction, message, digits) self.resetSimulations() return
#NAME????? #maBoss only find ss with prob >0? #assert if given some condition (nodes dictionaries) other nodes has always the same values
[docs] def assertNodesDependencies(self, mutations, condition, nodes_expected): """ Assert that all states satisfying a condition on some given nodes also present the expected value for some other nodes. :param dict mutations: The mutations to apply to the model :param dict condition: A list of nodes with a specifc value assigned (0:inactive or 1:active) that a state has to respect in order to be selected :param dict nodes_expected: A list of nodes with a specifc value assigned (0:inactive or 1:active) that all the selected states have to respect This function will simulate the model with the given mutations. It will then extract the stable states of the model in which the activity of the nodes in condition is satisfied. It will then check that, for each selected state, the values of the nodes in nodes_expected is satisfied. If not correct, this test will fail by raising an exception. """ if not self.checkNodes(condition): return if not self.checkNodes(nodes_expected): return #for stable states don't need outputs self.mutateSimulation(mutations) #mutate New_sim self.New_result = self.New_sim.run() all_stable_states = self.getStableStates('New') #states satisfying the input condition states_satisfying_condition = self.checkForState('stable', condition, all_stable_states) #selected states satisfying both condition and nodes_expected if states_satisfying_condition != None: if not nodes_expected: selected_states = None else: selected_states = self.checkForState('stable', nodes_expected, states_satisfying_condition) else: print("Not even one stable state satisfy: ", condition) return if self.VERBOSE: try: self.assertEqual(states_satisfying_condition, selected_states) print("True! \nAll the states that satisfy: ", condition, " have: ", nodes_expected) except Exception as e: print('False! \nThe states with ', condition, ' are : ') self.printStates(states_satisfying_condition) print('\nOf these, those with ', nodes_expected, ' are: ') self.printStates(selected_states) elif not self.VERBOSE: self.assertEqual(states_satisfying_condition, selected_states) print('...OK') self.resetSimulations() return
[docs] def assertStableStateProbability(self, mutations, state, direction, reference_prob = 0, digits = 4): """ Assert the evolution of the probability of a given stable state after applying a mutation. :param dict mutations: The mutations to apply to the model :param dict state: The state to evaluate :param string direction: The direction of the evolution of the given state, it may be: 'increase', 'decrease' or 'stable' :param float reference_prob: The probability that will be compared with the probability to obtain "state" :param int digits: The number of digits you want to keep during the comparison This function will simulate the model with the given mutations. It will then compare simulation results with reference_prob, and check if the given stable state is evolving in the indicated direction. If not correct, this test will fail by raising an exception. """ if not self.checkNodes(state): return self.mutateSimulation(mutations) #mutate New_sim self.New_result = self.New_sim.run() all_New_stable_states = self.getStableStates('New') New_states = self.checkForState('stable', state, all_New_stable_states) New_state_prob = 0 if New_states != None: for prob in New_states.keys(): New_state_prob += prob message = '\nThe probability of reaching the state is: {}'.format(New_state_prob) print('The reference probability is: ', reference_prob) self.compare(reference_prob, New_state_prob, direction, message, digits) self.resetSimulations() return
#take last nodes probability for every node
[docs] def getLastNodesProbabilities(self, mutations, I_C): """ Return a dictionary with the final activation probabily of every node in the model. :param dict mutations: The mutations to apply to the model :param dict I_C: Initial conditions with which to simulate the model, it may be a list or a dictionary This function will simulate the model with the given mutations and initial conditions. It will then return the activation probability of each node in a form that can be used as initial condition for the assert functions. """ output = list(self.New_sim.network.keys()) self.setOutput(output) self.setInitialConditions(I_C) self.mutateSimulation(mutations) self.New_result = self.New_sim.run() prob_table = self.New_result.get_last_nodes_probtraj() probability = {} for node in prob_table.columns: p = prob_table[node].values[0] p = self.truncate(p,10) probability[node]=[1-p,p] for node in self.New_sim.network.keys(): if node not in probability.keys(): probability[node]=[1,0] self.resetSimulations() return probability
INCREASE = 'increase' DECREASE = 'decrease' CHANGE = 'stable' #actually it is: does not change