# Colon cancer

This is a simple model of colon cancer growth in niches (colonic crypts). I was inspired by Mathematical modeling of cell population dynamics in the colonic crypt and in colorectal cancer by Matthew Johnston and colleagues.

## Rates

Matthew's continuous model has 3 types of cells. Simplifying this to Stem and "Leaf" cells, I can write:

```dStem/dt = (growth-change).Stem
dLeaf/dt = change.Stem - death.Leaf
initial: Stem = 1, Leaf = 0```

Without spatial considerations, the populations grow rapidly. To balance this, we have to modify the rate term to:

`(growth-change-high.Stem/(1+low.Stem)).Stem`

This is difficult to justify biologically, and makes analysis complicated.

Rate models (d/dt) are useful as a first step in describing a system. They can be manipulated, sometimes solved, and fairly well understood. But when we push a model too hard, the results aren't useful. The big simplification here is that individual cells form a continuous medium. Now we have computers, we can simulate individuals.

## Cells

My simple model only has two healthy populations: stem and "leaf" cells — differentiated cell, or common population. The cells are spatially arranged, covering a grid. Stem cells divide regularly, about once every 50 cycles. Since there is no free space, for a cell to divide, a neighbour must be destroyed. When a stem cell divides, it mostly produces one stem cell and one leaf cell. Occasionally — 1 time in 20 —  it produces 2 stem cells. Leaf cells are totally inert, unable to divide. (To compare to the continuous model, this is roughly birth=20, change=19.)

I initiate the model with all stem cells (blue). The tissue settles down quickly to a homeostatic balance of stem cell niches surrounded by leaf cells (white). The simulation is below. To see the initial behaviour, reload the page to restart.

## Cancer

I also have a second population: cancer stem cells and cancer leaf cells. They behave similarly to the healthy tissue — but the cancer propagates more aggressively. A cancer stem stem (red) is 10x more likely to divide than a healthy stem cell. This is the only difference. The cancerous stem cell only produces another stem cancer cell 1 in 20 divisions. Mostly it produces cancer leaf cells (pink).

I seed a blob of cancer in the middle of the field. The simple rules combined with the spatial restrictions produce a slow-growing cancer.

## Slow growth

How does the cancer grow so slowly ? The leaf cells, both healthy and cancerous, are inert; only the stem cells are dynamic, so invasive. Cancerous stem cells can invade healthy tissue easily — but only when they have healthy tissue neighbouring them. There is also a slight push-back from the healthy tissue: 1/10 as often a healthy stem cell will invade the cancer.

## Reality

This model is too simple to be much use. It deliberately ignores the folded nature of colonic crypts, and doesn't allow for the distortions of cancer — I imagined the crypts flattened-out. (If you want, you can also imagine the cancer growing into  the third dimension.) I made it to show that an incredibly simple cell model can produce robust, plausible behaviour.

## Code in Processing

### javascript variant p5

```var blockSize = 10;
var grid = [];

var STEM = 0;
var LEAF = 1;
var STEMCANCER = 2;
var LEAFCANCER = 3;
var typeColor = [];

var fitness = [
2,  // stem cells
0,  // leaf cells
20, // cancerous stem cells
0   // cancerous leaf cells
];

function setup() {
var xGrid = round(windowWidth / blockSize);
var yGrid = round(windowHeight / blockSize);
var canvas = createCanvas(xGrid * blockSize, yGrid * blockSize);
canvas.parent("container");
noStroke();
scale(blockSize);

typeColor[STEM] = color(128, 213, 255);
typeColor[LEAF] = color(255);
typeColor[STEMCANCER] = color(176, 47, 28);
typeColor[LEAFCANCER] = color(255, 192, 179);

makeGrid(xGrid, yGrid);
setNeighbors();
drawAll();
}

function makeGrid(xGrid, yGrid) {
for (var x = 0; x < xGrid; x++) {
grid[x] = [];
for (var y = 0; y < yGrid; y++) {
// most of the tissue is healthy
grid[x][y] = new Element(x, y, STEM);
// blob of cancer cells in the middle
if (dist(x, y, xGrid / 2, yGrid / 2) < 10) {
grid[x][y].change(STEMCANCER);
}
}
}
}

function setNeighbors() {
for (var x = 0; x < grid.length; x++) {
for (var y = 0; y < grid.length; y++) {
grid[x][y].setNeighbors();
}
}
}

function drawAll() {
for (var x = 0; x < grid.length; x++) {
for (var y = 0; y < grid.length; y++) {
grid[x][y].draw();
}
}
}

function draw() {
scale(blockSize);
for (var i = 0; i < grid.length * grid.length; i++) update();
}

function update() {
var element = random(random(grid));

// if sufficiently fit, assimilate a neighbor
if (fitness[element.type] > random(100)) {
if (element.type === STEM) {
if (random(20) > 1) {
// only 1 in 20 new stem cells don't differentiate
random(element.neighbors).change(LEAF);
return;
}
}
if (element.type === STEMCANCER) {
if (random(20) > 1) {
random(element.neighbors).change(LEAFCANCER);
return;
}
}
random(element.neighbors).change(element.type);
}
}

function Element(X, Y, t) {
this.x = X;
this.y = Y;
this.neighbors = [];

this.setNeighbors = function() {
if (this.x > 0) // left
this.neighbors.push(grid[this.x - 1][this.y]);
if (this.y > 0) // down
this.neighbors.push(grid[this.x][this.y - 1]);
if (this.y < grid.length - 1) // up
this.neighbors.push(grid[this.x][this.y + 1]);
if (this.x < grid.length - 1) // right
this.neighbors.push(grid[this.x + 1][this.y]);
};

this.draw = function() {
fill(typeColor[this.type]);
rect(this.x, this.y, 1, 1);
};

this.change = function(t) {
this.type = t;
this.draw();
};

this.change(t);
}```