cacatoo
Version:
Building, exploring, and sharing spatially structured models
167 lines (123 loc) • 8.31 kB
HTML
<html>
<script src="../../dist/cacatoo.js"></script> <!-- Include cacatoo library (compiled with rollup) -->
<script src="../../lib/all.js"></script> <!-- Load other packages -->
<link rel="stylesheet" href="../../style/cacatoo.css"> <!-- Set style sheet -->
<head>
<title>Cacatoo</title>
</head>
<script>
/*-----------------------Start user-defined code ---------------------*/
let sim; // Declare a variable named "sim" globally, so that we can access our cacatoo-simulation from wherever we need.
/**
* function cacatoo() contains all the user-defined parts of a cacatoo-model. Configuration, update rules, what is displayed or plotted, etc. It's all here.
*/
function cacatoo() {
/*
1. SETUP. First, set up a configuration-object. Here we define how large the grid is, how long will it run, what colours will the critters be, etc.
*/
let config =
{
title: "Colony", // The name of your cacatoo-simulation
description: "", // And a description if you wish
maxtime: 1000000, // How many time steps the model continues to run
ncol: 100, // Number of columns (width of your grid)
nrow: 100, // Number of rows (height of your grid)
seed: 5,
wrap: [false, false], // Wrapped boundary conditions? [COLS, ROWS]
scale:2, // Scale of the grid (nxn pixels per grid point)
statecolours: {'species': { 1: "#FFFFFF", // Sets up colours of states (here 1,2,3 = A,B,C). Can be a colour name or a hexadecimal colour.
2: "red", // If your state it not defined, it won't be drawn and you'll see the grid-background colour (default: black)
3: "#3030ff"}}
}
/*
1. SETUP. (continued) Now, let's use that configuration-object to generate a new Cacatoo simulation
*/
sim = new Simulation(config) // Initialise the Cacatoo simulation
sim.makeGridmodel("model") // Build a new Gridmodel within the simulation called "model"
let init_individuals = [{species:1,uptake_rate:1.0,internal_resources:1},
{species:2,uptake_rate:10.0,internal_resources:1},
{species:3,uptake_rate:100.0,internal_resources:1}]
sim.populateSpot(sim.model, init_individuals, [0.33,0.33,0.33], 25, config.ncol/2, config.nrow/2) // Place the three 'species' in a small spot in the middle of the grid
sim.createDisplay("model", "species", "Species") // Create a display in the same way we did in Tutorial 1 (display a discrete variable)
// sim.createDisplay_continuous({model:"model", property:"uptake_rate", label:"Uptake rate", // Createa a display for a continuous variable (ODE state for external resources)
// minval:0,maxval:100,fill:"viridis"})
sim.createDisplay_continuous({model:"model", property:"external_resources", label:"External resources", // Createa a display for a continuous variable (ODE state for external resources)
minval:0, maxval:5, fill:"viridis",num_colours: 100, decimals: 2})
sim.createDisplay_continuous({model:"model", property:"internal_resources", label:"Internal resources", // Createa a display for a continuous variable (ODE state for external resources)
minval:0, maxval:1, fill:"viridis",num_colours: 100, decimals: 2})
/*
2. DEFINING THE RULES. Below, the user defines the nextState function. This function will be applied for each grid point when we will update the grid later.
*/
// Define ODEs with basic resource dynamics
let resource_dynamics = function (u, k) {
return function (x, y) {
let external = y[0] // The first variable (y[0]) is the external resource concentration, which is taken up with rate u
let internal = y[1] // The second variable (y[1]) is the internal resource concentration, which is used by the cells to divide
return [ -u * external,
u * external - k * internal ]
}
}
// Configuration object with initial states, parameters, and diffusion rates
let ode_config = {
ode_name: "resources",
init_states: [5, 0.0], // y[0] and y[1], with y[0] = R = 5 there is strong resource competition. Which much higher values the 3 strains are similar.
parameters: [0.0, 0.0], // u and k are set to 0.0 by default, as we will make it dependent on cell presence!
diffusion_rates: [0.2, 0.00] // resources diffuse through exteral environment, but internal resources stay put
}
// Attaches an ODE to all gridpoints with initial state = [0,0].
sim.model.attachODE(resource_dynamics, ode_config);
sim.model.nextState = function (x, y) {
let randomneigh = this.randomMoore8(this, x, y) // Random neighbour
let this_gp = this.grid[x][y] // This cell
if (this_gp.species == undefined) // If empty
{
if (randomneigh.species >= 1 && randomneigh.resources.state[1] > 0.5) {
this_gp.species = randomneigh.species
this_gp.uptake_rate = randomneigh.uptake_rate
randomneigh.resources.state[1] = this.grid[x][y].resources.state[1] = randomneigh.resources.state[1] / 2
}
}
else {
this.grid[x][y].resources.pars = [this_gp.uptake_rate, 0.5] // Living cells take up and have upkeep
if (this.rng.genrand_real1() < 0.002) {
this_gp.species = 0
this_gp.uptake_rate=0.0
this_gp.resources.state[1] = 0
this_gp.resources.pars = [0.0, 0.0]
}
}
this_gp.resources.solveTimestep(0.1)
this_gp.external_resources = this_gp.resources.state[0]
if(this_gp.species > 0) this_gp.internal_resources = this.grid[x][y].resources.state[1]
else this.grid[x][y].rersources = 0.0
}
/*
3. MAIN SIMULATION LOOP. Finally, we need to set the update-function, which is the mainwill be applied to the whole grid each time step. For now, all we will do is call "synchronous", which
applies the next-state function shown above to each grid point. All cells are updated at the same time, rather than in turn (for this, use the function "asynchonous")
*/
sim.model.update = function () {
this.asynchronous() // Applied as many times as it can in 1/60th of a second
this.diffuseODEstates() // Diffusion of external metabolites
this.plotODEstates("resources", [0, 1], [[0, 0, 0], [255, 0, 0]])
}
/*
OPTIONAL: Now that we have everything setup, we can also add some interactive elements (buttons or sliders). See cheater.html for more examples of this.
*/
sim.addButton("Play/pause sim", function () { sim.toggle_play() })
sim.start()
}
/*-------------------------End user-defined code ---------------------*/
</script>
<body onload="cacatoo()">
<div class="header" id="header">
<h2>Cacatoo (example project)</h2>
</div>
<div class="content" id="canvas_holder"> </div>
<div class="content" id="graph_holder"> </div>
<div class="content" id="form_holder"></div>
<div class="content" id="examples">
</div>
<div class="footer" id="footer"></div>
</div>
</body>
</html>