cacatoo
Version:
Building, exploring, and sharing spatially structured models
204 lines (173 loc) • 10.8 kB
HTML
<!--
EXAMPLE FILE Petri dish
Simple colony growth on a petri dish. To make things a little bit more
interesting, the "wild type" has an elevated death rate, which can be
fixed by mutations. You may notice how many more mutants accumulate
whent he colony grows on a petri dish rather than in the well-mixed
control. This phenomena is called "allele surfing", and is explained in
this paper: https://www.nature.com/articles/ncomms12760
-->
<html>
<script src="./scripts/cacatoo.js"></script> <!-- Include cacatoo library (compiled with rollup) -->
<script src="./scripts/all.js"></script> <!-- Include other libraries (concattenated in 1 file) -->
<link rel="stylesheet" href="./styles/cacatoo.css"> <!-- Set style sheet -->
<script>
/*-----------------------Start user-defined code ---------------------*/
let sim;
var mutationrate = 0.001;
var cell_diffusion = 0;
var death_rate_growing = 0.0;
var mutations_required = 1;
function cacatoo()
{
let config = {
title: "Petridish with local growth",
description: "",
maxtime: 10000000,
fastmode: false, // If possible, fast-mode will update the sim with more than 60 FPS.
// Note: fastmode is only useful/recommended if the sim can readily run
// at 60FPS without fast-mode, and may actually reduce the reported FPS
// Nevertheless, the final state of the grid is reaches sooner in real time.
ncol : 100,
nrow : 100, // dimensions of the grid to build
wrap : [true, true], // Wrap boundary [COLS, ROWS]
scale : 1, // scale of the grid (nxn pixels per grid cell)
graph_interval: 10,
graph_update: 20,
statecolours: {alive:'default'} // The background state '0' is never drawn
}
sim = new Simulation(config)
sim.makeGridmodel("cells");
sim.createDisplay("cells","alive", "Colony on petridish")
sim.makeGridmodel("cells_wellmixed");
sim.createDisplay("cells_wellmixed","alive","Well-mixed population")
let birth_rate = 0.85
sim.cells.statecolours.alive[0] = [255,255,255] // Change bg to white
sim.cells.statecolours.alive[1] = [79,31,154] // Change WT 1 to white
sim.cells.statecolours.alive[2] = [228,178,36] // Change mutant 1 to gold
sim.cells.statecolours.alive[3] = [32, 100, 100] // Change mutant 2 to dark-turquoise
sim.cells.statecolours.alive[3] = [100, 100, 255] // Change mutant 3 to light blue
sim.cells.nr_of_mutations = 0
sim.cells_wellmixed.nr_of_mutations = 0
sim.cells.nextState = function(i,j) // Define the next-state function. This example is stochastic growth in a petri dish
{
if(this.grid[i][j].alive == 0)
{
let neighbour = this.randomMoore8(this,i,j) // In the Moore8 neighbourhood of this grid count # of 1's for the 'alive' property
if (neighbour.alive > 0 && sim.rng.genrand_real1() < birth_rate)
{
this.grid[i][j].alive = neighbour.alive
if(sim.rng.genrand_real1() < mutationrate){
this.grid[i][j].alive = (this.grid[i][j].alive+1)%19
this.nr_of_mutations++
}
}
}
else
{
if(this.grid[i][j].age < 10 && this.grid[i][j].alive <= mutations_required && sim.rng.genrand_real1() < death_rate_growing)
this.grid[i][j].alive = 0
else
this.grid[i][j].age++
}
}
sim.cells_wellmixed.nextState = sim.cells.nextState
sim.cells.update = function()
{
this.synchronous() // Applied as many times as it can in 1/60th of a second
for(let i=0; i<cell_diffusion; i++) this.MargolusDiffusion()
this.plotPopsizes('alive',[1,2,3])
if(this.time%200==0) sim.cells.reset()
}
sim.cells_wellmixed.update = function()
{
this.synchronous() // Applied as many times as it can in 1/60th of a second
for(let i=0; i<cell_diffusion; i++) this.MargolusDiffusion()
this.plotPopsizes('alive',[1,2,3])
sim.cells_wellmixed.perfectMix()
this.plotArray(['Cumulative mut (colony)', 'Cumulative mut (WM)'],[sim.cells.nr_of_mutations,this.nr_of_mutations,],["black","grey"],"Cumulative mutations in both pops",{drawPoints: true, strokeWidth:2, pointSize:2, strokePattern: [1,2]})
}
sim.cells.reset = function()
{
sim.initialSpot(sim.cells,'alive',1,2,sim.cells.nr/2,sim.cells.nc/2)
sim.initialSpot(sim.cells_wellmixed,'alive',1,2,sim.cells_wellmixed.nr/2,sim.cells_wellmixed.nc/2)
sim.initialGrid(sim.cells,'age',0,1.0)
sim.initialGrid(sim.cells_wellmixed,'age',0,1.0)
}
sim.cells.reset()
sim.cells.bottleneck = function()
{
for(let i=0; i<this.nc; i++)
for(let j=0;j<this.nr;j++)
if(this.rng.genrand_real1() < 0.999) this.grid[i][j].alive = 0
}
sim.addButton("pause/continue",function() {sim.toggle_play()}) // Add a button that calls function "display" in "model"
sim.addButton("mix once",function() { sim.cells.perfectMix()}) // Add a button that calls function "perfectMix" in "model.cheater"
sim.addButton("well-mix",function() { sim.toggle_mix()}) // Add a button that calls function "perfectMix" in "model.cheater"
sim.addButton("bottleneck",function() { sim.cells.bottleneck()}) // Add a button that calls function "perfectMix" in "model.cheater"
sim.addButton("reset",function() { sim.cells.reset()}) // Add a button that calls function "perfectMix" in "model.cheater"
sim.addHTML("form_holder","<br>")
sim.addSlider("mutationrate",0.0,0.01,0.0001)
sim.addSlider("death_rate_growing",0.0,1.0,0.01)
sim.addSlider("cell_diffusion",0,10,1)
sim.addSlider("mutations_required",0,10,1)
sim.start()
}
/*-------------------------End user-defined code ---------------------*/
</script>
<body onload="cacatoo()">
<!-- --------------------- START MENU. Couldnt get it to load dynamically, so this needs to be replaced in every HTML file upon changing --------------------- -->
<header class="header" id="btnNav"><buton class="header__button" id="btnNav" type="button"><i class="material-icons">menu</i></buton></header>
<nav class="nav"><div class="nav__links">
<a href="#" class="nav__head"><i id="btnNavclose" class="material-icons" style="cursor:pointer"> menu </i> Cacatoo </a>
<a href="index.html" id="nav__link" class="nav__link">Home</a>
<a href="https://github.com/bramvandijk88/cacatoo" id="nav__link" target="_blank" class="nav__link"> Source code (Github)</a>
<!-- <a href="https://replit.com/@bramvandijk88/Cacatoo-IBMs-with-examples" id="nav__link" target="_blank" class="nav__link"> Replit </a> -->
<a href="#" class="nav__head"><i class="material-icons"> play_circle_outline </i> Examples</a>
<a href="example_predator_prey.html" id="nav__link" class="nav__link"> Predator prey</a>
<a href="example_colony_growth.html" id="nav__link" class="nav__link"> Colony growth</a>
<a href="example_pheromones.html" id="nav__link" class="nav__link"> Ant pheromones</a>
<a href="example_aapjes.html" id="nav__link" class="nav__link"> Aapjes (monkeys)</a>
<a href="example_mutational_jackpot.html" id="nav__link" class="nav__link"> Mutational jackpot</a>
<a href="example_starlings.html" id="nav__link" class="nav__link"> Starlings</a> <a href="example_cooperation.html" id="nav__link" class="nav__link"> Cooperation</a>
<a href="example_TEs.html" id="nav__link" class="nav__link"> Transposon evolution</a>
<a href="examples_jsfiddle.html" id="nav__link" class="nav__link"> More examples (JSFiddle)</a>
<a href="#" class="nav__head"><i class="material-icons"> grid_on </i> How to Cacatoo </a>
<a href="overview.html" class="nav__link"> Tutorials (Blog style)</a>
<a href="list_of_options.html" class="nav__link"> All configuration options</a>
<a href="populating_the_simulation.html" class="nav__link"> Populating a simulation</a> <a href="display_and_colours.html" class="nav__link"> Display, colours, and UI</a>
<a href="neighbourhood_retrieval.html" class="nav__link"> Neighbourhood retrieval</a>
<a href="random_numbers.html" class="nav__link"> Using random numbers </a>
<a href="grid_events.html" class="nav__link"> Grid events</a>
<a href="working_with_odes.html" class="nav__link"> Working with ODEs</a>
<a href="jsdocs/index.html" id="nav__headlink" target="_blank" class="nav__headlink"><i class="material-icons">data_object </i> Full JS-Docs</a>
</div><div class="nav__overlay"></div></nav>
<script>
document.addEventListener("DOMContentLoaded", () => {
const nav = document.querySelector(".nav");
document.querySelector("#btnNav").addEventListener("click", () => {
nav.classList.add("nav--open");
});
document.querySelector(".nav__overlay").addEventListener("click", () => {
nav.classList.remove("nav--open");
});
document.querySelector("#btnNavclose").addEventListener("click", () => {
nav.classList.remove("nav--open");
});
var all_links = document.getElementsByClassName("nav__link");
var hide_menu = function() {
nav.classList.remove("nav--open");
};
for (var i = 0; i < all_links.length; i++) {
all_links[i].addEventListener('click', hide_menu, false);
}
});
</script>
<!-- --------------------- END MENU --------------------- -->
<div class="header" id="header"><h2>Cacatoo</h2></div>
<div class="content" id="canvas_holder"></div>
<div class="content" id="form_holder"></div>
<div class="content" id="graph_holder"> </div>
<div class="footer" id="footer"></div>
</body>
</html>