Note: This article presents advanced topics on tissue simulation. Refer to
vignette("tissue_simulation")
for an introduction on the subject.
Disclaimer: RACES/rRACES internally implements the probability distributions using the C++11 random number distribution classes. The standard does not specify their algorithms, and the class implementations are left free for the compiler. Thus, the simulation output depends on the compiler used to compile RACES, and because of that, the results reported in this article may differ from those obtained by the reader.
Sometimes it is convenient to plot a time series of a simulation, reporting species or firing counts over time. Since rRACES is programmable, it is immediate to make a for-loop algorithm and collect the simulation data over time.
Default History-Based Data
However, this is not required because at the end of any
run_to_*
methods, RACES stores the data about the number of
species cells, and that of event firings. These data can be
extracted.
Let us consider the simulation sim
as produced in
vignette("tissue_simulation")
.
library(rRACES)
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
# The firings
sim$get_firing_history() %>% head()
#> event mutant epistate fired time
#> 1 death A - 44 69.90667
#> 2 growth A - 331 69.90667
#> 3 switch A - 46 69.90667
#> 4 death A + 1097 69.90667
#> 5 growth A + 1650 69.90667
#> 6 switch A + 100 69.90667
# For example, total number of the deaths on `B+` at the end of the
# previous calls of the `run_to_*` methods
sim$get_firing_history() %>%
filter(event == "death", mutant == "B", epistate == "-")
#> event mutant epistate fired time
#> 1 death B - 0 69.90667
#> 2 death B - 0 84.11499
#> 3 death B - 0 99.12279
#> 4 death B - 398 135.91017
#> 5 death B - 706 142.91031
# The counts
sim$get_count_history() %>% head()
#> mutant epistate count time
#> 1 A - 341 69.90667
#> 2 A + 500 69.90667
#> 3 B - 0 69.90667
#> 4 B + 0 69.90667
#> 5 C - 0 69.90667
#> 6 C + 0 69.90667
The time-series can be plot using plot_timeseries()
# Time-series plot
plot_timeseries(sim)
Custom Time-Series
If the default time-series is not enough coarse-grained, one can set
SpatialSimulation$history_delta
to increase the sampling
rate of the state (by default,
SpatialSimulation$history_delta
is set to
).
We show this by re-simulating a tumour with two submutants.
# Example time-series on a new simulation, with coarse-grained time-series
sim <- SpatialSimulation("Finer Time Series")
sim$history_delta <- 1
sim$death_activation_level <- 100
# A
sim$add_mutant(name = "A",
epigenetic_rates = c("+-" = 0.01, "-+" = 0.01),
growth_rates = c("+" = 0.2, "-" = 0.08),
death_rates = c("+" = 0.1, "-" = 0.01))
sim$place_cell("A+", 500, 500)
sim$run_up_to_size("A+", 400)
#> [████████████████████████████████████████] 100% [00m:00s] Saving snapshot
# B (linear inside A)
sim$add_mutant(name = "B",
epigenetic_rates = c("+-" = 0.05, "-+" = 0.05),
growth_rates = c("+" = 0.3, "-" = 0.3),
death_rates = c("+" = 0.05, "-" = 0.1))
sim$mutate_progeny(sim$choose_cell_in("A"), "B")
sim$run_up_to_size("B-", 300)
#> [████████████████████████████████████████] 100% [00m:00s] Saving snapshot
# C (linear inside B)
sim$add_mutant(name = "C",
epigenetic_rates = c("+-" = 0.1, "-+" = 0.1),
growth_rates = c("+" = 0.2, "-" = 0.4),
death_rates = c("+" = 0.1, "-" = 0.01))
sim$mutate_progeny(sim$choose_cell_in("B"), "C")
# D (linear inside A, so branching with C) - same parameters of C
sim$add_mutant(name = "D",
epigenetic_rates = c("+-" = 0.1, "-+" = 0.1),
growth_rates = c("+" = 0.2, "-" = 0.4),
death_rates = c("+" = 0.1, "-" = 0.01))
sim$mutate_progeny(sim$choose_cell_in("A"), "D")
sim$run_up_to_size("D+", 1000)
#> [██████████████████----------------------] 43% [00m:00s] Cells: 33804 [████████████████████████████████████████] 99% [00m:00s] Cells: 60066 [████████████████████████████████████████] 100% [00m:01s] Saving snapshot
The time-series can be plot using plot_timeseries()
.
# Time-series plot
plot_timeseries(sim)
# Logscale helps seeing the different effective growth rates
plot_timeseries(sim) + ggplot2::scale_y_log10()
#> Warning in ggplot2::scale_y_log10(): log-10 transformation introduced infinite values.
#> log-10 transformation introduced infinite values.
Muller Plot
We can also get a Muller plot of the evolution using ggmuller.
# default Muller plot
plot_muller(sim)
In this case every population is annotated as a descendant of the ancestor mutant. Note however that reversible espistates do not fit a traditional Muller plot because they violate the no-back mutation model.
In this case, rRACES will show first the epistate that was randomly injected in the simulation, and the second will result by linear. This is not a completely correct perspective of the simulation time-series; still, it help understand trends.
# Custom Mullers
clock <- sim$get_clock()
plot_muller(sim) + ggplot2::xlim(clock * 3/4, clock)
plot_muller(sim) +
ggplot2::xlim(clock * 3/4, clock) +
ggplot2::scale_y_log10()
Time-Varying Evolutionary Rates
You can model the fact that the rates of one species. For instance, this happens when a population is subject to a targeted treatment.
Considering the example above, where C
and
D
have the same rates, we increase the death rate of both
C+
and C-
species, as well as B+
and B-
.
# Current rates
sim
#>
#> ======= ==== ==== ==== ====== =========
#> species λ δ ε counts %
#> ======= ==== ==== ==== ====== =========
#> A- 0.08 0.01 0.01 8234 13.605645
#> A+ 0.20 0.10 0.01 2216 3.661660
#> B- 0.30 0.10 0.05 7032 11.619491
#> B+ 0.30 0.05 0.05 22140 36.583552
#> C- 0.40 0.01 0.10 11487 18.980816
#> C+ 0.20 0.10 0.10 1705 2.817297
#> D- 0.40 0.01 0.10 6705 11.079165
#> D+ 0.20 0.10 0.10 1000 1.652374
#> ======= ==== ==== ==== ====== =========
#>
#> Species [A-]: 3570 (deaths), 11973 (duplications) and 1340 (switches)
#> Species [A+]: 23175 (deaths), 25223 (duplications) and 1171 (switches)
#> Species [B-]: 20571 (deaths), 22726 (duplications) and 3208 (switches)
#> Species [B+]: 29098 (deaths), 56115 (duplications) and 8086 (switches)
#> Species [C-]: 2068 (deaths), 15720 (duplications) and 3168 (switches)
#> Species [C+]: 3331 (deaths), 2870 (duplications) and 1002 (switches)
#> Species [D-]: 1123 (deaths), 9074 (duplications) and 1793 (switches)
#> Species [D+]: 1903 (deaths), 1656 (duplications) and 547 (switches)
# Raise the death rate levels
sim$update_rates("B+", c(death = 3))
sim$update_rates("B-", c(death = 3))
sim$update_rates("C+", c(death = 3))
sim$update_rates("C-", c(death = 3))
# Now D will become larger
sim$run_up_to_size("D+", 6000)
#> [█████████████████████████---------------] 61% [00m:00s] Cells: 46159 [████████████████████████████████████████] 100% [00m:00s] Saving snapshot
# Current state
sim
#>
#> ======= ==== ==== ==== ====== =========
#> species λ δ ε counts %
#> ======= ==== ==== ==== ====== =========
#> A- 0.08 0.01 0.01 15814 22.213170
#> A+ 0.20 0.10 0.01 2547 3.577649
#> B- 0.30 3.00 0.05 0 0.000000
#> B+ 0.30 3.00 0.05 0 0.000000
#> C- 0.40 3.00 0.10 0 0.000000
#> C+ 0.20 3.00 0.10 0 0.000000
#> D- 0.40 0.01 0.10 46831 65.781268
#> D+ 0.20 0.10 0.10 6000 8.427913
#> ======= ==== ==== ==== ====== =========
#>
#> Species [A-]: 8327 (deaths), 25352 (duplications) and 2850 (switches)
#> Species [A+]: 33287 (deaths), 34624 (duplications) and 1639 (switches)
#> Species [B-]: 28743 (deaths), 23600 (duplications) and 3335 (switches)
#> Species [B+]: 53576 (deaths), 58719 (duplications) and 8479 (switches)
#> Species [C-]: 15242 (deaths), 17754 (duplications) and 3576 (switches)
#> Species [C+]: 5570 (deaths), 3057 (duplications) and 1063 (switches)
#> Species [D-]: 10168 (deaths), 66646 (duplications) and 13398 (switches)
#> Species [D+]: 14912 (deaths), 11264 (duplications) and 3751 (switches)
# This now show the change in rates
clock <- sim$get_clock()
plot_muller(sim) + ggplot2::xlim(clock * 3/4, clock)
plot_muller(sim) +
ggplot2::xlim(clock * 3/4, clock) +
ggplot2::scale_y_log10()