Cell Growth and Cell Death
Building on the previous tutorial, we add two crucial features of cell morphogenesis: cell growth and cell death.
In cell growth, there are two components to consider: physical growth and eventual cell division when it arrives at maximum cell size. Cell death occurs at approximately every 30 minutes of simulation in random proportion. In the following section, we describe the specifics of growth and death in much detail.
The tutorial is organized in the following manner:
Section 2. Model Descriptions explains the 3 files changed from the previous tutorial:
Section 3. Model Output describes the expected output and animation of the model. Section 4. Ordinary Differential Equations in Cell Growth will be left as an additional guide for readers who wish to utilize ODE’s to compute the rate of growth (instead of a constant). This is a more realistic way of modeling morphogenesis and requires the use of Biocellion’s ODENetInfo class.
In model_define.h, we introduce new global variables and enumerations needed to model cell growth, division, and death.
A_MAX_CELL_RADIUS A_MIN_CELL_RADIUS A_LINEAR_CELL_GROWTH_CONSTANT A_CELL_DENSITY A_CELL_DEATH_RATE cell_model_e UPTAKE_PCT_INC_RATIO
Since a cell must divide when it reaches its maximum cell size, we define the maximum radius, A_MAX_CELL_RADIUS as well as a minimum cell radius, A_MIN_CELL_RADIUS. A_MIN_CELL_RADIUS can serve two purposes. It could be set as the minimum cell radius immediately upon the birth, or if a cell has a property to shrink (by secretion), it may considered dead when the cell radius becomes smaller than A_MIN_CELL_RADIUS. We will use the former case for this model.
Cell growth rate, A_LINEAR_CELL_GROWTH_CONSTANT is a constant linear growth in this model. If you’d like to employ a more realistic growth using deterministic Ordinary Differential Equations, refer to Section 4. Ordinary Differential Equations in Cell Growth.
A_CELL_DENSITY is used to measure two cell states that change during model simulation: cell mass and cell volume. Notice that with cell radius and density, which are declared model states, we can always calculate the agent volume and mass of a cell.
A_CELL_DEATH_RATE is a constant cell rate at which cells die. This A_CELL_DEATH_RATE is “randomized” later for a realistic feel.
cell_model_e is the model enumeration for additional cell states: CELL_MODEL_REAL_BIOMASS and CELL_MODEL_REAL_UPTAKE_PERCT. The concept of uptake percentage and UPTAKE_PCT_INC_RATIO, constant used for increasing the model state at each step will be further explained in later tutorials. In this case, CELL_MODEL_REAL_UPTAKE_PERCT is only used to determine live and dead cells.
Since we have additional model states defined by cell_model_e, updateSpAgentInfo() needs to be revised. We simply set info.numStateModelReals to the last enumerator of our indexing scheme, CELL_NUM_MODEL_REALS.
Along with previous model states, we initialize the three new states (biomass, uptake percentage) in addSpAgnets().
In updateSpAgentState(), we set the model equation to grow the cells. Given a live specific agent (has an uptake percentage of greater than 0.0), the biomass of the cell grows at each time-step by the factor of A_LINEAR_CELL_GROWTH_CONSTANT, such that, . With the newBiomass value and global variable A_CELL_DENSITY, we can compute the new volume and the radius of the updated cell. Update by using state.setRadius() and state.setModelReal().
With a cell able to grow at each time-step, now we incorporate cell division. Cell division occurs when it reaches maximum cell size (A_MAX_CELL_RADIUS). We model cell division divideSpAgent(). The model function uses classes, motherState and daughterState to indicate the two different resulting cells. Using the OldBiomass (the cell biomass right before division), split the mass “roughly” in half using MODEL_RNG_UNIFORM. The resulting masses of the mother and daughter cells are MotherBiomass and DaugtherBiomass. Using the mass and density of the two cells, compute the volume, and eventually the radius. Initialize the new states (radius, biomass, default radius uptake percentage) of motherState and daugtherState. Remember that the daughterState needs the required cell type also. You may add additional model specifics in divideSpAgent() function i.e. if the cells push each other after division causing the cells to move, you can update motherDisp and daughterDisp.
In adjustSpAgent(), we determine whether a cell will die upon “roughly” at the time step determined by A_CELL_DEATH_RATE using MODEL_RNG_UNIOFRM. A cell is set dead by adjusting the Uptake Percentage to 0.0. A cell is determined dead if , where is A_CELL_DEATH_RATE[ type ], is BASELINE_TIME_STEP_DURATION, and is a uniformly randomly generated number between .
Finally, in updateSpAgentBirthDeath(), we set model rules for cell growth and death by updating the boolean variables, divide and disappear. Cell grow (divide = true) when the cell is live (uptake percentage > 0.0) and has reached A_MAX_CELL_RADIUS. Cells die (disappear = false) when cell has shrunk to the radius smaller than A_MIN_CELL_RADIUS, or the uptake percentage of the specific cell is 0.0 or less.
Refer to the attached animation.
Ordinary Differential Equations in Cell Growth
Should you choose to model cell growth as an exponential growth using ODE’s, make the following changes.
Instead of A_LINEAR_CELL_GROWTH_CONSTANT, we need a different constant, A_ODE_CELL_GROWTH_CONSTANT for the exponential growth.
ode_net_GrowingCell_var_e is the enumeration declaration for the ODE’s. ODE_NET_VAR_GrowingCell_biomass is the enumerator used for ODE initial condition, and update (after time-step) condition. model_routine_config.cpp In updateSpagentInfo(), along with the initial cell state info, we define odeNetInfo for each cell type. Here, we set all the parameters required for solving a deterministic ODE’s. Adjust epsilon to increase/decrease error size.
Assign initial ODE’s to each cell in addSpAgents().
Set Biocellion to solve the “Right Hand Side” of the deterministic ODE by filling out spAgentCRNODEHRS(). For our model, we use a standard exponential growth formula: . v_y stores the current value of biomass (ODE system variables), and v_f stores the derivatives of the ODE system. is A_ODE_CELL_GROWTH_CONSTANT.
In updateSpAgentState(), instead of linear multiplication or previous biomass, set newBiomass with getODEVal(). newBiomass is the solved rate of change from spAgentCRNODERHS() after each baseline time-step.