Source code for maboss.simulation

"""Class that handles the parameters of a MaBoSS simulation.
"""


from sys import stderr, stdout
from contextlib import ExitStack

from colomoto import ModelState

from .result import Result
import os
import uuid

_default_parameter_list = {'time_tick': 0.1,
                  'max_time': 4,
                  'sample_count': 10000,
                  'discrete_time': 0,
                  'use_physrandgen': 1,
                  'seed_pseudorandom': 0,
                  'display_traj': 0,
                  'statdist_traj_count': 0,
                  'statdist_cluster_threshold': 1,
                  'thread_count': 1,
                  'statdist_similarity_cache_max_size': 20000
                  }


[docs]class Simulation(object): """ Class that handles MaBoSS simulations. .. py:attribute:: network A Network object, that will be translated in a bnd file .. py:attribute:: mutations A list of nodes for which mutation can be triggered by modifying the cfg file .. py:attribute:: palette A mapping of nodes to color for plotting the results of the simulation. .. py:attribute:: param A dictionary that contains global variables (keys starting with a '$'), and simulation parameters (keys not starting with a '$'). """
[docs] def __init__(self, nt, **kwargs): """ Initialize the Simulation object. :param nt: the network associated with the simulation. :type nt: :py:class:`Network` :param dict kwargs: parameters of the simulation """ self.param = _default_parameter_list.copy() if 'palette' in kwargs: self.palette = kwargs.pop('palette') else: self.palette = {} for p in kwargs: if p in _default_parameter_list or p[0] == '$': self.param[p] = kwargs[p] else: print("Warning: unused parameter %s" % p, file=stderr) self.network = nt self.mutations = [] self.refstate = {}
[docs] def update_parameters(self, **kwargs): """Add elements to ``self.param``.""" for p in kwargs: if p in _default_parameter_list or p[0] == '$': self.param[p] = kwargs[p] else: print("Warning: unused parameter %s" % p, file=stderr)
def copy(self): new_network = self.network.copy() result = Simulation(new_network, **(self.param), palette=self.palette) if self.mutations: result.mutations = self.mutations.copy() return result
[docs] def print_bnd(self, out=stdout): """Produce the content of the bnd file associated to the simulation.""" print(self.network, file=out)
[docs] def print_cfg(self, out=stdout): """Produce the content of the cfg file associated to the simulation.""" print("$nb_mutable = " + str(len(self.mutations)) + ";", file=out) for p in self.param: if p[0] == '$': print(p + ' = ' + str(self.param[p]) + ';', file=out) self.network.print_istate(out=out) print('', file=out) for p in self.param: if p[0] != '$': print(p + ' = ' + str(self.param[p]) + ';', file=out) for name in self.network.names: string = name+'.is_internal = ' + str(int(self.network[name].is_internal)) + ';' print(string, file=out) for nd in self.refstate: string = nd +'.refstate = ' + self.refstate[nd] + ';' print(string, file=out)
[docs] def run(self): """Run the simulation with MaBoSS and return a Result object. :rtype: :py:class:`Result` """ return Result(self)
[docs] def mutate(self, node, state): """ Trigger or untrigger mutation for a node. :param node: The :py:class:`Node` to be modified :type node: :py:class:`Node` :param str State: * ``'ON'`` (always up) * ``'OFF'`` (always down) * ``'WT'`` (mutable but with normal behaviour) The node will appear as a mutable node in the bnd file. This means that its rate will be of the form: ``rate_up = $LowNode ? 0 :($HighNode ? 1: (@logic ? rt_up : 0))`` If the node is already mutable, this method will simply set $HighNode and $LowNode accordingly to the desired mutation. """ if node not in self.network: print("Error, unknown node %s" % node, file=stderr) return nd = self.network[node] if not nd.is_mutant: self.network[node]=_make_mutant_node(nd) self.mutations.append(nd.name) lowvar = "$Low_"+node highvar = "$High_"+node if state == "ON": self.param[lowvar] = 0 self.param[highvar] = 1 elif state == "OFF": self.param[lowvar] = 1 self.param[highvar] = 0 elif state == "WT": self.param[lowvar] = 0 self.param[highvar] = 0 else: print("Error, state must be ON, OFF or WT", file=stderr) return
[docs] def continue_from_result(self, result): """Set the initial state from as the last state from result.""" node_prob = result.get_nodes_probtraj() nodes = node_prob.iloc[-1] for i in nodes.index: if i != "<nil>": prob = nodes[i] self.network.set_istate(i, [1 - prob, prob])
[docs] def get_initial_state(self): """ TODO """ istate = ModelState() for nd in self.network.keys(): states = set() for state in [0, 1]: if self.network._initState[nd][state]: states.add(state) istate[nd] = states.pop() if len(states) == 1 else states return istate
def _make_mutant_node(nd): """Create a new logic for mutation that can be activated from .cfg file.""" curent_rt_up = nd.rt_up curent_rt_down = nd.rt_down lowvar = "$Low_"+nd.name highvar = "$High_"+nd.name rt_up = (lowvar+" ? 0 : (" + highvar + " ? 1E308/$nb_mutable : (" + curent_rt_up + "))") rt_down = (highvar + " ? 0 : (" + lowvar + " ? 1E308/$nb_mutable : (" + curent_rt_down + "))") # Once this is done, the mutation can be activated by modifying the value # of $Low_nodename and $High_nodename in the .cfg file newNode = nd.copy() newNode.rt_up = rt_up newNode.rt_down = rt_down newNode.is_mutant = True return newNode def set_nodes_istate(masim, nodes, istate): for n in nodes: masim.network.set_istate(n, istate) def set_output(masim, output): masim.network.set_output(output) def copy_and_mutate(masim, nodes, mut): masim2 = masim.copy() for node in nodes: masim2.mutate(node, mut) return masim2 def copy_and_update_parameters(sim, parameters): new_sim = sim.copy() new_sim.update_parameters( **parameters ) return new_sim