Beispiel #1
0
    void TestAssigningModifiersToACellModel() throw(Exception)
    {
        boost::shared_ptr<ZeroStimulus> p_stimulus(new ZeroStimulus());
        boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver);
        CellShannon2004FromCellML* p_shannon = new CellShannon2004FromCellML(p_solver, p_stimulus);

        TS_ASSERT_EQUALS(p_shannon->HasModifier("Alan"), false);
        TS_ASSERT_THROWS_THIS(p_shannon->GetModifier("Alan"), "There is no modifier called Alan in this model.");


        // Default modifier shouldn't do anything to the value inputted to calc()
        TS_ASSERT_EQUALS(p_shannon->HasModifier("membrane_rapid_delayed_rectifier_potassium_current_conductance"), true);
        TS_ASSERT_DELTA(p_shannon->GetModifier("membrane_rapid_delayed_rectifier_potassium_current_conductance")->Calc(123,0),123,1e-9);

        // Make a new modifier
        boost::shared_ptr<AbstractModifier> p_new_modifier(new FixedModifier(-90.0));

        TS_ASSERT_THROWS_THIS(p_shannon->SetModifier("Alan",p_new_modifier), "There is no modifier called Alan in this model.");

        // Assign it to the Shannon model
        p_shannon->SetModifier("membrane_rapid_delayed_rectifier_potassium_current_conductance",p_new_modifier);

        // We should now get a new answer to this.
        TS_ASSERT_DELTA(p_shannon->GetModifier("membrane_rapid_delayed_rectifier_potassium_current_conductance")->Calc(0,0),-90,1e-9);

        delete p_shannon;
    }
    //  Run normally up to stretch-time, then apply stretch and
    //  run until stretch-off-time, then return to stretch=1
    //  and run until 1000ms.
    void RunModelWithSacRecruitment(double stretch,
                                    double stretchStartTime,
                                    double stretchEndTime,
                                    std::string directory,
                                    std::string filePrefix,
                                    bool clearDir)
    {
        boost::shared_ptr<SimpleStimulus> p_stimulus(new SimpleStimulus(
                -3 /*magnitude*/,
                3 /*duration*/,
                10.0 /*start time*/));
        boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver);

        double time_step = 0.01;
        HeartConfig::Instance()->SetOdePdeAndPrintingTimeSteps(time_step, time_step, 1.0);

        CML_noble_varghese_kohl_noble_1998_basic_with_sac   n98_with_sac(p_solver, p_stimulus);

        OutputFileHandler handler(directory,clearDir);
        out_stream p_file = handler.OpenOutputFile(filePrefix+".dat");
        *p_file << 0 << " " << n98_with_sac.GetVoltage() << "\n";

        double printing_dt = 1;
        TimeStepper stepper(0, stretchStartTime, printing_dt);

        while ( !stepper.IsTimeAtEnd() )
        {
            n98_with_sac.Compute(stepper.GetTime(), stepper.GetNextTime());
            stepper.AdvanceOneTimeStep();

            *p_file << stepper.GetTime() << " " << n98_with_sac.GetVoltage() << "\n";
        }

        n98_with_sac.SetStretch(stretch);

        TimeStepper stepper2(stepper.GetTime(), stretchEndTime, printing_dt);
        while ( !stepper2.IsTimeAtEnd() )
        {
            n98_with_sac.Compute(stepper2.GetTime(), stepper2.GetNextTime());
            stepper2.AdvanceOneTimeStep();

            *p_file << stepper2.GetTime() << " " << n98_with_sac.GetVoltage() << "\n";
        }

        n98_with_sac.SetStretch(1.0);

        TimeStepper stepper3(stepper2.GetTime(), 1000, printing_dt);
        while ( !stepper3.IsTimeAtEnd() )
        {
            n98_with_sac.Compute(stepper3.GetTime(), stepper3.GetNextTime());
            stepper3.AdvanceOneTimeStep();

            *p_file << stepper3.GetTime() << " " << n98_with_sac.GetVoltage() << "\n";
        }

        p_file->close();
    }
    void TestOdeSolverForFox2002WithRegularStimulus(void) throw (Exception)
    {
        clock_t ck_start, ck_end;
        // Set stimulus
        double magnitude = -80.0;
        double duration  = 1.0 ;  // ms
        double start = 50.0; // ms
        double period = 500; // ms
        boost::shared_ptr<RegularStimulus> p_stimulus(new RegularStimulus(magnitude, duration, period, start));

        double end_time = 1000.0; //One second in milliseconds


        HeartConfig::Instance()->SetOdeTimeStep(0.002); // 0.005 leads to NaNs.

        boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver);
        CellFoxModel2002FromCellML fox_ode_system(p_solver, p_stimulus);

        // Solve and write to file
        ck_start = clock();
        RunOdeSolverWithIonicModel(&fox_ode_system,
                                   end_time,
                                   "FoxRegularStimLong",
                                   500);
        ck_end = clock();
        double forward = (double)(ck_end - ck_start)/CLOCKS_PER_SEC;

        CheckCellModelResults("FoxRegularStimLong");

        // Solve using Backward Euler
        HeartConfig::Instance()->SetOdeTimeStep(0.01);
        CellFoxModel2002FromCellMLBackwardEuler backward_system(p_solver, p_stimulus);
        ck_start = clock();
        RunOdeSolverWithIonicModel(&backward_system,
                                   end_time,
                                   "BackwardFoxRegularStimLong",
                                   100);
        ck_end = clock();
        double backward = (double)(ck_end - ck_start)/CLOCKS_PER_SEC;

        CompareCellModelResults("FoxRegularStimLong", "BackwardFoxRegularStimLong", 0.15);
        // Mainly for coverage, and to test consistency of GetIIonic
        TS_ASSERT_DELTA(fox_ode_system.GetIIonic(),
                        backward_system.GetIIonic(),
                        1e-6);

        std::cout << "Run times:\n\tForward: " << forward
                  << "\n\tBackward: " << backward
                  << std::endl;

    }
Beispiel #4
0
    void TestAccessingParametersWithoutModifiers() throw(Exception)
    {
        boost::shared_ptr<ZeroStimulus> p_stimulus(new ZeroStimulus());
        boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver);
        CellShannon2004FromCellML* p_shannon = new CellShannon2004FromCellML(p_solver, p_stimulus);

        // We should now have all of the following methods available as an alternative to using 'modifiers'
        TS_ASSERT_DELTA(p_shannon->GetParameter("membrane_fast_sodium_current_conductance"),16.0,1e-5);
        TS_ASSERT_DELTA(p_shannon->GetParameter("membrane_L_type_calcium_current_conductance"),5.4e-4,1e-5);
        TS_ASSERT_DELTA(p_shannon->GetParameter("membrane_rapid_delayed_rectifier_potassium_current_conductance"),0.03,1e-5);
        TS_ASSERT_DELTA(p_shannon->GetParameter("membrane_slow_delayed_rectifier_potassium_current_conductance"),0.07,1e-5);

        delete p_shannon;
     }
    void TestArchiving(void) throw(Exception)
    {
        //Archive
        OutputFileHandler handler("archive", false);
        handler.SetArchiveDirectory();
        std::string archive_filename =  ArchiveLocationInfo::GetProcessUniqueFilePath("GI.arch");

        // Save
        {

            boost::shared_ptr<SimpleStimulus> p_stimulus(new SimpleStimulus(0.0,1.0,0.5));
            boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver);
            double time_step = 0.01;
            HeartConfig::Instance()->SetOdePdeAndPrintingTimeSteps(time_step, time_step, time_step);

            // icc and smc
            AbstractCardiacCell* const p_smc = new CorriasBuistSMCModified(p_solver, p_stimulus);
            AbstractCardiacCell* const p_icc = new CorriasBuistICCModified(p_solver, p_stimulus);

            std::ofstream ofs(archive_filename.c_str());
            boost::archive::text_oarchive output_arch(ofs);

            output_arch <<  p_smc;
            output_arch <<  p_icc;

            delete p_smc;
            delete p_icc;
        }
        // Load
        {
            std::ifstream ifs(archive_filename.c_str(), std::ios::binary);
            boost::archive::text_iarchive input_arch(ifs);

            AbstractCardiacCell* p_smc;
            AbstractCardiacCell* p_icc;
            input_arch >> p_smc;
            input_arch >> p_icc;

            TS_ASSERT_EQUALS( p_smc->GetNumberOfStateVariables(), 14U );
            TS_ASSERT_EQUALS( p_icc->GetNumberOfStateVariables(), 18U );

            delete p_smc;
            delete p_icc;
        }
     }
    void TestScaleFactorsMaleckar(void) throw (Exception)
    {
        double end_time =500;
        boost::shared_ptr<RegularStimulus> p_stimulus(new RegularStimulus(-5.6,
                                                                          6,
                                                                          1000,
                                                                          4.0));

        boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver); //define the solver
        HeartConfig::Instance()->SetOdeTimeStep(0.001);
        CellMaleckar2008FromCellML atrial_ode_system(p_solver, p_stimulus);

        const std::string control_file = "control";
        const std::string first_set_file = "first_scale_factor_set";
        const std::string second_set_file = "second_scale_factor_set";
        const std::string AZD_file = "AZD_scale_factor_set";

        OdeSolution control_solution;
        OdeSolution first_scale_factor_set_solution;
        OdeSolution second_scale_factor_set_solution;
        OdeSolution AZD_scale_factor_set_solution;

        double time_step=0.001;
        double sampling_time=0.001;
        std::vector<double> state_variables= atrial_ode_system.GetInitialConditions();

        //default values
        atrial_ode_system.SetParameter("ScaleFactorGks",1.0);
        atrial_ode_system.SetParameter("ScaleFactorIto",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGkr",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGna",1.0);
        atrial_ode_system.SetParameter("ScaleFactorAch",1e-24);
        atrial_ode_system.SetParameter("ScaleFactorGNaK",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGNaCa",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGKur",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGK1",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGCaL",1.0);
        atrial_ode_system.SetParameter("ScaleFactorAZD",0.0);

        control_solution = p_solver->Solve(&atrial_ode_system, state_variables, 0, end_time, time_step, sampling_time);
        control_solution.WriteToFile("TestIonicModels",
                              control_file,
                              "ms",//time units
                              100,//steps per row
                              false);/*true cleans the directory*/

        //now apply the first scale factor set, decreases outward currents
        atrial_ode_system.SetParameter("ScaleFactorGks",0.8);
        atrial_ode_system.SetParameter("ScaleFactorIto",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGkr",0.9);
        atrial_ode_system.SetParameter("ScaleFactorGna",1.0);
        atrial_ode_system.SetParameter("ScaleFactorAch",1e-24);
        atrial_ode_system.SetParameter("ScaleFactorGNaK",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGNaCa",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGKur",0.7);
        atrial_ode_system.SetParameter("ScaleFactorGK1",0.6);
        atrial_ode_system.SetParameter("ScaleFactorGCaL",1.0);
        atrial_ode_system.SetParameter("ScaleFactorAZD",0.0);

        state_variables= atrial_ode_system.GetInitialConditions();
        first_scale_factor_set_solution = p_solver->Solve(&atrial_ode_system, state_variables, 0, end_time, time_step, sampling_time);
        first_scale_factor_set_solution.WriteToFile("TestIonicModels",
                              first_set_file,
                              "ms",//time units
                              100,//steps per row
                              false);/*true cleans the directory*/

        //now apply the secondscale factor set, this one increases inward currents
        atrial_ode_system.SetParameter("ScaleFactorGks",1.0);
        atrial_ode_system.SetParameter("ScaleFactorIto",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGkr",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGna",1.5);
        atrial_ode_system.SetParameter("ScaleFactorAch",1e-24);
        atrial_ode_system.SetParameter("ScaleFactorGNaK",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGNaCa",2.0);
        atrial_ode_system.SetParameter("ScaleFactorGKur",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGK1",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGCaL",1.6);
        atrial_ode_system.SetParameter("ScaleFactorAZD",0.0);

        state_variables= atrial_ode_system.GetInitialConditions();
        second_scale_factor_set_solution = p_solver->Solve(&atrial_ode_system, state_variables, 0, end_time, time_step, sampling_time);
        second_scale_factor_set_solution.WriteToFile("TestIonicModels",
                              second_set_file,
                              "ms",//time units
                              100,//steps per row
                              false);/*true cleans the directory*/

        //check the AZD scale factor (vs control)
        atrial_ode_system.SetParameter("ScaleFactorGks",1.0);
        atrial_ode_system.SetParameter("ScaleFactorIto",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGkr",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGna",1.0);
        atrial_ode_system.SetParameter("ScaleFactorAch",1e-24);
        atrial_ode_system.SetParameter("ScaleFactorGNaK",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGNaCa",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGKur",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGK1",1.0);
        atrial_ode_system.SetParameter("ScaleFactorGCaL",1.0);
        atrial_ode_system.SetParameter("ScaleFactorAZD",5.0);

        AZD_scale_factor_set_solution = p_solver->Solve(&atrial_ode_system, state_variables, 0, end_time, time_step, sampling_time);
        AZD_scale_factor_set_solution.WriteToFile("TestIonicModels",
                              AZD_file,
                              "ms",//time units
                              100,//steps per row
                              false);/*true cleans the directory*/


        ColumnDataReader data_reader1("TestIonicModels", control_file);
        std::vector<double> voltages1 = GetVoltages(data_reader1);
        ColumnDataReader data_reader2("TestIonicModels", first_set_file);
        std::vector<double> voltages2 = GetVoltages(data_reader2);
        ColumnDataReader data_reader3("TestIonicModels", second_set_file);
        std::vector<double> voltages3 = GetVoltages(data_reader3);
        ColumnDataReader data_reader4("TestIonicModels", AZD_file);
        std::vector<double> voltages4 = GetVoltages(data_reader4);

        TS_ASSERT_EQUALS(voltages1.size(), voltages2.size());
        TS_ASSERT_EQUALS(voltages2.size(), voltages3.size());
        TS_ASSERT_EQUALS(voltages3.size(), voltages4.size());

        //create the times vector
        std::vector<double> times;
        double k =0;
        for (unsigned i=0; i<voltages2.size(); i++)
        {
          times.push_back(k);
          k=k+0.1;
        }

        CellProperties cell_properties_control(voltages1, times);
        CellProperties cell_properties_first(voltages2, times);
        CellProperties cell_properties_second(voltages3, times);
        CellProperties cell_properties_AZD(voltages4, times);

        double control_APD = cell_properties_control.GetLastActionPotentialDuration(90);
        double first_APD = cell_properties_first.GetLastActionPotentialDuration(90);
        double second_APD = cell_properties_second.GetLastActionPotentialDuration(90);
        double AZD_APD = cell_properties_AZD.GetLastActionPotentialDuration(90);

        //test that the aps are actually longer than control (all interventions were meant to have that effect except the last one)
        TS_ASSERT_LESS_THAN(control_APD, first_APD);
        TS_ASSERT_LESS_THAN(control_APD, second_APD);
        TS_ASSERT_LESS_THAN(AZD_APD, control_APD);

        //leave some hardcoded value for testing
        TS_ASSERT_DELTA(control_APD, 206.1278, 0.1);
        TS_ASSERT_DELTA(first_APD, 403.8293, 0.1);
        TS_ASSERT_DELTA(second_APD, 320.0195, 0.1);
        TS_ASSERT_DELTA(AZD_APD , 187.8073, 0.1);
    }
    /**
     * Here we test that the scale factors for the TT model do what they are expected to
     * We check that they modify APD in a way that is expected.
     */
    void TestScaleFactorsForTT06(void)
    {
        double simulation_end=500;/*end time, in milliseconds for this model*/

        // Set the stimulus, the following values are appropriate for single cell simulations of this model.
        double magnitude = -38.0;   // pA/pF
        double duration = 1.0;  // ms
        double start = 100;   // ms
        boost::shared_ptr<SimpleStimulus> p_stimulus(new SimpleStimulus(magnitude,
                                                                        duration,
                                                                        start));
        boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver); //define the solver
        HeartConfig::Instance()->SetOdeTimeStep(0.001);// with Forward Euler, this must be as small as 0.001.


        const std::string control_file = "TT_epi";
        const std::string mid_file = "TT_mid";
        const std::string endo_file = "TT_endo";
        const std::string LQT_file = "TT_LQT";

        CellTenTusscher2006EpiFromCellML TT_model_epi(p_solver, p_stimulus);

        TT_model_epi.SetParameter("ScaleFactorIto", 1.0);
        TT_model_epi.SetParameter("ScaleFactorGkr", 1.0);
        TT_model_epi.SetParameter("ScaleFactorGks", 1.0);
        //run the model
        RunOdeSolverWithIonicModel(&TT_model_epi,
                                   simulation_end,
                                   control_file,
                                   100,
                                   false);

        CellTenTusscher2006EpiFromCellML TT_model_mid(p_solver, p_stimulus);
        TT_model_mid.SetParameter("ScaleFactorIto", 1.0);
        TT_model_mid.SetParameter("ScaleFactorGkr", 1.0);
        TT_model_mid.SetParameter("ScaleFactorGks", 0.25);

        RunOdeSolverWithIonicModel(&TT_model_mid,
                                   simulation_end,
                                   mid_file,
                                   100,
                                   false);

        CellTenTusscher2006EpiFromCellML TT_model_endo(p_solver, p_stimulus);
        TT_model_endo.SetParameter("ScaleFactorIto", 0.165);
        TT_model_endo.SetParameter("ScaleFactorGkr", 1.0);
        TT_model_endo.SetParameter("ScaleFactorGks", 0.66);

        RunOdeSolverWithIonicModel(&TT_model_endo,
                                   simulation_end,
                                   endo_file,
                                   100,
                                   false);

        CellTenTusscher2006EpiFromCellML TT_model_LQT(p_solver, p_stimulus);
        TT_model_LQT.SetParameter("ScaleFactorIto", 1.0);
        TT_model_LQT.SetParameter("ScaleFactorGkr", 0.0);
        TT_model_LQT.SetParameter("ScaleFactorGks", 1.0);

        RunOdeSolverWithIonicModel(&TT_model_LQT,
                                   simulation_end,
                                   LQT_file,
                                   100,
                                   false);

        ColumnDataReader data_reader1("TestIonicModels", control_file);
        std::vector<double> voltages1 = GetVoltages(data_reader1);
        ColumnDataReader data_reader2("TestIonicModels", mid_file);
        std::vector<double> voltages2 = GetVoltages(data_reader2);
        ColumnDataReader data_reader3("TestIonicModels", endo_file);
        std::vector<double> voltages3 = GetVoltages(data_reader3);
        ColumnDataReader data_reader4("TestIonicModels", LQT_file);
        std::vector<double> voltages4 = GetVoltages(data_reader4);

        TS_ASSERT_EQUALS(voltages1.size(), voltages2.size());
        TS_ASSERT_EQUALS(voltages2.size(), voltages3.size());
        TS_ASSERT_EQUALS(voltages3.size(), voltages4.size());

        //create the times vector
        std::vector<double> times;
        double k =0;
        for (unsigned i=0; i<voltages2.size(); i++)
        {
          times.push_back(k);
          k=k+0.1;
        }

        CellProperties  cell_properties_control(voltages1, times);
        CellProperties  cell_properties_mid(voltages2, times);
        CellProperties  cell_properties_endo(voltages3, times);
        CellProperties  cell_properties_LQT(voltages4, times);

        double control_APD = cell_properties_control.GetLastActionPotentialDuration(90);
        double mid_APD = cell_properties_mid.GetLastActionPotentialDuration(90);
        double endo_APD = cell_properties_endo.GetLastActionPotentialDuration(90);
        double LQT_APD = cell_properties_LQT.GetLastActionPotentialDuration(90);

        TS_ASSERT_DELTA(control_APD, 300.4789, 0.1);
        TS_ASSERT_DELTA(mid_APD, 392.1871, 0.1);
        TS_ASSERT_DELTA(endo_APD, 329.2048, 0.1);
        TS_ASSERT_DELTA(LQT_APD , 347.8374, 0.1);
     }
    void TestTysonNovakCellCycleModel() throw(Exception)
    {
        // Set up
        SimulationTime* p_simulation_time = SimulationTime::Instance();
        unsigned num_timesteps = 50;
        p_simulation_time->SetEndTimeAndNumberOfTimeSteps(3.0, num_timesteps);

        double standard_divide_time = 75.19/60.0;

        // Test TysonNovakCellCycleModel methods for a healthy cell
        TysonNovakCellCycleModel* p_cell_model = new TysonNovakCellCycleModel;
        p_cell_model->SetBirthTime(p_simulation_time->GetTime());

        TS_ASSERT_EQUALS(p_cell_model->CanCellTerminallyDifferentiate(), false);

        MAKE_PTR(WildTypeCellMutationState, p_healthy_state);
        MAKE_PTR(StemCellProliferativeType, p_stem_type);

        CellPtr p_cell(new Cell(p_healthy_state, p_cell_model));
        p_cell->SetCellProliferativeType(p_stem_type);
        p_cell->InitialiseCellCycleModel();
        p_cell_model->SetDt(0.1/60.0);

        /*
         * For coverage, we create another cell-cycle model that is identical except that we
         * manually pass in an ODE solver. In this case, our ODE solver (BackwardEulerIvpOdeSolver)
         * is the same type as the solver used by the cell-cycle model if no solver is provided
         * (unless CVODE is used), so our results should be identical.
         */
        boost::shared_ptr<CellCycleModelOdeSolver<TysonNovakCellCycleModel, BackwardEulerIvpOdeSolver> >
            p_solver(CellCycleModelOdeSolver<TysonNovakCellCycleModel, BackwardEulerIvpOdeSolver>::Instance());
        p_solver->SetSizeOfOdeSystem(6);
        p_solver->Initialise();

        TysonNovakCellCycleModel* p_other_cell_model = new TysonNovakCellCycleModel(p_solver);
        p_other_cell_model->SetBirthTime(p_simulation_time->GetTime());
        // Timestep for non-adaptive solvers defaults to 0.0001
        TS_ASSERT_EQUALS(p_other_cell_model->GetDt(), 0.0001);
        p_other_cell_model->SetDt(0.1/60.0);

        CellPtr p_other_cell(new Cell(p_healthy_state, p_other_cell_model));
        p_other_cell->SetCellProliferativeType(p_stem_type);
        p_other_cell->InitialiseCellCycleModel();

        // Test the cell is ready to divide at the right time
        for (unsigned i=0; i<num_timesteps/2; i++)
        {
            p_simulation_time->IncrementTimeOneStep();
            double time = p_simulation_time->GetTime();

            bool result = p_cell_model->ReadyToDivide();
            bool other_result = p_other_cell_model->ReadyToDivide();

            if (time > standard_divide_time)
            {
                TS_ASSERT_EQUALS(result, true);
                TS_ASSERT_EQUALS(other_result, true);
            }
            else
            {
                TS_ASSERT_EQUALS(result, false);
                TS_ASSERT_EQUALS(other_result, false);
            }
        }

        // Test ODE solution
        std::vector<double> proteins = p_cell_model->GetProteinConcentrations();
        TS_ASSERT_EQUALS(proteins.size(), 6u);
        TS_ASSERT_DELTA(proteins[0], 0.10000000000000, 1e-2);
        TS_ASSERT_DELTA(proteins[1], 0.98913684535843, 1e-2);
        TS_ASSERT_DELTA(proteins[2], 1.54216806705641, 1e-1);
        TS_ASSERT_DELTA(proteins[3], 1.40562614481544, 2e-2);
        TS_ASSERT_DELTA(proteins[4], 0.67083371879876, 1e-2);
        TS_ASSERT_DELTA(proteins[5], 0.95328206604519, 2e-2);

        std::vector<double> other_proteins = p_other_cell_model->GetProteinConcentrations();
        TS_ASSERT_EQUALS(other_proteins.size(), 6u);
        TS_ASSERT_DELTA(other_proteins[0], 0.10000000000000, 1e-2);
        TS_ASSERT_DELTA(other_proteins[1], 0.98913684535843, 1e-2);
        TS_ASSERT_DELTA(other_proteins[2], 1.54216806705641, 1e-1);
        TS_ASSERT_DELTA(other_proteins[3], 1.40562614481544, 2e-2);
        TS_ASSERT_DELTA(other_proteins[4], 0.67083371879876, 1e-2);
        TS_ASSERT_DELTA(other_proteins[5], 0.95328206604519, 2e-2);

        TS_ASSERT_EQUALS(p_cell_model->ReadyToDivide(),true);

        // For coverage, we also test TysonNovakCellCycleModel methods for a mutant cell
        p_cell_model->ResetForDivision();

        TS_ASSERT_EQUALS(p_cell_model->ReadyToDivide(),false);

        TysonNovakCellCycleModel* p_cell_model2 = static_cast<TysonNovakCellCycleModel*> (p_cell_model->CreateCellCycleModel());

        MAKE_PTR(ApcOneHitCellMutationState, p_mutation);
        CellPtr p_stem_cell_2(new Cell(p_mutation, p_cell_model2));

        TS_ASSERT_EQUALS(p_cell_model2->ReadyToDivide(),false);

        p_stem_cell_2->SetCellProliferativeType(p_stem_type);

        TS_ASSERT_EQUALS(p_cell_model->ReadyToDivide(),false);
        TS_ASSERT_EQUALS(p_cell_model2->ReadyToDivide(),false);

        // Test the cell is ready to divide at the right time
        for (unsigned i=0; i<num_timesteps/2; i++)
        {
            p_simulation_time->IncrementTimeOneStep();
            double time = p_simulation_time->GetTime();

            bool result = p_cell_model->ReadyToDivide();
            bool result2 = p_cell_model2->ReadyToDivide();

            if (time > 2.0* standard_divide_time)
            {
                TS_ASSERT_EQUALS(result, true);
                TS_ASSERT_EQUALS(result2, true);
            }
            else
            {
                TS_ASSERT_EQUALS(result, false);
                TS_ASSERT_EQUALS(result2, false);
            }
        }

        // Test ODE solution
        proteins = p_cell_model->GetProteinConcentrations();
        TS_ASSERT_EQUALS(proteins.size(), 6u);
        TS_ASSERT_DELTA(proteins[0], 0.10000000000000, 1e-2);
        TS_ASSERT_DELTA(proteins[1], 0.98913684535843, 1e-2);
        TS_ASSERT_DELTA(proteins[2], 1.54216806705641, 1e-1);
        TS_ASSERT_DELTA(proteins[3], 1.40562614481544, 1e-1);
        TS_ASSERT_DELTA(proteins[4], 0.67083371879876, 1e-2);
        TS_ASSERT_DELTA(proteins[5], 0.9662, 1e-2);

        // Coverage of AbstractOdeBasedCellCycleModel::SetProteinConcentrationsForTestsOnly()
        std::vector<double> test_results(6);
        for (unsigned i=0; i<6; i++)
        {
            test_results[i] = (double)i;
        }
        p_cell_model->SetProteinConcentrationsForTestsOnly(1.0, test_results);
        proteins = p_cell_model->GetProteinConcentrations();

        for (unsigned i=0; i<6; i++)
        {
            TS_ASSERT_DELTA(proteins[i], test_results[i], 1e-6);
        }
    }
    void TestAlarcon2004OxygenBasedCellCycleModel() throw(Exception)
    {
        // Set up SimulationTime
        SimulationTime* p_simulation_time = SimulationTime::Instance();
        p_simulation_time->SetEndTimeAndNumberOfTimeSteps(30.0, 3);

        // Set up oxygen_concentration
        double oxygen_concentration = 1.0;

         // Create cell-cycle models
        Alarcon2004OxygenBasedCellCycleModel* p_model_1d = new Alarcon2004OxygenBasedCellCycleModel();
        p_model_1d->SetDimension(1);

        Alarcon2004OxygenBasedCellCycleModel* p_model_2d = new Alarcon2004OxygenBasedCellCycleModel();
        p_model_2d->SetDimension(2);

        Alarcon2004OxygenBasedCellCycleModel* p_model_3d = new Alarcon2004OxygenBasedCellCycleModel();
        p_model_3d->SetDimension(3);

        // Create cells
        MAKE_PTR(WildTypeCellMutationState, p_state);
        MAKE_PTR(StemCellProliferativeType, p_stem_type);

        CellPtr p_cell_1d(new Cell(p_state, p_model_1d));
        p_cell_1d->SetCellProliferativeType(p_stem_type);
        p_cell_1d->GetCellData()->SetItem("oxygen", oxygen_concentration);
        p_cell_1d->InitialiseCellCycleModel();

        CellPtr p_cell_2d(new Cell(p_state, p_model_2d));
        p_cell_2d->SetCellProliferativeType(p_stem_type);
        p_cell_2d->GetCellData()->SetItem("oxygen", oxygen_concentration);
        p_cell_2d->InitialiseCellCycleModel();

        CellPtr p_cell_3d(new Cell(p_state, p_model_3d));
        p_cell_3d->SetCellProliferativeType(p_stem_type);
        p_cell_3d->GetCellData()->SetItem("oxygen", oxygen_concentration);
        p_cell_3d->InitialiseCellCycleModel();

        // For coverage, we create another cell-cycle model that is identical to p_model_2d except for the ODE solver
        boost::shared_ptr<CellCycleModelOdeSolver<Alarcon2004OxygenBasedCellCycleModel, RungeKutta4IvpOdeSolver> >
            p_solver(CellCycleModelOdeSolver<Alarcon2004OxygenBasedCellCycleModel, RungeKutta4IvpOdeSolver>::Instance());
        p_solver->Initialise();

        Alarcon2004OxygenBasedCellCycleModel* p_other_model_2d = new Alarcon2004OxygenBasedCellCycleModel(p_solver);
        p_other_model_2d->SetDimension(2);

        CellPtr p_other_cell_2d(new Cell(p_state, p_other_model_2d));
        p_other_cell_2d->SetCellProliferativeType(p_stem_type);
        p_other_cell_2d->GetCellData()->SetItem("oxygen", oxygen_concentration);
        p_other_cell_2d->InitialiseCellCycleModel();

        // Check oxygen concentration is correct in cell-cycle model
        TS_ASSERT_DELTA(p_model_2d->GetProteinConcentrations()[5], 1.0, 1e-5);
        TS_ASSERT_EQUALS(p_model_2d->ReadyToDivide(), false);

        TS_ASSERT_DELTA(p_other_model_2d->GetProteinConcentrations()[5], 1.0, 1e-5);
        TS_ASSERT_EQUALS(p_other_model_2d->ReadyToDivide(), false);

        // Divide the cells
        Alarcon2004OxygenBasedCellCycleModel* p_model_1d_2 = static_cast<Alarcon2004OxygenBasedCellCycleModel*> (p_model_1d->CreateCellCycleModel());
        CellPtr p_cell_1d_2(new Cell(p_state, p_model_1d_2));
        p_cell_1d_2->SetCellProliferativeType(p_stem_type);
        p_cell_1d_2->GetCellData()->SetItem("oxygen", oxygen_concentration);

        Alarcon2004OxygenBasedCellCycleModel* p_model_2d_2 = static_cast<Alarcon2004OxygenBasedCellCycleModel*> (p_model_2d->CreateCellCycleModel());
        CellPtr p_cell_2d_2(new Cell(p_state, p_model_2d_2));
        p_cell_2d_2->SetCellProliferativeType(p_stem_type);
        p_cell_2d_2->GetCellData()->SetItem("oxygen", oxygen_concentration);

        Alarcon2004OxygenBasedCellCycleModel* p_model_3d_2 = static_cast<Alarcon2004OxygenBasedCellCycleModel*> (p_model_3d->CreateCellCycleModel());
        CellPtr p_cell_3d_2(new Cell(p_state, p_model_3d_2));
        p_cell_3d_2->SetCellProliferativeType(p_stem_type);
        p_cell_3d_2->GetCellData()->SetItem("oxygen", oxygen_concentration);

        p_simulation_time->IncrementTimeOneStep();
        TS_ASSERT_EQUALS(p_model_1d->ReadyToDivide(), false);
        TS_ASSERT_EQUALS(p_model_2d->ReadyToDivide(), false);
        TS_ASSERT_EQUALS(p_other_model_2d->ReadyToDivide(), false);
        TS_ASSERT_EQUALS(p_model_3d->ReadyToDivide(), false);

        p_simulation_time->IncrementTimeOneStep();
        TS_ASSERT_EQUALS(p_model_1d->ReadyToDivide(), true)
        TS_ASSERT_EQUALS(p_model_2d->ReadyToDivide(), true)
        TS_ASSERT_EQUALS(p_other_model_2d->ReadyToDivide(), true);
        TS_ASSERT_EQUALS(p_model_3d->ReadyToDivide(), true);

        TS_ASSERT_THROWS_NOTHING(p_model_2d->ResetForDivision());

        // For coverage, create a 1D model
        Alarcon2004OxygenBasedCellCycleModel* p_cell_model3 = new Alarcon2004OxygenBasedCellCycleModel();
        p_cell_model3->SetDimension(1);

        CellPtr p_cell3(new Cell(p_state, p_cell_model3));
        p_cell3->SetCellProliferativeType(p_stem_type);
        p_cell3->GetCellData()->SetItem("oxygen", oxygen_concentration);
        p_cell3->InitialiseCellCycleModel();

        TS_ASSERT_DELTA(p_cell_model3->GetProteinConcentrations()[5], 1.0, 1e-5);
        TS_ASSERT_EQUALS(p_cell_model3->ReadyToDivide(), false);
        p_simulation_time->IncrementTimeOneStep();
        TS_ASSERT_EQUALS(p_cell_model3->ReadyToDivide(), false);
    }