Skip to contents

Disclaimer: ProCESS/CLONES 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 CLONES, and because of that, the results reported in this article may differ from those obtained by the reader.

ProCESS/CLONES simulate the tumour growth according to two alternative models: the “border” growth model and the homogeneous-growth model.

The former exclusively admits duplication of cells that have space to duplicate (i.e., cells on the cancer border or near to dead cells). The latter allows cell duplications everywhere in the tumour.

The “border” growth model is the default one. However, users can switch to the homogeneous growth model by assigning the TissueSimulation’s border_growth_model Boolean field. By setting it to FALSE, the homogeneous-growth model is used. If, instead, it is set to TRUE, the simulation evolves according to the “border” growth model.

In the rest of this article, we clarify the differences among the supported growth models by showing that they produce distinct evolutions of the same cancer model.

Homogeneous Growth

First of all, we need to create a new TissueSimulation object and set border_growth_model to FALSE.

library(ProCESS)

set.seed(0)

sim <- TissueSimulation("Homogeneous Growth")

# Set the homogeneous growth model
sim$border_growth_model <- FALSE

# Set the death activation level to avoid drift
sim$death_activation_level <- 50

Add a mutant A with an epigenetic state, let the simulation evolve until there are 1300 cells of species A+, take two samples, and let the simulation evolve again for 15 time units.

# Add a mutant
sim$add_mutant(name = "A",
               epigenetic_rates = c("+-" = 0.01, "-+" = 0.01),
               growth_rates = c("+" = 0.1, "-" = 0.08),
               death_rates = c("+" = 0.1, "-" = 0.01))

sim$place_cell("A+", 500, 500)

# Let the simulation evolve until "A+" consists of 1300 cells
sim$run_up_to_size("A+", 1300)
#>  [████████████████████████████████████████] 100% [00m:00s] Saving snapshot

bbox_width <- 15

# Takes two samples
sim$sample_cells("S_1_1",
                 bottom_left = c(480, 480),
                 top_right = c(480 + bbox_width, 480 + bbox_width))

sim$sample_cells("S_1_2",
                 bottom_left = c(500, 500),
                 top_right = c(500 + bbox_width, 500 + bbox_width))

# Let the simulation evolve again for 15 time units
sim$run_up_to_time(sim$get_clock() + 15)
#>  [████████████████████████████████████████] 100% [00m:00s] Saving snapshot

Add a new mutant B, let one of the cells in A generate a cell in B, let the simulation evolve until there are 5000 cells in B+, and take two more samples.

sim$add_mutant(name = "B",
               epigenetic_rates = c("+-" = 0.05, "-+" = 0.1),
               growth_rates = c("+" = 0.8, "-" = 0.3),
               death_rates = c("+" = 0.05, "-" = 0.05))

sim$mutate_progeny(sim$choose_cell_in("A"), "B")

sim$run_up_to_size("B+", 5000)
#>  [████████████████████████████████████████] 100% [00m:00s] Saving snapshot

ncells <- 0.9 * bbox_width * bbox_width

bbox <- sim$search_sample(c("B" = ncells), bbox_width, bbox_width)
sim$sample_cells("S_2_1", bbox$lower_corner, bbox$upper_corner)

bbox <- sim$search_sample(c("A" = ncells), bbox_width, bbox_width)
sim$sample_cells("S_2_2", bbox$lower_corner, bbox$upper_corner)

Let us have a look at the simulated tissue and plot the simulation Muller plot.

plot_tissue(sim, num_of_bins = 500)

The tissue plot of a tumour grown according the uniform growth model.

The Muller plot of a tumour grown according the uniform growth model.

Finally, let us build the ancestor forest of the samples.

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

forest <- sim$get_sample_forest()

plot_forest(forest) %>%
  annotate_forest(forest)

The sample forest of a tumour grown according the uniform growth model.

We use a special highlight parameter to add the edges connecting cells in each sample.

plot_forest(forest, highlight = "S_1_1") %>%
  annotate_forest(forest)

The sample forest of a tumour grown according the uniform growth model. The sub-forest of sample S_1_1 is highlighted.


plot_forest(forest, highlight = "S_1_2") %>%
  annotate_forest(forest)

The sample forest of a tumour grown according the uniform growth model. The sub-forest of sample S_1_2 is highlighted.


plot_forest(forest, highlight = "S_2_1") %>%
  annotate_forest(forest)

The sample forest of a tumour grown according the uniform growth model. The sub-forest of sample S_2_1 is highlighted.


plot_forest(forest, highlight = "S_2_2") %>%
  annotate_forest(forest)

The sample forest of a tumour grown according the uniform growth model. The sub-forest of sample S_2_2 is highlighted.

“Border” Growth

We now build a tissue simulation and use the “border” growth model.

set.seed(0)

sim <- TissueSimulation("Border Growth")

# Setting the "border" growth model is not needed as the
# border growth model is the default.
sim$border_growth_model
#> [1] TRUE

# Set the death activation level to avoid drift
sim$death_activation_level <- 50

Let us repeat what we did in the homogeneous growth model example.

# Add a mutant
sim$add_mutant(name = "A",
               epigenetic_rates = c("+-" = 0.01, "-+" = 0.01),
               growth_rates = c("+" = 0.1, "-" = 0.08),
               death_rates = c("+" = 0.1, "-" = 0.01))

sim$place_cell("A+", 500, 500)

# Let the simulation evolve until "A+" consists of 1300 cells
sim$run_up_to_size("A+", 1300)
#>  [███████████████████████████-------------] 65% [00m:00s] Cells: 27922 [████████████████████████████████████████] 100% [00m:00s] Saving snapshot

bbox_width <- 15

# Takes two samples
sim$sample_cells("S_1_1",
                 bottom_left = c(480, 480),
                 top_right = c(480 + bbox_width, 480 + bbox_width))

sim$sample_cells("S_1_2",
                 bottom_left = c(500, 500),
                 top_right = c(500 + bbox_width, 500 + bbox_width))

# Let the simulation evolve again for 15 time units
sim$run_up_to_time(sim$get_clock() + 15)
#>  [████████████████████████████████████████] 100% [00m:00s] Saving snapshot

# Add a new mutant
sim$add_mutant(name = "B",
               epigenetic_rates = c("+-" = 0.05, "-+" = 0.1),
               growth_rates = c("+" = 0.8, "-" = 0.3),
               death_rates = c("+" = 0.05, "-" = 0.05))


# Let one of the "A" cells generate a cell in "B"
sim$mutate_progeny(sim$choose_cell_in("A"), "B")

# Let the simulation evolve until "B+" consists of 5000 cells
sim$run_up_to_size("B+", 5000)
#>  [████████████████████████████████████████] 100% [00m:00s] Saving snapshot

ncells <- 0.9 * bbox_width * bbox_width

bbox <- sim$search_sample(c("B" = ncells), bbox_width, bbox_width)
sim$sample_cells("S_2_1", bbox$lower_corner, bbox$upper_corner)

bbox <- sim$search_sample(c("A" = ncells), bbox_width, bbox_width)
sim$sample_cells("S_2_2", bbox$lower_corner, bbox$upper_corner)

Let us have a look at the simulated tissue and plot the simulation Muller plot.

plot_tissue(sim, num_of_bins = 500)

The tissue plot of the above tumour grown according the border-driven growth model.

The Muller plot of the above tumour grown according the border-driven growth model.

Once more, let us build the ancestor forest of the samples.

forest <- sim$get_sample_forest()

plot_forest(forest) %>%
  annotate_forest(forest)

The sample forest of the tumour grown according the border-driven growth model.

We use a special highlight parameter to add the edges connecting cells in each sample.

plot_forest(forest, highlight = "S_1_1") %>%
  annotate_forest(forest)

The sample forest of the tumour grown according the border-driven growth model. The sub-forest of sample S_1_1 is highlighted.


plot_forest(forest, highlight = "S_1_2") %>%
  annotate_forest(forest)

The sample forest of the tumour grown according the border-driven growth model. The sub-forest of sample S_1_2 is highlighted.


plot_forest(forest, highlight = "S_2_1") %>%
  annotate_forest(forest)

The sample forest of the tumour grown according the border-driven growth model. The sub-forest of sample S_2_1 is highlighted.


plot_forest(forest, highlight = "S_2_2") %>%
  annotate_forest(forest)

The sample forest of the tumour grown according the border-driven growth model. The sub-forest of sample S_2_2 is highlighted.

It is easy to see the differences in the analogous plots of the above examples.

First of all, the cancer growth is slower when subject to the “border” growth model than when the homogeneous-growth model is used. This is because the internal cells cannot duplicate in the former growth model; thus, the number of cells active for duplication is always greater in it than in the homogeneous-growth model.

Moreover, spatial closeness and closeness in the sample forest are strictly related in the “border” growth model, whereas they appear to be loosely related in the homogeneous growth model. These features can be easily spotted in the forest plots when the sample S_2_1 is selected near the external tumour border.