//************************************************************************************************ // Simulation functions //************************************************************************************************ ///////////////////////////////////////////////////////////////////////// // Top level aging function - call appropriate function based on the current stage ///////////////////////////////////////////////////////////////////////// public void age(double deltaTime) { switch (stage) { case K.Stage.A: doStage_A(K.PROBTIMESTEP); break; case K.Stage.B: doStage_B(K.PROBTIMESTEP); break; case K.Stage.C1: doStage_C1(K.PROBTIMESTEP); break; case K.Stage.C2: doStage_C2(K.PROBTIMESTEP); break; case K.Stage.C3: doStage_C3(K.PROBTIMESTEP); break; default: return; } // Record life years and QALYs for current stage. stayInCurrentStage(deltaTime); // See if we have to move to a new stage - and move if we the next stage is new. nextStage = getNextStage(stage, deltaTime); if (nextStage != stage) { moveToNewStage(nextStage); } }
///////////////////////////////////////////////////////////////////////// // moveToNewStage(K.Stage newStage) ///////////////////////////////////////////////////////////////////////// private void moveToNewStage(K.Stage newStage) { stage = newStage; // Update stage to new stage timeInCurrentStage = 0; // Reset timeInCurrentStage to zero alive = (stage != K.deadStage); // Set alive appropriately if (!alive) { ageAtDeath = ageNow; // If subject died, then set ageAtDeath } }
///////////////////////////////////////////////////////////////////////// // initializePerson - Sets ///////////////////////////////////////////////////////////////////////// public void initializePerson() { // Acumulator values lifeYears = 0; qalyTotal = 0; ageAtDeath = 0; // Status values timeSinceSimStart = 0; stage = K.initStage; timeInCurrentStage = 0; firstSimCycle = true; relapseStatus = K.RelapseHx.NEVER_RELAPSED; // Half timestep correction age(K.DELTA_TIME * 0.5); // Flag that the subject is on the first cycle through the model firstSimCycle = false; }
///////////////////////////////////////////////////////////////////////// // Once the transition probabilities have been computed for the current state, figure out // which state will be next and do the transition, as needed. ///////////////////////////////////////////////////////////////////////// private K.Stage getNextStage(K.Stage currentStage, double myTimeStep) { // If all the transition probabilities are zero, stay in the current stage and return immediately if (probToA + probToB + probToC1 + probToC2 + probToC3 + probToD <= K.tinyProb) { return(currentStage); } // If any of transition probabilities = 1.0, automatically proceed to that state if (probToA >= 1) { return(K.Stage.A); } if (probToB >= 1) { return(K.Stage.B); } if (probToC1 >= 1) { return(K.Stage.C1); } if (probToC2 >= 1) { return(K.Stage.C2); } if (probToC3 >= 1) { return(K.Stage.C3); } if (probToD >= 1) { return(K.Stage.D); } // Calculate corresponding rates that match the duration of myTimeStep. rateToA = myTimeStep * Utility.rateFromProb(probToA); rateToB = myTimeStep * Utility.rateFromProb(probToB); rateToC1 = myTimeStep * Utility.rateFromProb(probToC1); rateToC2 = myTimeStep * Utility.rateFromProb(probToC2); rateToC3 = myTimeStep * Utility.rateFromProb(probToC3); rateToD = myTimeStep * Utility.rateFromProb(probToD); // Adjust rates to account for probability time period in K file. This step inflates the rate up // to its value for one year. rateToA = rateToA / K.PROBTIMESTEP; rateToB = rateToB / K.PROBTIMESTEP; rateToC1 = rateToC1 / K.PROBTIMESTEP; rateToC2 = rateToC2 / K.PROBTIMESTEP; rateToC3 = rateToC3 / K.PROBTIMESTEP; rateToD = rateToD / K.PROBTIMESTEP; // Convert these rates back to probabilies probToA = Utility.probFromRate(rateToA); probToB = Utility.probFromRate(rateToB); probToC1 = Utility.probFromRate(rateToC1); probToC2 = Utility.probFromRate(rateToC2); probToC3 = Utility.probFromRate(rateToC3); probToD = Utility.probFromRate(rateToD); // Finally, set the probability of remaining in the current state equal to 1 minus the probability of // proceeding to any of the other states. switch (currentStage) { case K.Stage.A: probToA = 1 - (probToB + probToC1 + probToC2 + probToC3 + probToD); break; case K.Stage.B: probToB = 1 - (probToA + probToC1 + probToC2 + probToC3 + probToD); break; case K.Stage.C1: probToC1 = 1 - (probToA + probToB + probToC2 + probToC3 + probToD); break; case K.Stage.C2: probToC2 = 1 - (probToA + probToB + probToC1 + probToC3 + probToD); break; case K.Stage.C3: probToC3 = 1 - (probToA + probToB + probToC1 + probToC2 + probToD); break; case K.Stage.D: probToD = 1 - (probToA + probToB + probToC1 + probToC2 + probToC3); break; default: probToD = 1 - (probToA + probToB + probToC1 + probToC2 + probToC3); break; } if (probToA < 0 || probToB < 0 || probToC1 < 0 || probToC2 < 0 || probToC3 < 0 || probToD < 0) { Console.WriteLine("Probability less than zero error. Hit any key to exit program."); Console.ReadKey(); Environment.Exit(0); } double randomNum = MyRandom.RandomProvider.Next(); K.Stage returnVal = currentStage; if (randomNum <= probToA) { returnVal = K.Stage.A; return(returnVal); } if (randomNum <= probToA + probToB) { returnVal = K.Stage.B; return(returnVal); } if (randomNum <= probToA + probToB + probToC1) { returnVal = K.Stage.C1; return(returnVal); } if (randomNum <= probToA + probToB + probToC1 + probToC2) { returnVal = K.Stage.C2; return(returnVal); } if (randomNum <= probToA + probToB + probToC1 + probToC2 + probToC3) { returnVal = K.Stage.C3; return(returnVal); } if (randomNum <= probToA + probToB + probToC1 + probToC2 + probToC3 + probToD) { returnVal = K.Stage.D; return(returnVal); } return(returnVal); }