Building and Using MaBoSS Models

As of v4.2.5., CC3D supports simulating boolean models using MaBoSS (Markovian Boolean Stochastic Simulator) [1] and attaching them to cells. MaBoSS enables representing intracellular mechanisms like gene regulatory networks and chemical kinetics as Boolean networks, on which MaBoSS simulates continuous or discrete time Markov processes. CC3D provides an interactive version of MaBoSS simulations with select MaBoSS simulation capabilities, so that individual networks can be selectively integrated in time, modified, and reconfigured according to an overall CC3D simulation. With combined capabilities, MaBoSS models in CC3D can be interconnected and coupled with cellular properties, local conditions, and ODE models. For a detailed description of MaBoSS capabilities, examples of MaBoSS simulations and downloading the full, standalone MaBoSS simulation package, visit the MaBoSS homepage.

Note

To cite MaBoSS usage in CC3D, use the following,

Stoll, Gautier, et al. “MaBoSS 2.0: an environment for stochastic Boolean modeling.” Bioinformatics 33.14 (2017): 2226-2228.

Building a MaBoSS Model in CC3D

MaBoSS simulation specification is divided into two components: a network description, and a simulation configuration. A MaBoSS network description describes a network on the basis of nodes, including the name, logic, and transition rates of each node of the network. A MaBoSS simulation configuration describes the network parameters and initial conditions. Typical MaBoSS usage includes creating a network description file with the extension .bnd and a configuration file with the extension .cfg, which are both passed to MaBoSS using a terminal. In CC3D, MaBoSS simulations can be created using any combination of network and configuration files or multiline strings.

A very simple network description of two nodes A and B in a multiline string could look like the following,

"""
node A {
    logic = $B_ext && !B;
    rate_up = @logic ? $node_rate : 0.0;
    rate_down = @logic ? 0.0 : $node_rate;
}
node B {
    logic = A;
    rate_up = @logic ? $node_rate : 0.0;
    rate_down = $node_rate / 10;
}
"""

The network description describes the logic of each node (i.e., logic), and an expression for the rate of each node going from 0 to 1 (i.e., rate_up) and going from 1 to 0 (i.e., rate_down). Rate expressions can be constant (e.g., rate_down for node B), or conditional (e.g., rate_down for node B). For conditional expressions, the syntax X ? Y : Z reads Y if X is true, otherwise Z. The network also uses two external variables $B_ext and $node_rate, the values of which are specified in the configuration file and, along with everything else described in this network except the network itself, can be accessed and modified in CC3D for individual simulation instances of this network.

A corresponding configuration for this network in a multiline string could look like the following,

"""
A.istate = FALSE;
$B_ext = FALSE;
$node_rate = 10.0;
"""

The configuration declares the initial state of node A, and declares values for the external variables $B_ext and $node_rate. Note that, since the configuration does not declare the initial state of node B, each network instance will initialize node B with a randomly selected state.

Note

MaBoSS provides additional specification capabilities for the configuration file (e.g., declaring a random generator seed). The network and configuration specification relevant to MaBoSS simulations in CC3D are described in the previous example. The remaining inputs relevant to specifying a MaBoSS simulation in CC3D are described in subsequent text, and are declared through an interface provided by CC3D.

A MaBoSS simulation can be created and attached to a cell in CC3D using MaBoSS network description and configuration files from within a steppable,

self.add_maboss_to_cell(cell=cell,
                        model_name=model_name,
                        bnd_file=bnd_file,
                        cfg_file=cfg_file,
                        time_step=time_step,
                        time_tick=time_tick)

Here cell is the CC3D cell to which the MaBoSS simulation should be attached, model_name is a string that declares an alias name by which the MaBoSS simulation can be accessed after the call, bnd_file and cfg_file are the absolute path to the location of a network description and configuration file, respectively, time_step is a float equal to the MaBoSS simulation time that corresponds to one simulation step in CC3D, and time_tick is the MaBoSS simulation time that corresponds to considering the transition of every node in the network one time (i.e., the MaBoSS time window).

MaBoSS model and simulation specification declared in Python multiline strings can also be used to create a MaBoSS simulation and attach it to a cell,

self.add_maboss_to_cell(cell=cell,
                        model_name=model_name,
                        bnd_str=bnd_str,
                        cfg_str=cfg_str,
                        time_step=time_step,
                        time_tick=time_tick)

Here bnd_str and cfg_str are network description and configuration multiline strings, respectively (i.e., the contents of a file, but as a multiline string). Any combination of file path and string inputs can be used for passing the network description and configuration, so long as each is passed.

MaBoSS simulations can also be created from within a steppable without being attached to a cell,

mm = self.maboss_model(model_name=model_name,
                       bnd_file=bnd_file,
                       cfg_file=cfg_file,
                       time_step=time_step,
                       time_tick=time_tick)

The same can be accomplished from outside a steppable using a function of the same name and arguments from the cc3d.core.MaBoSSCC3D module,

from cc3d.core import MaBoSSCC3D
mm = MaBoSSCC3D.maboss_model(model_name=model_name,
                             bnd_file=bnd_file,
                             cfg_file=cfg_file,
                             time_step=time_step,
                             time_tick=time_tick)

Both implementations of maboss_model take the same optional arguments as the steppable method add_maboss_to_cell (e.g., the keyword arguments bnd_str and seed).

MaBoSS simulations are automatically destroyed when a cell is destroyed unless the MaBoSS simulation is also stored elsewhere (e.g., as an attribute on a steppable). MaBoSS simulations can also be manually removed from a cell,

self.delete_maboss_from_cell(cell=cell, model_name=model_name)

All provided functions to create MaBoSS simulations in CC3D can also take optional keyword arguments,

  • discrete_time takes a Boolean value (default is False). When passing discrete_time=True, a MaBoSS simulation will perform time integration with fixed time intervals equal to time_tick until an amount of time equal to time_step has elapsed for one integration step. By default, a MaBoSS simulation will integrate using the Gillespie algorithm.

  • seed takes an integer value (default is 0) as the seed for the random generator of the MaBoSS simulation.

  • istate a dictionary of string names and corresponding initial state values.

Note

A time_step value less than a time_tick value is only valid when using the default Gillespie algorithm. Otherwise, the time_step value must be greater than the time_tick value for anything to occur.

Interacting with a MaBoSS Model

All MaBoSS simulations attached to each cell can be accessed using the cell property maboss and referring to the alias of the model as passed to the keyword argument model_name when the simulation was created,

self.add_maboss_to_cell(cell=cell, model_name='MyMaBoSSModel', ...)
...
mm = cell.maboss.MyMaBoSSModel

Every MaBoSS simulation attached to every cell in simulation can be integrated one step in time from a steppable,

self.timestep_maboss()

Likewise, a MaBoSS simulation instance can be individually integrated one step in time,

cell.maboss.MyMaBoSSModel.step()

The values passed to the keyword arguments time_step, time_tick, discrete_time and seed when creating a MaBoSS simulation can all be overwritten at any time by interacting with the MaBoSS simulation instance and its attached CC3DRunConfig object,

mm = cell.maboss.MyMaBoSSModel
mm.step_size *= 2.0  # Double value passed to time_step
mm.run_config.time_tick /= 2.0  # Half value passed to time_tick
mm.run_config.discrete_time = False  # Enable Gillespie algorithm
mm.run_config.seed - mm.run_config.seed + 1  # Increment value passed to seed

Each node of a MaBoSS simulation network can be accessed as if interacting with a Python dictionary. For example, to get node A in a network attached to a cell with alias MyMaBoSSModel,

node_a = cell.maboss.MyMaBoSSModel['A']

Data about a node can be accessed and, where appropriate, set using properties and functions of a node. For example, the state of a node can be accessed and set using the property state such that networks of individual cells and/or multiple networks in the same cell can be coupled,

node_1a = cell1.maboss.MyMaBoSSModel['A']
node_1ao = cell1.maboss.MyOtherMaBoSSModel['A']
node_2b = cell2.maboss.MyMaBoSSModel['B']
node_1a.state = node_2b.state or node_1ao.state

Likewise, the value of external variables can be accessed and set using the MaBoSS Network attached to a MaBoSS simulation. The network of a MaBoSS simulation can be accessed with the property network, and the external variables of a network can be accessed and set using the property symbol_table of the network. For example, an external variable declared in a MaBoSS simulation specification as $cellVolume can be coupled to the current volume of a cell (e.g., to use the cell volume as a MaBoSS model parameter),

cell.maboss.MyMaBoSSModel.network.symbol_table['cellVolume'] = cell.volume

CC3D MaBoSS API

For brevity and generality, the following APIs are presented as relevant to modeling and simulation using CC3D and MaBoSS.

The module cc3d.cpp.MaBoSSCC3DPy contains the following relevant API,

# Network node
class CC3DMaBoSSNode:
    # Description; read-only
    description: str
    # Input node flag; read-only
    is_input: bool
    # Internal node flag
    is_internal: bool
    # Reference node flag
    is_reference: bool
    # Initial state
    istate: bool
    # Current rate down; read-only
    rate_down: float
    # Current rate up; read-only
    rate_up: float
    # Reference state
    ref_state: bool
    # Current state
    state: bool
    # MaBoSS Node "mutate" method
    def mutate(self, value: float) -> None

# External variable value container
class SymbolTable:
    # List of symbol names; read-only
    names: List[str]
    # Gets a symbol value by name
    def __getitem__(self, item: str) -> Union[bool, int, float]
    # Sets a symbol value by name
    def __setitem__(self, item: str, value: Union[bool, int, float]) -> None

# Simulation network
class Network:
    # List of nodes; read-only
    nodes: List[CC3DMaBoSSNode]
    # Symbol table; read-only
    symbol_table: SymbolTable

# Simulation configuration
class CC3DRunConfig:
    # Current random generator seed
    seed: int
    # Simulation time tick
    time_tick: float
    # Discrete time flag
    discrete_time: bool

# The main MaBoSS simulation class in CC3D
class CC3DMaBoSSEngine:
    # Network of the simulation; read-only
    network: Network
    # Configuration of the simulation; read-only
    run_config: CC3DRunConfig
    # Current simulation time; read-only
    time: float
    # Current default step size
    step_size: float
    # Integrates the simulation one step; passing no argument integrates over current value of step_size
    def step(self, _stepSize=-1.0) -> None
    # Gets the network state
    def getNetworkState(self) -> NetworkState
    # Loads an existing network state
    def loadNetworkState(self, _networkState: NetworkState) -> None
    # Get a node by node name
    def __getitem__(self, key: str) -> CC3DMaBoSSNode
    # Set a node state by node name
    def __setitem__(self, key: str, value: bool) -> None

The module cc3d.core.MaBoSSCC3D contains the following relevant API,

# Instantiates and returns a MaBoSS simulation instance from files and/or strings.
def maboss_model(bnd_file: str = None,
                 bnd_str: str = None,
                 cfg_file: str = None,
                 cfg_str: str = None,
                 time_step: float = 1.0,
                 time_tick: float = 1.0,
                 discrete_time: bool = False,
                 seed: int = None,
                 istate: Dict[str, bool] = None) -> MaBoSSCC3DPy.CC3DMaBoSSEngine

The SteppableBasePy class contains the following relevant API,

class SteppableBasePy:
    # Adds a MaBoSS simulation instance to a cell
    @staticmethod
    def add_maboss_to_cell(cell: CellG,
                           model_name: str,
                           bnd_file: str = None,
                           bnd_str: str = None,
                           cfg_file: str = None,
                           cfg_str: str = None,
                           time_step: float = 1.0,
                           time_tick: float = 1.0,
                           discrete_time: bool = False,
                           seed: int = 0,
                           istate: Dict[str, bool] = None) -> None
    # Removes a MaBoSS simulation instance from a cell
    @staticmethod
    def delete_maboss_from_cell(cell: CellG, model_name: str) -> None
    # Instantiates and returns a MaBoSS simulation instance from files and/or strings.
    @staticmethod
    def maboss_model(bnd_file: str = None,
                     bnd_str: str = None,
                     cfg_file: str = None,
                     cfg_str: str = None,
                     time_step: float = 1.0,
                     time_tick: float = 1.0,
                     discrete_time: bool = False,
                     seed: int = 0,
                     istate: Dict[str, bool] = None) -> MaBoSSCC3DPy.CC3DMaBoSSEngine
    # Steps all existing MaBoSS simulations
    def timestep_maboss(self) -> None:
    # Returns a dictionary with summary statistics of a node of a model
    def maboss_stats(self, model_name: str, node_name: str) -> dict: