-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathPerson.h
385 lines (308 loc) · 20.1 KB
/
Person.h
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
// Person.h
// A single individual.
#ifndef __PERSON_H
#define __PERSON_H
#include <bitset>
#include <vector>
#include <climits>
#include "Parameters.h"
#include "Location.h"
//enum QuarantineLevel {MINIMAL, MODERATE, FULL, NUM_OF_QUARANTINE_LEVELS};
class Location;
class Community;
class Vaccinee;
struct Detection {
Detection() {
detected_state = NUM_OF_OUTCOME_TYPES;
reported_time = INT_MAX;
};
Detection(OutcomeType ds, int rt) : detected_state(ds), reported_time(rt) {};
Detection(const Detection& o) {
detected_state = o.detected_state;
reported_time = o.reported_time;
};
OutcomeType detected_state;
int reported_time;
};
class Infection {
friend class Person;
Infection() {
infectedBegin = INT_MAX;
infectiousBegin = INT_MAX;
symptomBegin = INT_MAX;
severeBegin = INT_MAX;
hospitalizedBegin = INT_MAX;
criticalBegin = INT_MAX;
icuBegin = INT_MAX;
deathTime = INT_MAX;
infectedPlace = nullptr;
infectedBy = nullptr;
infectionOwner = nullptr;
infectiousEnd = INT_MIN;
symptomEnd = INT_MIN;
severeEnd = INT_MIN;
criticalEnd = INT_MIN;
strain = WILDTYPE;
relInfectiousness = 1.0;
_detection = nullptr;
};
Infection(const Infection& o) {
infectedBegin = o.infectedBegin;
infectedPlace = o.infectedPlace;
infectedBy = o.infectedBy;
infectionOwner = o.infectionOwner; // TODO: need to test to make sure that infections are copied and cached properly
infectiousBegin = o.infectiousBegin;
infectiousEnd = o.infectiousEnd;
symptomBegin = o.symptomBegin;
symptomEnd = o.symptomEnd;
severeBegin = o.severeBegin;
severeEnd = o.severeEnd;
hospitalizedBegin = o.hospitalizedBegin;
criticalBegin = o.criticalBegin;
criticalEnd = o.criticalEnd;
icuBegin = o.icuBegin;
deathTime = o.deathTime;
infections_caused = o.infections_caused;
strain = o.strain;
relInfectiousness = o.relInfectiousness;
_detection = o._detection ? new Detection(*(o._detection)) : nullptr;
};
~Infection() {
if (_detection) delete _detection;
}
int infectedBegin; // when infected?
Location* infectedPlace; // where infected?
Person* infectedBy; // who infected this person
Person* infectionOwner; // who this infection belongs to
int infectiousBegin; // when infectious period starts
int infectiousEnd;
int symptomBegin; // when symptoms start
int symptomEnd;
int severeBegin;
int severeEnd;
int hospitalizedBegin;
int criticalBegin;
int criticalEnd;
int icuBegin;
int deathTime;
std::vector<Infection*> infections_caused;
StrainType strain;
double relInfectiousness;
Detection* _detection;
static const Parameters* _par;
public:
bool isLocallyAcquired() const { return infectedBy != nullptr; }
Location* getInfectedPlace() const { return infectedPlace; }
void setInfectedPlace(Location* loc) { infectedPlace = loc; }
Person* getInfectedBy() const { return infectedBy; }
void setInfectedBy(Person* p) { infectedBy = p; }
Person* getInfectionOwner() const { return infectionOwner; }
void setInfectionOwner(Person* p) { infectionOwner = p; }
int getInfectedTime() const { return infectedBegin; }
int getInfectiousTime() const { return infectiousBegin; }
int getInfectiousEndTime() const { return infectiousEnd; }
int getSymptomTime() const { return symptomBegin; }
int getSymptomEndTime() const { return symptomEnd; }
int getSevereTime() const { return severeBegin; }
int getSevereEndTime() const { return severeEnd; }
int getHospitalizedTime() const { return hospitalizedBegin; }
int getCriticalTime() const { return criticalBegin; }
int getCriticalEndTime() const { return criticalEnd; }
int getIcuTime() const { return icuBegin; }
int getDeathTime() const { return deathTime; }
StrainType getStrain() const { return strain; }
double getRelInfectiousness() const { return relInfectiousness; } // Could be time-varying in the future
bool infected() const { return infectedBegin != INT_MAX; } // These functions check whether these things
bool infectious() const { return infectiousBegin != INT_MAX; } // happen at any point during this infection, e.g.
bool symptomatic() const { return symptomBegin != INT_MAX; } // have these been modified from their defaults?
bool severe() const { return severeBegin != INT_MAX; }
bool critical() const { return criticalBegin != INT_MAX; }
bool hospital() const { return hospitalizedBegin != INT_MAX; }
bool icu() const { return icuBegin != INT_MAX; }
bool fatal() const { return deathTime != INT_MAX; }
// if we ensure that death coincides with the end of symptoms/severity/criticality, then we don't also need to check deathtime
bool isInfected(int now) const { return infectedBegin <= now and now < infectiousEnd;}
bool isInfectious(int now) const { return infectiousBegin <= now and now < infectiousEnd;}
bool isSymptomatic(int now) const { return symptomBegin <= now and now < symptomEnd; }
bool isSevere(int now) const { return severeBegin <= now and now < severeEnd; }
bool isCritical(int now) const { return criticalBegin <= now and now < criticalEnd; }
bool inHospital(int now) const { return hospitalizedBegin <= now and now < severeEnd;} // if fatal, severe state ends upon death
bool inIcu(int now) const { return icuBegin <= now and now < criticalEnd;}
bool isDead(int now) const { return deathTime <= now; }
void detect(OutcomeType detected_state, int report_date) { _detection = new Detection{detected_state, report_date}; }
Detection* getDetection() { return _detection; }
bool isDetected() const { return (bool) _detection; }
bool isDetectedOn(int now) const { return (bool) isDetected() and _detection->reported_time == now; }
void log_transmission(Infection* inf) { infections_caused.push_back(inf); }
size_t secondary_infection_tally () const { return infections_caused.size(); }
std::vector<Infection*> get_infections_caused() { return infections_caused; }
std::vector<int> generation_times () const {
std::vector<int> times;
for (Infection* other: infections_caused) { times.push_back(other->getInfectedTime() - getInfectedTime()); }
return times;
}
void dumper() const;
};
class Person {
friend Vaccinee;
public:
Person();
Person(const Person& o) {
id = o.id;
home_loc = o.home_loc;
day_loc = o.day_loc;
patronized_locs = o.patronized_locs;
age = o.age;
sex = o.sex;
long_term_care = o.long_term_care;
comorbidity = o.comorbidity;
naiveVaccineProtection = o.naiveVaccineProtection;
immune_state = o.immune_state;
infectionHistory = std::vector<Infection*>(o.infectionHistory.size());
for(size_t i = 0; i < o.infectionHistory.size(); ++i) {
infectionHistory[i] = new Infection(*(o.infectionHistory[i]));
}
naturalImmunityDuration = o.naturalImmunityDuration;
startingNaturalEfficacy = o.startingNaturalEfficacy;
immunityQuantile = o.immunityQuantile;
vaccineHistory = o.vaccineHistory;
quarantineHistory = o.quarantineHistory;
};
~Person();
void revertState(const Date* date);
inline int getID() const { return id; }
int getAge() const { return age; }
void setAge(int a) { age = a; }
SexType getSex() const { return sex; }
void setSex(SexType s) { sex = s; }
bool isHCW() { return getDayLoc() and ((getDayLoc()->getType() == HOSPITAL) or (getDayLoc()->getType() == NURSINGHOME)); }
double getStartingNaturalEfficacy() const { return startingNaturalEfficacy; }
void setStartingNaturalEfficacy(double sne) { startingNaturalEfficacy = sne; }
//size_t getDaysImmune() const { return daysImmune; }
//void setDaysImmune(size_t di) { daysImmune = di; }
int getNaturalImmunityDuration() const { return naturalImmunityDuration; }
void setNaturalImmunityDuration(int nid) { naturalImmunityDuration = nid; }
float getCrossProtectionProbability() const { return crossProtectionProbability; }
void setCrossProtectionProbability(float cpp) { crossProtectionProbability = cpp; }
int getVaccineImmunityDuration(size_t dose, StrainType strain) const { return _par->immunityDuration(immunityQuantile, dose, strain); }
double getImmunityQuantile() const { return immunityQuantile; }
void setImmunityQuantile(double iq) { immunityQuantile = iq; }
bool getLongTermCare() { return long_term_care; }
void setLongTermCare(bool b) { long_term_care = b; }
ComorbidType hasComorbidity() { return comorbidity; }
void setComorbidity(ComorbidType status) { comorbidity = status; }
Location* getHomeLoc() { return home_loc; }
void setHomeLoc(Location* loc) { home_loc = loc; }
double getRiskiness() const { return home_loc->getRiskiness(); }
Location* getDayLoc() { return day_loc; }
void setDayLoc(Location* loc) { day_loc = loc; }
Location* getHospital() const { return home_loc->getHospital(); }
void goToHospital() { getHospital()->addPerson(this); }
void leaveHospital() { getHospital()->removePerson(this); }
void addPatronizedLocation(Location* loc) { patronized_locs.push_back(loc); } // person is sometimes a customer of these businesses
vector<Location*> getPatronizedLocations() const { return patronized_locs; }
void setPatronizedLocations(vector<Location*> pl) { patronized_locs = pl; }
// void setImmunity() { immune = true; }
// void copyImmunity(const Person *p);
void resetImmunity();
bool isCrossProtected(int time, StrainType strain) const; // assumes binary cross-immunity
bool isVaccineProtected(int time, StrainType strain) const;
inline Person* getInfectedBy(int infectionsago=0) const { return getInfection(infectionsago)->infectedBy; }
inline Location* getInfectedPlace(int infectionsago=0) const { return getInfection(infectionsago)->infectedPlace; }
inline int getInfectedTime(int infectionsago=0) const { return getInfection(infectionsago)->infectedBegin; }
inline int getInfectiousTime(int infectionsago=0) const { return getInfection(infectionsago)->infectiousBegin; }
inline int getSymptomTime(int infectionsago=0) const { return getInfection(infectionsago)->symptomBegin; }
inline int getSevereTime(int infectionsago=0) const { return getInfection(infectionsago)->severeBegin; }
inline int getCriticalTime(int infectionsago=0) const { return getInfection(infectionsago)->criticalBegin; }
inline int getHospitalizedTime(int infectionsago=0) const { return getInfection(infectionsago)->hospitalizedBegin; }
inline int getIcuTime(int infectionsago=0) const { return getInfection(infectionsago)->icuBegin; }
inline int getDeathTime(int infectionsago=0) const { return getInfection(infectionsago)->deathTime; }
Infection* getInfection(int infectionsago=0) const { return infectionHistory[getNumNaturalInfections() - 1 - infectionsago]; }
StrainType getStrain(int infectionsago=0) const { return getInfection(infectionsago)->strain; }
double getRelInfectiousness(int infectionsago=0) const { return getInfection(infectionsago)->relInfectiousness; }
inline int getNumNaturalInfections() const { return infectionHistory.size(); }
int getNumVaccinations() const { return vaccineHistory.size(); }
const std::vector<int>& getVaccinationHistory() const { return vaccineHistory; }
const std::vector<Infection*>& getInfectionHistory() const { return infectionHistory; }
int daysSinceVaccination(int time) const { assert( vaccineHistory.size() > 0); return time - vaccineHistory.back(); } // isVaccinated() should be called first
double vaccineProtection(const int time, const StrainType strain) const;
vector<double> calculate_event_probabilities(const int time, const StrainType strain) const;
// strain determined by source, unless source is nullptr
Infection* infect(Community* community, Person* source, const Date* date, Location* sourceloc, StrainType strain = NUM_OF_STRAIN_TYPES, bool check_susceptibility = true);
void processDeath(Community* community, Infection &infection, const int time);
inline Infection* infect(Community* community, const Date* date, StrainType strain) {return infect(community, nullptr, date, nullptr, strain);}
// TODO -- the following functions assume that only the most recent infection needs to be inspected
bool inHospital(int time) const { return infectionHistory.size() > 0 and infectionHistory.back()->inHospital(time); }
bool inIcu(int time) const { return infectionHistory.size() > 0 and infectionHistory.back()->inIcu(time); }
bool isDead(int time) const { return infectionHistory.size() > 0 and infectionHistory.back()->isDead(time); } // no deaths due to other causes
bool isAlive(int time) const { return not isDead(time); }
bool isNewlyInfected(int time) const { return infectionHistory.size() > 0 and time == infectionHistory.back()->infectedBegin; }
bool isInfected(int time) const { return infectionHistory.size() > 0 and infectionHistory.back()->isInfected(time); }
bool isInfectious(int time) const { return infectionHistory.size() > 0 and infectionHistory.back()->isInfectious(time); }
bool isSymptomatic(int time) const { return infectionHistory.size() > 0 and infectionHistory.back()->isSymptomatic(time); }
bool isSevere(int time) const { return infectionHistory.size() > 0 and infectionHistory.back()->isSevere(time); }
bool isCritical(int time) const { return infectionHistory.size() > 0 and infectionHistory.back()->isCritical(time); }
bool isNewlyDead(int time) const { return infectionHistory.size() > 0 and time == infectionHistory.back()->deathTime; }
bool isVaccinated() const { return vaccineHistory.size() > 0; } // has been vaccinated
bool isInfectable(int time, StrainType strain) const;
double remainingEfficacy(const int time) const;
bool hasBeenInfected() const { return (bool) infectionHistory.size(); }
//bool isNaive() const { return immune_state == NAIVE; }
bool isImmuneState(ImmuneStateType is) const { return is == immune_state; }
// does this person's immune state permit vaccination?
// NB: inaccurate test results are possible
//bool isSeroEligible(VaccineSeroConstraint vsc, double falsePos, double falseNeg) const;
bool isSeroEligible() const;
bool isInfEligible(int today) const;
static void setPar(const Parameters* par) { _par = par; }
Infection& initializeNewInfection();
Infection& initializeNewInfection(int time, size_t incubation_period, Location* sourceloc, Person* source);
static void reset_ID_counter() { NEXT_ID = 0; }
bool isSurveilledPerson() { return id < _par->numSurveilledPeople; }
void scheduleQuarantine(int start, int quarantineDuration);
bool isQuarantining(int time);
// TODO: generalize
double getBaselineRiskSevOutcome() { return _par->probSeriousOutcome.at(SEVERE)[hasComorbidity()][getAge()] * _par->pathogenicityByAge[getAge()]; }
void dumper(int time = 0) const {
cerr << "Person ID: " << id << endl;
cerr << "\thome loc: " << home_loc->getID() << endl;
cerr << "\tday loc: " << (day_loc ? day_loc->getID() : -1) << endl;
cerr << "\tday loc type: " << (day_loc ? day_loc->getType() : NUM_OF_LOCATION_TYPES) << endl;
cerr << "\thospital: " << getHospital()->getID() << endl;
cerr << "\tage: " << age << endl;
cerr << "\tsex: " << sex << endl;
cerr << "\tltc: " << long_term_care << endl;
cerr << "\tinfection history size: " << infectionHistory.size() << endl;
cerr << "\tinfection days: "; for (size_t i = 0; i < infectionHistory.size(); ++i) { cerr << getInfectedTime(i) << ' '; } cerr << endl;
cerr << "\tvaccination history size: " << vaccineHistory.size() << endl;
cerr << "\tvaccine dose days: "; for (int d : vaccineHistory) { cerr << d << ' '; } cerr << endl;
cerr << boolalpha << "\tis alive: " << isAlive(time) << endl;
cerr << boolalpha << "\tin hospital: " << inHospital(time) << endl;
cerr << boolalpha << "\tin icu: " << inIcu(time) << endl;
cerr << noboolalpha;
}
protected:
size_t id; // unique identifier
Location* home_loc; // family membership
Location* day_loc; // ID of location of work
std::vector<Location*> patronized_locs; // business patronized by this person
int age; // age in years
SexType sex; // sex (gender)
bool long_term_care; // resident of nursing home, etc.
ComorbidType comorbidity; // person has a relevant comorbidity
bool naiveVaccineProtection; // if vaccinated, do we use the naive or non-naive VE_S?
ImmuneStateType immune_state;
std::vector<Infection*> infectionHistory;
int naturalImmunityDuration; // number of days this person retains natural immunity (for all-or-none immunity model)
double startingNaturalEfficacy; // level of protection (Pr{reisting infection}, analogous to VE_S) acquired by person after natural infection
double immunityQuantile; // represents the individual's immune durability
float crossProtectionProbability; // probability of having broad cross-protection
std::vector<int> vaccineHistory; // vector of days on which vaccinations were received
void clearInfectionHistory();
std::vector<pair<int,int>> quarantineHistory;
bool vaccinate(int time); // vaccinate this person
static const Parameters* _par;
static size_t NEXT_ID; // unique ID to assign to the next Person allocated
};
struct PerPtrComp { bool operator()(const Person* A, const Person* B) const { return A->getID() < B->getID(); } };
#endif