-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathStateUpdater.cpp
More file actions
8084 lines (7308 loc) · 380 KB
/
Copy pathStateUpdater.cpp
File metadata and controls
8084 lines (7308 loc) · 380 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include "include.h"
/** Constructor takes in the patient object */
StateUpdater::StateUpdater(Patient *patient) :
patient(patient)
{
}
/** Destructor is empty, no cleanup required */
StateUpdater::~StateUpdater(void) {
}
/**
* \brief Virtual function to perform the initial updates upon patient creation.
* Sets the simContext, runStats, and tracer to match that of this->patient */
void StateUpdater::performInitialUpdates() {
// Copy the pointers to the simContext, runStats, and tracer objects
this->simContext = this->patient->simContext;
this->runStats = this->patient->runStats;
this->costStats = this->patient->costStats;
this->tracer = this->patient->tracer;
}
/**
* \brief Virtual function to perform all updates for a simulated month.
* Empty for now, no actions to perform if child does not override
* */
void StateUpdater::performMonthlyUpdates() {
// Empty for now, no actions to perform if child does not override
}
/** Virtual function changes the inputs the updater uses to determine disease progression -- to be used primarily by the transmission model */
void StateUpdater::setSimContext(SimContext *newSimContext){
this->simContext = newSimContext;
}
/** \brief initializePatient initializes the patient's basic state
* \param patientNum an integer argument that assigns the patient a (hopefully unique!) identifier
* \param tracingEnabled a bool argument that is true if this patient is to be output in the trace file
*
* This function initializes patient->monthNum to the initial month number (0 unless otherwise specified by the transmission model),
* all costs to 0, all life months (LMs) and discounted LMs to 0, the discount factor to 1, and marks the patient as alive */
void StateUpdater::initializePatient(int patientNum, bool tracingEnabled) {
patient->generalState.patientNum = patientNum;
patient->generalState.tracingEnabled = tracingEnabled;
patient->generalState.monthNum = patient->generalState.initialMonthNum;
patient->generalState.costsDiscounted = 0;
patient->artState.costsART = 0;
patient->monitoringState.costsCD4Testing = 0;
patient->monitoringState.costsHVLTesting = 0;
patient->monitoringState.costsPrEP = 0;
patient->monitoringState.costsHIVTesting = 0;
patient->generalState.LMsDiscounted = 0;
patient->generalState.qualityAdjustLMsDiscounted = 0;
patient->generalState.LMsUndiscounted = 0;
for (int i = 0; i < SimContext::NUM_DISCOUNT_RATES; i++){
patient->generalState.multDiscCosts[i] = 0;
patient->generalState.multDiscLMs[i] = 0;
patient->generalState.multDiscQALMs[i] = 0;
patient->generalState.multDiscFactorCost[i] = 1.0;
patient->generalState.multDiscFactorBenefit[i] = 1.0;
}
patient->generalState.discountFactor = 1.0;
patient->generalState.loggedPatientOIs = false;
patient->diseaseState.isAlive = true;
patient->diseaseState.useHEUMortality = false;
patient->diseaseState.neverExposed = false;
}
/** \brief setPatientAgeGender set the patients age and gender
* \param gender a SimContext::GENDER_TYPE (male or female)
* \param ageMonths an integer specifying the patient's initial age
*
* The patient's age categories are also set using helper functions
* \see StateUpdater::getAgeCategoryHIVInfection(int)
* \see StateUpdater::getAgeCategoryCHRMs(int)
* \see StateUpdater::getAgeCategoryPediatrics(int) */
void StateUpdater::setPatientAgeGender(SimContext::GENDER_TYPE gender, int ageMonths) {
patient->generalState.gender = gender;
patient->generalState.ageMonths = ageMonths;
patient->generalState.ageCategoryHIVInfection = getAgeCategoryHIVInfection(ageMonths);
patient->generalState.ageCategoryHeterogeneity = getAgeCategoryHeterogeneity(ageMonths);
patient->generalState.ageCategoryCost = getAgeCategoryCost(ageMonths);
patient->pedsState.ageCategoryCD4Metric = getAgeCategoryCD4Metric(ageMonths);
patient->pedsState.ageCategoryPediatrics = getAgeCategoryPediatrics(ageMonths);
patient->pedsState.ageCategoryPedsCost = getAgeCategoryPediatricsCost(ageMonths);
patient->pedsState.ageCategoryPedsARTCost = getAgeCategoryPediatricsARTCost(ageMonths);
} /* end setPatientAgeGender */
/** \brief setInitialARTState initializes the patients ARTState object
*
* Initializes all ART variables: by default, isOnART and hasTakenART are false and number of observed
* failures is 0. The CD4 envelope and CD4 percentage envelope is set to non-active, all
* "number of months since" data relating to ART is set to 0, and all toxicity effects are cleared.
**/
void StateUpdater::setInitialARTState() {
patient->artState.isOnART = false;
patient->artState.applyARTEffect = false;
patient->artState.isOnResupp = false;
patient->artState.numFailedResupp = 0;
patient->artState.hasTakenART = false;
patient->artState.numObservedFailures = 0;
patient->artState.hadSuccessOnRegimen = false;
patient->artState.overallCD4Envelope.isActive = false;
patient->artState.indivCD4Envelope.isActive = false;
patient->artState.overallCD4PercentageEnvelope.isActive = false;
patient->artState.indivCD4PercentageEnvelope.isActive = false;
patient->artState.hadPrevToxicity = false;
patient->artState.monthOfNewCD4MultArtFail=0;
patient->artState.currCD4MultArtFail=1.0;
for (int i = 0; i < SimContext::OI_NUM; i++) {
patient->artState.numObservedOIsSinceFailOrStopART[i] = 0;
}
for (int i = 0; i < SimContext::ART_NUM_LINES; i++) {
patient->artState.numMonthsOnUnsuccessfulByRegimen[i] = 0;
patient->artState.hasTakenARTRegimen[i] = false;
}
for (int i = 0; i < SimContext::HVL_NUM_STRATA; i++) {
patient->artState.numMonthsOnUnsuccessfulByHVL[i] = 0;
}
patient->artState.activeToxicityEffects.clear();
} /* end setInitialARTState */
/**
* \brief setInitialProphState initializes the patients ProphState object
*
* Initializes the state to reflect that no prophylaxis drugs are currently taken
* or have a history of being taken
* */
void StateUpdater::setInitialProphState() {
// Initialize state to reflect that no drugs are currently taken and
patient->prophState.currTotalNumProphsOn = 0;
for (int i = 0; i < SimContext::OI_NUM; i++) {
patient->prophState.isOnProph[i] = false;
for (int j = 0; j < SimContext::PROPH_NUM_TYPES; j++){
patient->prophState.hasTakenProph[i][j] = false;
}
}
} /* end setInitialProphState */
/** \brief setInitialTBProphState sets the initial TB proph state to not be on any TB prophs
*
* Also sets the patient to not be scheduled to start any TB proph
* */
void StateUpdater::setInitialTBProphState() {
patient->tbState.isOnProph = false;
patient->tbState.isScheduledForProph = false;
for(int i = 0; i < SimContext::TB_NUM_PROPHS; i++){
patient->tbState.numProphStarts[i] = 0;
}
patient->tbState.hasCompletedProph = false;
patient->tbState.isEligibleForProph = false;
patient->tbState.hasRolledEligibleForProph = false;
} /* end setInitialTBProphState */
/** \brief setInitialTBTreatmentState sets the initial TB treatment state to not be on TB treatment
*
* Also sets the patient not to be scheduled to start any TB treatment and determines initial TB treatment history for those who start the model with such a history
* */
void StateUpdater::setInitialTBTreatmentState() {
patient->tbState.isScheduledForTreatment = false;
patient->tbState.isOnTreatment = false;
patient->tbState.isOnEmpiricTreatment = false;
patient->tbState.hasIncompleteTreatment = false;
patient->tbState.everHadNonInitialTreatmentOrEmpiric = false;
patient->tbState.willIncreaseResistanceUponDefault = false;
patient->tbState.monthOfMortEfficacyStop = SimContext::NOT_APPL;
for(int i = 0; i < SimContext::TB_NUM_UNFAVORABLE; i++)
patient->tbState.hasUnfavorableOutcome[i] = false;
if(patient->tbState.observedHistActiveTBAtEntry){
patient->tbState.everOnTreatmentOrEmpiric = true;
patient->tbState.hasStoppedTreatmentOrEmpiric = true;
// Treatment stop or transition to treatment default TB state must have occurred at least 1 month ago to keep outcomes synced with those who stop treatment after model entry
double monthsSinceStopMean = simContext->getTBInputs()->monthsSinceInitTreatStopMean;
double monthsSinceStopStdDev = simContext->getTBInputs()->monthsSinceInitTreatStopStdDev;
int monthsSinceInitTreatStop = (int) (CepacUtil::getRandomGaussian(monthsSinceStopMean, monthsSinceStopStdDev, 13020, patient) + 0.5);
if(patient->tbState.currTrueTBDiseaseState == SimContext::TB_STATE_TREAT_DEFAULT){
patient->tbState.everCompletedTreatmentOrEmpiric = false;
if(monthsSinceInitTreatStop < simContext->getTBInputs()->monthsToLongTermEffectsLTFU + 1){
monthsSinceInitTreatStop = simContext->getTBInputs()->monthsToLongTermEffectsLTFU + 1;
}
}
// Previously Treated
else{
patient->tbState.everCompletedTreatmentOrEmpiric = true;
if(monthsSinceInitTreatStop < 1){
monthsSinceInitTreatStop = 1;
}
}
patient->tbState.monthOfInitialTreatmentStop = -1 * monthsSinceInitTreatStop;
patient->tbState.monthOfTreatmentOrEmpiricStop = patient->tbState.monthOfInitialTreatmentStop;
// Determine the initial TB treatment line they stopped before model entry - the assumption is made that their TB strain was identified correctly because they were successfully cured by this treatment
int lineNum = SimContext::TB_NUM_TREATMENTS - 1;
SimContext::TB_STRAIN obsvStrain = patient->tbState.currTrueTBResistanceStrain;
double randNum = CepacUtil::getRandomDouble(13021, patient);
for (int i = 0; i < SimContext::TB_NUM_TREATMENTS; i++) {
if (randNum < simContext->getTBInputs()->TBTreatmentProbInitialLine[0][obsvStrain][i]) {
lineNum = i;
break;
}
randNum -= simContext->getTBInputs()->TBTreatmentProbInitialLine[0][obsvStrain][i];
}
patient->tbState.mostRecentTreatNum = lineNum;
}
else{
patient->tbState.everOnTreatmentOrEmpiric = false;
patient->tbState.hasStoppedTreatmentOrEmpiric = false;
patient->tbState.everCompletedTreatmentOrEmpiric = false;
}
} /* end setInitialTBTreatmentState */
/** \brief incrementMonth increments the simulation month number and patient age by 1
*
* Also resets the age categories using helper functions
* \see StateUpdater::getAgeCategoryHIVInfection(int)
* \see StateUpdater::getAgeCategoryCHRMs(int)
* \see StateUpdater::getAgeCategoryPediatrics(int)
*
* */
void StateUpdater::incrementMonth() {
patient->generalState.monthNum++;
patient->generalState.ageMonths++;
// Update the HIV infection and pediatrics age category
patient->generalState.ageCategoryHIVInfection = getAgeCategoryHIVInfection(patient->generalState.ageMonths);
patient->generalState.ageCategoryHeterogeneity = getAgeCategoryHeterogeneity(patient->generalState.ageMonths);
patient->generalState.ageCategoryCost = getAgeCategoryCost(patient->generalState.ageMonths);
patient->pedsState.ageCategoryCD4Metric = getAgeCategoryCD4Metric(patient->generalState.ageMonths);
patient->pedsState.ageCategoryPediatrics = getAgeCategoryPediatrics(patient->generalState.ageMonths);
patient->pedsState.ageCategoryPedsCost = getAgeCategoryPediatricsCost(patient->generalState.ageMonths);
patient->pedsState.ageCategoryPedsARTCost = getAgeCategoryPediatricsARTCost(patient->generalState.ageMonths);
} /* end incrementMonth */
/** \brief incrementDiscountFactor adjusts the discounting factor for each new month
*
* \param amount a double, the inverse of which is multiplied by the current discount factor
*
* \f$DiscountFactor_{new} = \frac{1}{amount} * DiscountFactor_{old}\f$
* */
void StateUpdater::incrementDiscountFactor(double amount) {
patient->generalState.discountFactor *= (1 / amount);
} /* end incrementDiscountFactor */
/** \brief incrementMultDiscountFactor adjusts the discounting factor for each new month when using multiple discount factors
*
* \param amount a double, the inverse of which is multiplied by the current discount factor
*
* \f$DiscountFactor_{new} = \frac{1}{amount} * DiscountFactor_{old}\f$
* */
void StateUpdater::incrementMultDiscountFactor(double amountCost, double amountBenefit, int i) {
patient->generalState.multDiscFactorCost[i] *= (1 / amountCost);
patient->generalState.multDiscFactorBenefit[i] *= (1/ amountBenefit);
} /* end incrementDiscountFactor */
/** \brief resetQOL resets the quality of life factor back to the background value for the patient's age in years and gender
**/
void StateUpdater::resetQOL(){
int ageYears = patient->generalState.ageMonths / 12;
SimContext::GENDER_TYPE gender = patient->generalState.gender;
patient->generalState.QOLValue = simContext->getQOLInputs()->backgroundQOL[gender][ageYears];
}/*end resetQOL */
/** \brief accumulateQOLModifier accumulates the QOL in one of 4 ways, defined by user inputs: by multiplying the new factor with the existing one (MULT), subtracting the new factor from the existing one (ADD), taking the minimum of the old one and the new one (MIN), or adding the new factor to the existing one (MARGINAL)
*
* \param amount a double indicating the new factor to accumulate the QOL by
*
* \f$QOL_{new} = QOL_{old} * amount\f$
* \f$QOL_{new} = QOL_{old} - amount\f$
* \f$QOL_{new} = min(QOL_{old}, amount)\f$
* \f$QOL_{new} = QOL_{old} + amount\f$
* */
void StateUpdater::accumulateQOLModifier(double amount) {
if(simContext->getQOLInputs()->QOLCalculationType==SimContext::MULT){
patient->generalState.QOLValue *= amount;
}
if(simContext->getQOLInputs()->QOLCalculationType==SimContext::ADD){
patient->generalState.QOLValue -= amount;
}
if(simContext->getQOLInputs()->QOLCalculationType==SimContext::MIN){
patient->generalState.QOLValue = min(patient->generalState.QOLValue, amount);
}
if(simContext->getQOLInputs()->QOLCalculationType==SimContext::MARGINAL){
patient->generalState.QOLValue += amount;
}
} /* end accumulateQOLModifier */
/** \brief finalizeQOLValue checks that the patient's QOL value is between 0 and 1 and bounds it if necessary before it is used
*
**/
void StateUpdater::finalizeQOLValue(){
if(patient->generalState.QOLValue < 0){
patient->generalState.QOLValue = 0;
}
if(patient->generalState.QOLValue > 1){
patient->generalState.QOLValue = 1;
}
} /* end finalizeQOLValue */
/** \brief setHIVIncReducMultiplier sets the current HIV incidence reduction multiplier if incidence reduction is enabled
* \param reducMult a double indicating the multiplier to be applied for the current time period to the patient's monthly HIV infection probability
*
*/
void StateUpdater::setHIVIncReducMultiplier(double reducMult){
patient->monitoringState.HIVIncReducMultiplier = reducMult;
}
/** \brief setInfectedHIVState sets the patient to the specified HIV infection state and updates statistics
*
* \param infectedState a SimContext::HIV_INF (HIV infection state) to set the patient to
* \param isInitial a bool marking whether or not this is an initial (i.e. prevalent) case or not (i.e. incident case)
* \param resetTimeOfInfection if infectedState is not negative, this bool marks whether the HIV infection occurred this month (not shifting between HIV+ states)
* \param isHighRisk a bool defaulting to true marking whether or not the patient is high risk;
* this only matters for people who start the model HIV-negative and draw from a different incident
* infection distribution/ PrEP inputs; others default to true
* All statistics counting different infection types/times are incremented in this function
**/
void StateUpdater::setInfectedHIVState(SimContext::HIV_INF infectedState, bool isInitial, bool resetTimeOfInfection, bool isHighRisk) {
patient->diseaseState.infectedHIVState = infectedState;
if (infectedState != SimContext::HIV_INF_NEG) {
// Currently HIV_POS is identical to HIV_INF, but with the first value HIV_INF_NEG removed - if either enum changes this will need to change
patient->diseaseState.infectedHIVPosState = (SimContext::HIV_POS) (infectedState-1);
if (resetTimeOfInfection)
patient->diseaseState.monthOfHIVInfection = patient->generalState.monthNum;
}
if (infectedState == SimContext::HIV_INF_ACUTE_SYN) {
patient->diseaseState.monthOfAcuteToChronicHIV = patient->generalState.monthNum + simContext->getHIVTestInputs()->monthsFromAcuteToChronic;
}
if (isInitial) {
//Note that isHIghRiskForHIV is not valid for prevalent HIV cases
if (infectedState == SimContext::HIV_INF_NEG) {
patient->diseaseState.isPrevalentHIVCase = false;
patient->monitoringState.isHighRiskForHIV = isHighRisk;
}
else {
patient->diseaseState.isPrevalentHIVCase = true;
}
}
// Update statistics for a prevalent or incident infection
if (isInitial) {
SimContext::HIV_EXT_INF extInfectedState = (SimContext::HIV_EXT_INF) infectedState;
if ((infectedState == SimContext::HIV_INF_NEG) && !isHighRisk)
extInfectedState = SimContext::HIV_EXT_INF_NEG_LO;
runStats->hivScreening.numPatientsInitialHIVState[extInfectedState]++;
if (infectedState == SimContext::HIV_INF_NEG) {
runStats->hivScreening.numHIVNegativeAtInit++;
}
else if (infectedState == SimContext::HIV_INF_SYMP_CHR_POS) {
runStats->hivScreening.numPatientsInitialHIVState[SimContext::HIV_INF_ASYMP_CHR_POS]--;
}
else {
runStats->hivScreening.numPrevalentCases++;
}
}
else if (infectedState == SimContext::HIV_INF_ACUTE_SYN) {
runStats->hivScreening.numIncidentCases++;
if(patient->monitoringState.hasPrEP){
runStats->hivScreening.numIncidentCasesByPrEPState[SimContext::HIV_POS_ON_PREP]++;
}
else if(patient->monitoringState.isPrEPDropout){
runStats->hivScreening.numIncidentCasesByPrEPState[SimContext::HIV_POS_PREP_DROPOUT]++;
}
else if(patient->monitoringState.prepStoppedMaxAge){
runStats->hivScreening.numIncidentCasesByPrEPState[SimContext::HIV_POS_PREP_AGESTOP]++;
}
else{
runStats->hivScreening.numIncidentCasesByPrEPState[SimContext::HIV_POS_NEVER_PREP]++;
}
runStats->hivScreening.monthsToInfectionSum += patient->generalState.monthNum;
runStats->hivScreening.monthsToInfectionSumSquares += patient->generalState.monthNum * patient->generalState.monthNum;
RunStats::TimeSummary *currTime = getTimeSummaryForUpdate();
if (currTime) {
currTime->numIncidentHIVInfections++;
if (simContext->getCohortInputs()->useDynamicTransm && simContext->getCohortInputs()->updateDynamicTransmInc)
currTime->dynamicNumIncidentHIVInfections++;
}
}
} /* end setInfectedHIVState */
/** \brief setInfectedPediatricsHIVState sets the pediatrics HIV state
*
* \param hivState a SimContext::PEDS_HIV_STATE (HIV infection state for pediatrics) that the patient is set to
* \param isInitial a bool that specifies if this is called during initialzation
*
**/
void StateUpdater::setInfectedPediatricsHIVState(SimContext::PEDS_HIV_STATE hivState, bool isInitial) {
patient->diseaseState.infectedPediatricsHIVState = hivState;
if (hivState != SimContext::PEDS_HIV_NEG)
patient->diseaseState.useHEUMortality = false;
if (hivState == SimContext::PEDS_HIV_POS_PP){
RunStats::TimeSummary *currTime = getTimeSummaryForUpdate();
if (currTime){
currTime->numIncidentPPInfections++;
}
}
if (isInitial){
runStats->initialDistributions.numInitialPediatrics[patient->diseaseState.infectedPediatricsHIVState][patient->pedsState.maternalStatus]++;
if(hivState == SimContext::PEDS_HIV_NEG){
// update exposure status if the patient is HIV-negative
if(patient->pedsState.motherInfectedDuringDelivery[SimContext::MOM_CHRONIC_PREGNANCY]){
runStats->hivScreening.numHIVExposed[SimContext::MOM_CHRONIC_PREGNANCY]++;
if(simContext->getPedsInputs()->exposedUninfectedDefsEarly[SimContext::MOM_CHRONIC_PREGNANCY] && !(simContext->getPedsInputs()->exposedUninfectedDefsEarly[SimContext::MOM_ON_ART_UNEXPOSED] && patient->pedsState.motherOnARTInitially))
patient->diseaseState.useHEUMortality = true;
}
else if(patient->pedsState.motherInfectedDuringDelivery[SimContext::MOM_ACUTE_PREGNANCY]){
runStats->hivScreening.numHIVExposed[SimContext::MOM_ACUTE_PREGNANCY]++;
if(simContext->getPedsInputs()->exposedUninfectedDefsEarly[SimContext::MOM_ACUTE_PREGNANCY] && !(simContext->getPedsInputs()->exposedUninfectedDefsEarly[SimContext::MOM_ON_ART_UNEXPOSED] && patient->pedsState.motherOnARTInitially))
patient->diseaseState.useHEUMortality = true;
}
}
}
} /* end setInfectedPediatricsHIVState */
/** \brief setMaternalHIVState sets the maternal HIV state for pediatrics at initiation and the maternal transition from acute to chronic. See rollForMaternalInfection() to update maternal HIV state for incident cases.
*
* \param momHIVState a SimContext::PEDS_MATERNAL_HIV_STATE that specifies the (pediatric) patient's mother's HIV status
* \param motherBecameInfected a bool that specifies if the mother's state is HIV+
* \param isInit a bool that specifies if this is called during initialzation - if not, it is the maternal transition from acute to chronic
**/
void StateUpdater::setMaternalHIVState(SimContext::PEDS_MATERNAL_STATUS momHIVState, bool motherBecameInfected, bool isInit) {
patient->pedsState.maternalStatus = momHIVState;
if(motherBecameInfected){
patient->pedsState.monthOfMaternalHIVInfection = patient->generalState.monthNum;
// mother was infected during pregnancy
if(isInit){
if((momHIVState == SimContext::PEDS_MATERNAL_STATUS_CHR_LOW) || (momHIVState == SimContext::PEDS_MATERNAL_STATUS_CHR_HIGH)){
patient->pedsState.motherInfectedDuringDelivery[SimContext::MOM_CHRONIC_PREGNANCY] = true;
}
else if (momHIVState == SimContext::PEDS_MATERNAL_STATUS_ACUTE){
patient->pedsState.motherInfectedDuringDelivery[SimContext::MOM_ACUTE_PREGNANCY] = true;
}
}
}
} /* end setMaternalHIVState */
/** \brief setInitalMaternalState sets the maternal HIV state for pediatrics at init
*
**/
void StateUpdater::setInitialMaternalState() {
patient->pedsState.isMotherAlive = true;
for (int i = 0; i < SimContext::MOM_ACUTE_BREASTFEEDING; i++){
patient->pedsState.motherInfectedDuringDelivery[i] = false;
}
patient->pedsState.motherInfectedDuringBF = false;
patient->pedsState.breastfeedingStoppedEarly = false;
} /* end setInitialMaternalState */
/* \brief rollForMaternalInfection determines whether an HIV-negative mother becomes infected with HIV, and if so, updates the patient and maternal states */
void StateUpdater::rollForMaternalInfection() {
double randNum = CepacUtil::getRandomDouble(90105, patient);
if (randNum < simContext->getPedsInputs()->probMotherIncidentInfection[SimContext::PEDS_MATERNAL_STATUS_NEG]) {
patient->pedsState.maternalStatus = SimContext::PEDS_MATERNAL_STATUS_ACUTE;
patient->pedsState.monthOfMaternalHIVInfection = patient->generalState.monthNum;
if (patient->pedsState.breastfeedingStatus != SimContext::PEDS_BF_REPL){
patient->pedsState.motherInfectedDuringBF = true;
if(patient->diseaseState.infectedPediatricsHIVState == SimContext::PEDS_HIV_NEG){
// add to the aggregate totals for patients who have ever been exposed uninfected
runStats->hivScreening.numHIVExposed[SimContext::MOM_ACUTE_BREASTFEEDING]++;
// update exposure status for mortality purposes if enabled
if(simContext->getPedsInputs()->exposedUninfectedDefsEarly[SimContext::MOM_ACUTE_BREASTFEEDING]) {
patient->diseaseState.useHEUMortality = true;
}
}
}
// if the patient is HIV-negative and already replacement feeding, the patient was never exposed to HIV - this ensures we count patients who stopped breastfeeding the same month the mother was infected
else if(patient->diseaseState.infectedPediatricsHIVState == SimContext::PEDS_HIV_NEG){
if(!patient->diseaseState.neverExposed){
patient->diseaseState.neverExposed = true;
// add to the aggregate totals for patients who are never exposed to HIV by their mothers
runStats->hivScreening.numNeverHIVExposed++;
}
}
if (patient->generalState.tracingEnabled) {
tracer->printTrace(1, "**%d MATERNAL HIV INFECTION\n", patient->generalState.monthNum);
}
}
}
/* end rollForMaternalInfection */
/** \brief setMaternalStatusKnown sets the maternal HIV state for pediatrics
*
* \param isKnown a bool that specifies whether the mother knows about her status
**/
void StateUpdater::setMaternalStatusKnown(bool isKnown) {
patient->pedsState.maternalStatusKnown = isKnown;
}
/** \brief setMaternalARTSTatus sets whether the mother is on ART
*
* \param isOnART is a bool for whether the mother is on ART
* \param isSuppressed is a bool for whether the mother is on Suppressed ART
* \param isInitial is a bool for whether this is called at initiation and therefore refers to the mother's ART status in pregnancy
* \param suppressionKnown is a bool for whether the mother's suppression status is known (known suppressed or known not suppressed)
**/
void StateUpdater::setMaternalARTStatus(bool isOnART, bool isSuppressed, bool suppressionKnown, bool isInitial) {
patient->pedsState.motherOnART = isOnART;
patient->pedsState.motherOnSuppressedART = isSuppressed;
patient->pedsState.motherSuppressionKnown = suppressionKnown;
if(isInitial){
patient->pedsState.motherOnARTInitially = isOnART;
patient->pedsState.motherOnSuppressedARTInitially = isSuppressed;
patient->pedsState.motherSuppressionKnownInitially = suppressionKnown;
}
}
/** \brief setMaternalHVLStatus sets whether the mother is lowHVl or high HVL
* \param isLow is a bool for whether the mother is LowHVL
* \param isInitial is a bool for whether this is called at initiation and therefore refers to the mother's HVL during pregnancy
*
**/
void StateUpdater::setMaternalHVLStatus(bool isLow, bool isInitial){
patient->pedsState.motherLowHVL = isLow;
if (isInitial)
patient->pedsState.motherLowHVLInitially = isLow;
}
/** \brief updatePedsNeverExposed performs updates on HIV negative children who were never exposed to HIV
*
* \param atDeath a bool defaulting to false for whether we are logging a patient at death; they were never exposed if they die during breastfeeding from an HIV negative mother.
*/
void StateUpdater::updatePedsNeverExposed(bool atDeath){
// Check whether the child qualifies as never having been exposed to HIV
if(patient->pedsState.maternalStatus == SimContext::PEDS_MATERNAL_STATUS_NEG){
// if they die while breastfeeding from an HIV negative mother, they were never exposed and are counted in the exposure outputs as such
if(atDeath){
if(patient->pedsState.breastfeedingStatus != SimContext::PEDS_BF_REPL){
patient->diseaseState.neverExposed = true;
runStats->hivScreening.numNeverHIVExposed++;
}
}
else if(!patient->diseaseState.neverExposed && (patient->pedsState.breastfeedingStatus == SimContext::PEDS_BF_REPL)){
patient->diseaseState.neverExposed = true;
runStats->hivScreening.numNeverHIVExposed++;
}
}
}/* end updatePedsNeverExposed */
/** \brief updatePedsHIVExposureStats performs statistics on whether HIV negative children are exposed or unexposed to HIV
*
* \param momHIVState a SimContext::PEDS_MATERNAL_HIV_STATE that specifies the (pediatric) patient's mother's HIV status
*/
void StateUpdater::updatePedsHIVExposureStats(SimContext::PEDS_MATERNAL_STATUS momHIVState){
RunStats::TimeSummary *currTime = getTimeSummaryForUpdate();
// Update statistics on HIV exposure
if(patient->diseaseState.neverExposed){
if(currTime)
currTime->numNeverHIVExposed++;
}
else if(momHIVState == SimContext::PEDS_MATERNAL_STATUS_ACUTE){
if(patient->pedsState.breastfeedingStatus != SimContext::PEDS_BF_REPL){
if(currTime)
currTime->numHIVExposedUninf[SimContext::EXPOSED_BF_MOM_ACUTE]++;
}
}
else if ((momHIVState == SimContext::PEDS_MATERNAL_STATUS_CHR_LOW || momHIVState == SimContext::PEDS_MATERNAL_STATUS_CHR_HIGH)) {
if(patient->pedsState.breastfeedingStatus != SimContext::PEDS_BF_REPL){
if(currTime)
currTime->numHIVExposedUninf[SimContext::EXPOSED_BF_MOM_CHRONIC]++;
}
}
}/* end updatePedsHIVExposureStats */
/** \brief setBreastfeedingStatus for pediatrics and updates statistics
*
* \param bfType a SimContext::PEDS_BF_TYPE to set the breastfeeding status to
**/
void StateUpdater::setBreastfeedingStatus(SimContext::PEDS_BF_TYPE bfType) {
patient->pedsState.breastfeedingStatus = bfType;
if(bfType==SimContext::PEDS_BF_REPL){
patient->pedsState.monthOfReplacementFeedingStart=patient->generalState.monthNum;
if(patient->generalState.ageMonths < SimContext::PEDS_SAFE_BF_STOP_AGE)
patient->pedsState.breastfeedingStoppedEarly = true;
}
} /* end setBreastfeedingStatus */
/** \brief setBreastfeedingStopAge sets the age at which to stop breastfeeding for pediatrics
*
* \param stopAge an int for age at which to end bf
**/
void StateUpdater::setBreastfeedingStopAge(int stopAge) {
if (stopAge < 0)
stopAge = 0;
// Breastfeeding must stop before late childhood
if (stopAge > 60)
stopAge = 60;
patient->pedsState.breastfeedingStopAge = stopAge;
} /* end setBreastfeedingStopAge */
/** \brief setAgeOfSeroreversion sets the age of seroreversion for pediatrics and updates statistics
*
* \param age an int for age of seroreversion
**/
void StateUpdater::setAgeOfSeroreversion(int age) {
if (age < 0)
age = 0;
patient->pedsState.ageOfSeroreversion = age;
} /* end setAgeOfSeroreversion */
/** \brief resetNumMissedVisitsEID sets the number of missed eid visits to 0
**/
void StateUpdater::resetNumMissedVisitsEID(){
patient->pedsState.numMissedVistsEID = 0;
} /* end resetNumMissedVisitsEID */
/** \brief incrementNumMissedVisitsEID increases the number of missed eid visits by 1
**/
void StateUpdater::incrementNumMissedVisitsEID(){
patient->pedsState.numMissedVistsEID++;
} /* end incrementNumMissedVisitsEID */
/** \brief setCareState sets the patient's care state
*
* \param typeCare a SimContext::HIV_Care indicating the state of patient care
**/
void StateUpdater::setCareState(SimContext::HIV_CARE typeCare){
patient->monitoringState.careState = typeCare;
}
/** \brief setDetectedHIVState sets the patient's detection status and updates statistics
*
* \param isDetected a bool indicating whether or not the patient has been detected with HIV
* \param typeDetection a SimContext::HIV_DET indicating the type of detection
* \param oiType a SimContext::OI_TYPE indicating which OI (default OI_NONE) triggered the detection
*
* If isDetected is true, all detection statistics are updated.
**/
void StateUpdater::setDetectedHIVState(bool isDetected, SimContext::HIV_DET typeDetection, SimContext::OI_TYPE oiType) {
patient->monitoringState.isDetectedHIVPositive = isDetected;
// Update statistics for a newly detected patient, if screening module is enabled
if (isDetected) {
patient->monitoringState.monthOfDetection = patient->generalState.monthNum;
setCareState(SimContext::HIV_CARE_UNLINKED);
SimContext::CD4_STRATA cd4Strata = patient->diseaseState.currTrueCD4Strata;
SimContext::HVL_STRATA hvlStrata = patient->diseaseState.currTrueHVLStrata;
SimContext::HIV_POS hivPosState = patient->diseaseState.infectedHIVPosState;
int monthNum = patient->generalState.monthNum;
int ageMonths = patient->generalState.ageMonths;
// Monthly detection outputs
RunStats::TimeSummary *currTime = getTimeSummaryForUpdate();
if(currTime){
currTime->numHIVDetections[typeDetection]++;
if (simContext->getPedsInputs()->enablePediatricsModel && patient->pedsState.isMotherAlive && !patient->pedsState.maternalStatusKnown){
currTime->numNewlyDetectedPediatricsMotherStatusUnknown++;
}
}
//Disable PrEP on detection
if(simContext->getHIVTestInputs()->enableHIVTesting && simContext->getHIVTestInputs()->enablePrEP){
if(patient->monitoringState.hasPrEP){
setPrEP(false);
}
}
// Overall detection outputs
if (typeDetection != SimContext::HIV_DET_BACKGROUND_PREV_DET && typeDetection != SimContext::HIV_DET_OI_PREV_DET && typeDetection != SimContext::HIV_DET_SCREENING_PREV_DET && typeDetection != SimContext::HIV_DET_TB_PREV_DET){
runStats->hivScreening.numDetectedGender[patient->generalState.gender]++;
costStats->popSummary.numDetected++;
}
if (typeDetection == SimContext::HIV_DET_OI) {
runStats->hivScreening.numDetectedByOIs[oiType]++;
}
if (typeDetection == SimContext::HIV_DET_OI_PREV_DET){
runStats->hivScreening.numDetectedByOIsPrevDetected[oiType]++;
}
if (patient->diseaseState.isPrevalentHIVCase) {
runStats->hivScreening.numDetectedPrevalentMeans[typeDetection]++;
if (typeDetection != SimContext::HIV_DET_BACKGROUND_PREV_DET && typeDetection != SimContext::HIV_DET_OI_PREV_DET && typeDetection != SimContext::HIV_DET_SCREENING_PREV_DET){
runStats->hivScreening.numAtDetectionPrevalentCD4Metric[patient->pedsState.ageCategoryCD4Metric]++;
runStats->hivScreening.numAtDetectionPrevalentHIVCD4Metric[hivPosState][patient->pedsState.ageCategoryCD4Metric]++;
runStats->hivScreening.numAtDetectionPrevalentCD4HIV[cd4Strata][hivPosState]++;
runStats->hivScreening.numAtDetectionPrevalentHVLHIV[hvlStrata][hivPosState]++;
if (patient->pedsState.ageCategoryCD4Metric == SimContext::CD4_ABSOLUTE)
runStats->hivScreening.CD4AtDetectionPrevalentSumHIV[hivPosState]+= patient->diseaseState.currTrueCD4;
runStats->hivScreening.monthsToDetectionPrevalentSum += monthNum;
runStats->hivScreening.monthsToDetectionPrevalentSumSquares += monthNum * monthNum;
runStats->hivScreening.ageMonthsAtDetectionPrevalentSum += ageMonths;
runStats->hivScreening.ageMonthsAtDetectionPrevalentSumSquares += ageMonths * ageMonths;
}
}
else {
runStats->hivScreening.numDetectedIncidentMeans[typeDetection]++;
if (typeDetection != SimContext::HIV_DET_BACKGROUND_PREV_DET && typeDetection != SimContext::HIV_DET_OI_PREV_DET && typeDetection != SimContext::HIV_DET_SCREENING_PREV_DET && typeDetection != SimContext::HIV_DET_TB_PREV_DET){
runStats->hivScreening.numAtDetectionIncidentCD4Metric[patient->pedsState.ageCategoryCD4Metric]++;
runStats->hivScreening.numAtDetectionIncidentHIVCD4Metric[hivPosState][patient->pedsState.ageCategoryCD4Metric]++;
runStats->hivScreening.numAtDetectionIncidentCD4HIV[cd4Strata][hivPosState]++;
runStats->hivScreening.numAtDetectionIncidentHVLHIV[hvlStrata][hivPosState]++;
if (patient->pedsState.ageCategoryCD4Metric == SimContext::CD4_ABSOLUTE)
runStats->hivScreening.CD4AtDetectionIncidentSumHIV[hivPosState] += patient->diseaseState.currTrueCD4;
runStats->hivScreening.monthsToDetectionIncidentSum += monthNum;
runStats->hivScreening.monthsToDetectionIncidentSumSquares += monthNum * monthNum;
runStats->hivScreening.ageMonthsAtDetectionIncidentSum += ageMonths;
runStats->hivScreening.ageMonthsAtDetectionIncidentSumSquares += ageMonths * ageMonths;
int monthDiff = monthNum - patient->diseaseState.monthOfHIVInfection;
runStats->hivScreening.monthsAfterInfectionToDetectionSum += monthDiff;
runStats->hivScreening.monthsAfterInfectionToDetectionSumSquares += monthDiff * monthDiff;
}
}
}//end if(isdetected)
else{
if(patient->diseaseState.infectedHIVState!=SimContext::HIV_INF_NEG)
setCareState(SimContext::HIV_CARE_UNDETECTED);
}
} /* end setDetectedHIVState */
/** \brief setLinkedState sets the patient's Link status
* \param typeDetection a SimContext::HIV_DET defaulting to SimContext::HIV_DET_UNDETECTED indicating the type of detection
**/
void StateUpdater::setLinkedState(bool isLinked, SimContext::HIV_DET typeLinked) {
// Update statistics for a newly linked patient, if screening module is enabled
patient->monitoringState.isLinked = isLinked;
if (isLinked){
patient->monitoringState.monthOfLinkage=patient->generalState.monthNum;
setCareState(SimContext::HIV_CARE_IN_CARE);
SimContext::CD4_STRATA cd4Strata = patient->diseaseState.currTrueCD4Strata;
SimContext::HVL_STRATA hvlStrata = patient->diseaseState.currTrueHVLStrata;
SimContext::HIV_POS hivPosState = patient->diseaseState.infectedHIVPosState;
int monthNum = patient->generalState.monthNum;
int ageMonths = patient->generalState.ageMonths;
if(typeLinked == SimContext::HIV_DET_INITIAL)
runStats->hivScreening.numLinkedAtInit[hivPosState]++;
if (patient->monitoringState.hasObservedCD4){
SimContext::CD4_STRATA obsvCD4Strata = patient->monitoringState.currObservedCD4Strata;
costStats->popSummary.observedCD4DistributionAtLinkage[obsvCD4Strata]++;
}
costStats->popSummary.genderDistributionAtLinkage[patient->generalState.gender]++;
costStats->popSummary.ageDistributionAtLinkage[getAgeCategoryLinkageStats(patient->generalState.ageMonths)]++;
runStats->hivScreening.numLinkedMeans[typeLinked]++;
runStats->hivScreening.numAtLinkageCD4Metric[patient->pedsState.ageCategoryCD4Metric]++;
runStats->hivScreening.numAtLinkageHIVCD4Metric[hivPosState][patient->pedsState.ageCategoryCD4Metric]++;
runStats->hivScreening.numAtLinkageCD4HIV[cd4Strata][hivPosState]++;
runStats->hivScreening.numAtLinkageHVLHIV[hvlStrata][hivPosState]++;
if (patient->pedsState.ageCategoryCD4Metric == SimContext::CD4_ABSOLUTE)
runStats->hivScreening.CD4AtLinkageSumHIV[hivPosState]+=patient->diseaseState.currTrueCD4;
runStats->hivScreening.monthsToLinkageSum += monthNum;
runStats->hivScreening.monthsToLinkageSumSquares += monthNum*monthNum;
runStats->hivScreening.ageMonthsAtLinkageSum += ageMonths;
runStats->hivScreening.ageMonthsAtLinkageSumSquares += ageMonths * ageMonths;
runStats->hivScreening.monthsToLinkageSumMeans[typeLinked] += monthNum;
runStats->hivScreening.monthsToLinkageSumSquaresMeans[typeLinked] += monthNum*monthNum;
}
} /* end setLinkedState */
/** \brief setFalsePositiveStatus sets whether the patient is false positive and whether they are linked or not
* \param isFalsePositive is a bool of whether the patient is false positive
* \param isLinked is a bool of whether the patient is linked to care (their care state however is still HIV Neg)
**/
void StateUpdater::setFalsePositiveStatus(bool isFalsePositive, bool isLinked){
patient->pedsState.isFalsePositive = isFalsePositive;
patient->pedsState.isFalsePositiveLinked = isLinked;
} /* end setFalsePositiveStatus */
/** \brief setCanRecieveEID sets the status of whether the patient can get EID test visits
**/
void StateUpdater::setCanReceiveEID(bool canReceiveEID){
patient->pedsState.canReceiveEID = canReceiveEID;
} /* end setCanRecieveEID */
/** \brief removePendingEIDTestsAndResults gets rid of pending test results and scheduled confirmatory EID tests
**/
void StateUpdater::removePendingEIDTestsAndResults(bool removeOITests){
if(removeOITests){
patient->pedsState.eidPendingTestResults.clear();
patient->pedsState.eidScheduledConfirmatoryTests.clear();
}
else{
int i = 0;
while (i < patient->pedsState.eidPendingTestResults.size()){
SimContext::OI_TYPE triggeredByOI = patient->pedsState.eidPendingTestResults[i].triggeredByOI;
if (triggeredByOI == SimContext::OI_NONE){
vector<SimContext::EIDTestState>::iterator eraseIter = patient->pedsState.eidPendingTestResults.begin();
advance(eraseIter, i);
//remove element from vector
patient->pedsState.eidPendingTestResults.erase(eraseIter);
}
else
i++;
}
i = 0;
while (i < patient->pedsState.eidScheduledConfirmatoryTests.size()){
SimContext::OI_TYPE triggeredByOI = patient->pedsState.eidScheduledConfirmatoryTests[i].triggeredByOI;
if (triggeredByOI == SimContext::OI_NONE){
vector<SimContext::EIDTestState>::iterator eraseIter = patient->pedsState.eidScheduledConfirmatoryTests.begin();
advance(eraseIter, i);
//remove element from vector
patient->pedsState.eidScheduledConfirmatoryTests.erase(eraseIter);
}
else
i++;
}
}
} /* end removePendingEIDTestsAndResults */
/** \brief updateHIVTestingStats updates all statistics after an HIV testing event
*
* \param acceptTest a bool that indicates whether or not the patient accepted the test -- returnResults and isPositive are
* irrelevant if this is false
* \param returnResults a bool that indicates whether or not the patient returned for the result -- if this is false,
* isPositive is irrelevant
* \param isPositive a bool indicating whether or not the patient's test came back HIV positive
*
* If the patient accepted the test and returned for the test, the test results are recorded in the statistics depending
* on whether it was a true positive, true negative, false positive, or false negative.
**/
void StateUpdater::updateHIVTestingStats(bool acceptTest, bool returnResults, bool isPositive) {
if (!acceptTest) {
runStats->hivScreening.numRefuseTest++;
return;
}
SimContext::HIV_EXT_INF infectedState;
if ((patient->diseaseState.infectedHIVState == SimContext::HIV_INF_NEG) && !patient->monitoringState.isHighRiskForHIV) {
infectedState = SimContext::HIV_EXT_INF_NEG_LO;
}
else {
infectedState = (SimContext::HIV_EXT_INF) patient->diseaseState.infectedHIVState;
}
runStats->hivScreening.numTestsHIVState[infectedState]++;
runStats->hivScreening.numAcceptTest++;
if (!returnResults) {
runStats->hivScreening.numNoReturnForResults++;
return;
}
runStats->hivScreening.numReturnForResults++;
if (isPositive) {
if (patient->diseaseState.infectedHIVState == SimContext::HIV_INF_NEG) {
runStats->hivScreening.numTestResultsHIVNegativeType[SimContext::TEST_FALSE_POS]++;
}
else if (patient->diseaseState.isPrevalentHIVCase) {
runStats->hivScreening.numTestResultsPrevalentType[SimContext::TEST_TRUE_POS]++;
}
else {
runStats->hivScreening.numTestResultsIncidentType[SimContext::TEST_TRUE_POS]++;
}
}
else {
if (patient->diseaseState.infectedHIVState == SimContext::HIV_INF_NEG) {
runStats->hivScreening.numTestResultsHIVNegativeType[SimContext::TEST_TRUE_NEG]++;
}
else if (patient->diseaseState.isPrevalentHIVCase) {
runStats->hivScreening.numTestResultsPrevalentType[SimContext::TEST_FALSE_NEG]++;
}
else {
runStats->hivScreening.numTestResultsIncidentType[SimContext::TEST_FALSE_NEG]++;
}
}
} /* end updateHIVTestingStats */
/** \brief updateLabStagingStats updates all statistics after a Lab Staging event
*
* \param acceptTest a bool that indicates whether or not the patient accepted the test -- returnResults and isPositive are
* irrelevant if this is false
* \param returnResults a bool that indicates whether or not the patient returned for the result -- if this is false,
* hasLinked is irrelevant
* \param hasLinked a bool indicating whether or not the patient links to care
*
**/
void StateUpdater::updateLabStagingStats(bool acceptTest, bool returnResults, bool hasLinked) {
if (patient->diseaseState.infectedHIVState == SimContext::HIV_INF_NEG)
return;
if (!acceptTest) {
runStats->hivScreening.numRefuseLabStaging++;
return;
}
SimContext::HIV_POS infectedState = (SimContext::HIV_POS) (patient->diseaseState.infectedHIVState-1);
runStats->hivScreening.numAcceptLabStagingHIVState[infectedState]++;
runStats->hivScreening.numAcceptLabStaging++;
if (!returnResults) {
runStats->hivScreening.numNoReturnForResultsLabStaging++;
return;
}
SimContext::CD4_STRATA trueCD4Strata = patient->diseaseState.currTrueCD4Strata;
SimContext::CD4_STRATA obsvCD4Strata = patient->monitoringState.currObservedCD4Strata;
runStats->hivScreening.numReturnLabStagingHIVState[infectedState]++;
runStats->hivScreening.numReturnForResultsLabStaging++;
runStats->hivScreening.numReturnLabStagingObsvCD4[obsvCD4Strata]++;
runStats->hivScreening.numReturnLabStagingTrueCD4[trueCD4Strata]++;
runStats->hivScreening.numReturnLabStagingObsvTrueCD4[obsvCD4Strata][trueCD4Strata]++;
if(!hasLinked){
runStats->hivScreening.numNoLinkLabStaging++;
return;
}
runStats->hivScreening.numLinkLabStagingObsvCD4[obsvCD4Strata]++;
runStats->hivScreening.numLinkLabStagingTrueCD4[trueCD4Strata]++;
runStats->hivScreening.numLinkLabStagingObsvTrueCD4[obsvCD4Strata][trueCD4Strata]++;
runStats->hivScreening.numLinkLabStaging++;
} /* end updateLabStagingStats */
/** \brief setHIVTestingParams sets the interval and acceptance probability for HIV testing
*
* \param intervalIndex an integer representing which HIV Testing Interval to assign to the patient based on user specified stratification
* \param acceptanceProbIndex an integer representing which HIV Test acceptance probability to assign to the patient based on user specified stratification
*
* The patient's HIV testing interval and acceptance probability is set and the runStats relating to the number of patients in each testing interval and acceptance probability are incremented
**/
void StateUpdater::setHIVTestingParams(int intervalIndex, int acceptanceProbIndex) {
SimContext::HIV_EXT_INF extInfectedState = (SimContext::HIV_EXT_INF) patient->diseaseState.infectedHIVState;
if ((patient->diseaseState.infectedHIVState == SimContext::HIV_INF_NEG) && !patient->monitoringState.isHighRiskForHIV)
extInfectedState = SimContext::HIV_EXT_INF_NEG_LO;
patient->monitoringState.intervalHIVTest = simContext->getHIVTestInputs()->HIVTestingInterval[intervalIndex];
patient->monitoringState.acceptanceProbHIVTest = simContext->getHIVTestInputs()->HIVTestAcceptProb[extInfectedState][acceptanceProbIndex];
runStats->hivScreening.numTestingInterval[intervalIndex]++;
runStats->hivScreening.numTestingAcceptProb[acceptanceProbIndex][extInfectedState]++;
} /* end setHIVTestingParams */
/** \brief setPrEP sets whether the patient is on PrEP and updates statistics about PrEP start and stop
*
* \param hasPrEP a bool representing if the patient is on PrEP
* \param isDropout a bool defaulting to false indicating if the patient is dropping out of PrEP
* \param isMaxAge a bool defaulting to false indicating if the patient is stopping due to age
*
**/
void StateUpdater::setPrEP(bool hasPrEP, bool isDropout, bool isMaxAge) {
patient->monitoringState.hasPrEP = hasPrEP;
if (hasPrEP){
patient->monitoringState.everPrEP = true;
runStats->hivScreening.numEverPrEP++;
if(simContext->getHIVTestInputs()->dropoutThresholdFromPrEPStart)
patient->monitoringState.PrEPDropoutThresholdMonth = patient->generalState.monthNum + simContext->getHIVTestInputs()->PrEPDropoutThreshold;
else
patient->monitoringState.PrEPDropoutThresholdMonth = simContext->getHIVTestInputs()->PrEPDropoutThreshold;
}
else if(isDropout){
patient->monitoringState.isPrEPDropout = true;
runStats->hivScreening.numDropoutPrEP++;
}
else if(isMaxAge){
patient->monitoringState.prepStoppedMaxAge = true;
runStats->hivScreening.numStopPrEPMaxAge++;
}
} /* end setPrEP */
/** \brief setInitialPrEPParams sets the initial PrEP parameters
*
*
**/
void StateUpdater::setInitialPrEPParams(){
patient->monitoringState.everPrEP = false;
patient->monitoringState.isPrEPDropout = false;
patient->monitoringState.prepStoppedMaxAge = false;
} /* end setInitialPrEPParams */
/** \brief updatePrEPProbLogging logs the monthly probability of PrEP uptake
*
* \param prepProb a double indicating the probability of PrEP uptake calculated for this risk level
* \param risk a SimContext::HIV_BEHAV indicating the patient's HIV risk level
*
**/
void StateUpdater::updatePrEPProbLogging(double prepProb, SimContext::HIV_BEHAV risk){
RunStats::TimeSummary *currTime = getTimeSummaryForUpdate();
if (currTime)
currTime->probPrepUptake[risk] = prepProb;
} /* end updatePrEPProbLogging */
/** \brief setCD4TestingAvailable Sets whether the patient is able to get CD4 tests
*
* \param isAvail a bool indicating whether or not patient is able to get CD4 tests
**/
void StateUpdater::setCD4TestingAvailable(bool isAvail){
patient->monitoringState.CD4TestingAvailable = isAvail;
} /* end setCD4TestingAvailable */
/** \brief setChanceCD4Test sets whether the patient has had an option to get a cd4 test
*
* \param hadChance a bool indicating whether or not patient had a chance for cd4 test
**/
void StateUpdater::setChanceCD4Test(bool hadChance) {
patient->monitoringState.hadChanceCD4Test=hadChance;
} /* end setChanceCD4Test */
/** \brief setChanceHVLTest sets whether the patient has had an option to get a HVL test
*
* \param hadChance a bool indicating whether or not patient had a chance for HVL test
**/