# 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[0].length; y++) { grid[x][y].setNeighbors(); } } } function drawAll() { for (var x = 0; x < grid.length; x++) { for (var y = 0; y < grid[0].length; y++) { grid[x][y].draw(); } } } function draw() { scale(blockSize); for (var i = 0; i < grid.length * grid[0].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[0].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); }