Tutorial: Tyson-Novak 2001¶
This tutorial walks through the Tyson-Novak 2001, a model of the cell-cycle oscillator. It has eight state variables, twenty reactions, assignment rules, a function definition, and events, one of which represents cell division. This builds on the Goldbeter 1991 tutorial with a richer model that exercises more complex SBML constructs.
We generate it as a cell-cycle model, so the division event drives when a
Chaste cell divides.
1. Generate the code¶
The model ships with the repository under
chaste_sbml/SbmlRefModels/src/reference/TysonNovak2001/TysonNovak2001.xml.
As before, generate into a Chaste user project:
chaste-sbml chaste_sbml/SbmlRefModels/src/reference/TysonNovak2001/TysonNovak2001.xml --model-type cell-cycle \
--output-dir Chaste/projects/MyProject/src \
--test-output-dir Chaste/projects/MyProject/test
This produces the ODE system, the cell-cycle wrapper, and a placeholder test:
src/
├── TysonNovak2001SbmlOdeSystem.hpp/.cpp
└── TysonNovak2001SbmlCellCycleModel.hpp/.cpp
test/
└── TestTysonNovak2001Sbml.hpp
2. Function definitions¶
The model defines a Goldbeter-Koshland function GK(...). SBML function
definitions become C++ member functions taking double arguments:
// MODEL FUNCTIONS
inline double GK(double A1, double A2, double A3, double A4);
Calls to GK in the kinetic laws are emitted as ordinary calls to this method.
3. Events¶
The ODE constructor declares one event and sets up the per-event bookkeeping:
TysonNovak2001SbmlOdeSystem::TysonNovak2001SbmlOdeSystem()
: AbstractSbmlOdeSystem(8, 36, 1) // 8 state vars, 36 parameters, 1 event
{
// ...
// EVENTS
mEventType.resize(1, SbmlEventType::UNKNOWN);
// Uncomment lines below for events that should trigger cell division
mEventType[0] = SbmlEventType::CELL_DIVISION; // Cell division
mEventSatisfied = { true }; // From SBML trigger initialValue
// ...
}
The generator tries to guess which events cause division from their labels
and marks them SbmlEventType::CELL_DIVISION.
Note
Always review this block: uncomment or
comment the mEventType[...] lines so that exactly the events which should end
the cell cycle are tagged as division.
The actual event logic lives in ProcessModelEvents. For each event it computes
a signed trigger distance so that CVODE can root-find the exact firing time,
evaluates the trigger, and records the deferred event assignments. In this case,
an event assignment halves the cell mass at division:
double event_dist = (0.1) - (CycB) - std::numeric_limits<double>::epsilon();
bool active = CycB < 0.1;
// ...
mEventAdjustedStateValues[3] = m / 2.0; // deferred: halve mass at division
Note
Only a single top-level relational trigger (e.g. CycB < 0.1) yields a smooth
root-found firing time. Compound boolean or n-ary triggers still fire, but fall
back to a constant distance rather than smooth root-finding (e.g. (CycB < 0.1) && (m > 2.0)).
4. Cell cycle¶
The cell-cycle wrapper TysonNovak2001SbmlCellCycleModel owns the ODE system.
Its base class, AbstractSbmlCellCycleModel, connects the SBML event to Chaste:
ReadyToDivide() returns true only once an event tagged
SbmlEventType::CELL_DIVISION has fired, and ResetForDivision() clears the
event state for the next cycle.
5. Build and run¶
Copy the base classes into the project’s src/, register the test, and build. To
use it, pass the cell-cycle model when creating a cell:
#include "TysonNovak2001SbmlCellCycleModel.hpp"
CellPtr p_cell(new Cell(p_state, new TysonNovak2001SbmlCellCycleModel()));
p_cell->SetCellProliferativeType(p_type);
The cell now advances its ODE system each timestep and divides when the SBML division event fires.
Things to check¶
Time units: Confirm the assumed unit is right; pass
--timescaleif not.Event tags: Review the
mEventType[...]lines as the cell division guess is heuristic.
See also
Supported SBML features for the full list of SBML features the generator handles.