This repo implements direct and first reaction methods of Gillespie stochastic simulation algorithm for solving the Master equation. The code is based on PyTorch and can be used on CPU and GPU alike. The repo was developed and tested on Ubuntu 20.04 and Ubuntu 22.04 WSL2.
git clone git@github.com:aivarsoo/ssa-solvers.git
cd ssa-solvers
NAME=ssa_solvers
conda create --name $NAME -y python==3.10
conda activate $NAME
pip install -e .Build the docker image
docker build . --tag ssa_solvers
Make sure the docker container can write in the directory ./logs by running
chmod 775 -R logs
Connect to the container running bash while mounting the ./logs directory
docker run -it --rm --net=host --gpus all -v ./logs:/home/docker_user/project/logs --group-add $(id -g) --user docker_user ssa_solvers bash
This command uses the Nvidia docker wrapper for GPU access, see Nvidia docker installation notes for details.
To run notebooks
docker run -it --rm --net=host --gpus all -v ./logs:/home/docker_user/project/logs --group-add $(id -g) --user docker_user ssa_solvers jupyter lab
The base reaction system is encoded in BaseChemicalReactionSystem class in ssa_solvers.chemical_reaction_system.
To perform simulations one needs to create a subclass of BaseChemicalReactionSystem with the following fields overloaded:
self.stoichiometry_matrix - Stoichiometric matrix of the chemical reaction system
self._params - Dictionary of parameters of the chemical reaction system with a string key for parameter name and a float value for parameter value
self._species - Dictionary of species of the chemical reaction system with a string key for species name and an integer value for species index in the species vector
The following method calculates the propensity vector based on the current population, e.g.:
def propensities(self, pops: torch.Tensor) -> torch.Tensor:
propensities = [
...,
...,
]
return torch.vstack(propensities)cfg = {
'name': 'mRNAsRNAInTrans',
'stochastic_sim_cfg': {'checkpoint_freq': 1,
'save_to_file': True,
'trajectories_per_batch': 50000,
'path': './logs/',
'solver': 'direct',
'precision': 'fp32'},
'ode_sim_cfg': {'solver': 'RK23',
'atol': 1e-4,
'rtol': 1e-10}
}cfg['name'] - Reaction system name
cfg['stochastic_sim_cfg'] - parameters for stochastic simulation:
checkpoint_freq- frequency of checkpointssave_to_file- ifTruethe results are saved to a CSV file, otherwise kept in memorytrajectories_per_batch- number of trajectories to simulate at once. Set tosys.maxsizeifsave_to_file = False, i.e.,trajecories_per_batch = n_trajectoriessolver- type of a solver:directorfirst_reaction(default:fp16)path- path to save the logs and dataprecision- float precision for computing statistics:fp64- double,fp32- single andfp16half precision (default:fp16)
cfg['ode_sim_cfg'] - parameters for ODE simulation using solve_ivp method from xitorch package, see xitorch documentation for details
Define the classes
device = torch.device("cpu")
reaction_system = MyReactionSystem(device=device)
ssa_simulator = StochasticSimulator(
reaction_system=reaction_system,
cfg=cfg,
device=device
)Simulate
init_pops = torch.zeros(
(reaction_system_intrans.n_species, ), dtype=torch.int64, device=device)
end_time = 100
ssa_simulator.simulate(
init_pops=init_pops,
end_time=end_time,
n_trajectories = 100)Compute mean and variance on the specified grid
n_steps = 100
time_grid = torch.arange(0, end_time, int(
end_time / n_steps), device=device)
means, stds = ssa_simulator.data_set.mean_and_std(time_grid=time_grid)python run_example --circuit CIRCUIT --end_time END_TIME --n_steps N_STEPS --n_traj N_TRAJ --device DEVICECIRCUIT - Circuit name (currently implemented mrna, auto)
END_TIME - Simulation end time (positive float)
N_STEPS - Number of steps in the time grid (positive int)
N_TRAJ - Number of trajectories in the stochastic simulation (positive int)
DEVICE - Device for simulations (options: cpu, cuda)
notebooks/autorepressor.ipynb
notebooks/mrna_srna.ipynb
notebooks/speed_comparisons.ipynb