Simpact Cyan
Population based event driven simulation using mNRM
person.h
1 #ifndef PERSON_H
2 
3 #define PERSON_H
4 
5 #include "personbase.h"
6 #include "util.h"
7 #include "aidstodutil.h"
8 #include <stdlib.h>
9 #include <iostream>
10 #include <vector>
11 #include <set>
12 
13 class Person;
14 class Man;
15 class Woman;
17 class ConfigSettings;
18 class ConfigWriter;
20 class VspModel;
21 
22 Man *MAN(Person *pPerson);
23 Woman *WOMAN(Person *pPerson);
24 
25 class Person : public PersonBase
26 {
27 public:
28  enum InfectionType { None, Partner, Mother, Seed };
29  enum InfectionStage { NoInfection, Acute, Chronic, AIDS, AIDSFinal };
30 
31  Person(double dateOfBirth, Gender g);
32  ~Person();
33 
34  bool isMan() const { return getGender() == Male; }
35  bool isWoman() const { return getGender() == Female; }
36 
37  void setFather(Man *pFather) { assert(m_pFather == 0); assert(pFather != 0); m_pFather = pFather; }
38  void setMother(Woman *pMother) { assert(m_pMother == 0); assert(pMother != 0); m_pMother = pMother; }
39 
40  Man *getFather() const { return m_pFather; }
41  Woman *getMother() const { return m_pMother; }
42 
43  // This also resets the iterator for getNextRelationshipPartner
44  int getNumberOfRelationships() const { return m_relationshipsSet.size(); }
45  void startRelationshipIteration();
46  Person *getNextRelationshipPartner(double &formationTime);
47  int getNumberOfDiagnosedPartners();
48 
49  bool hasRelationshipWith(Person *pPerson) const;
50 
51  // WARNING: do not use these during relationship iteration
52  void addRelationship(Person *pPerson, double t);
53  void removeRelationship(Person *pPerson, double t, bool deathBased);
54 
55  // result is negative if no relations formed yet
56  double getLastRelationshipChangeTime() const { return m_lastRelationChangeTime; }
57 
58  void setSexuallyActive(double t) { m_sexuallyActive = true; assert(t >= 0); m_debutTime = t; }
59  bool isSexuallyActive() { return m_sexuallyActive;}
60  double getDebutTime() const { return m_debutTime; }
61 
62  void setInfected(double t, Person *pOrigin, InfectionType iType);
63  bool isInfected() const { if (m_infectionStage == NoInfection) return false; return true; }
64  double getInfectionTime() const { assert(m_infectionStage != NoInfection); return m_infectionTime; }
65  InfectionStage getInfectionStage() const { return m_infectionStage; }
66  void setInChronicStage() { assert(m_infectionStage == Acute); m_infectionStage = Chronic; }
67  void setInAIDSStage() { assert(m_infectionStage == Chronic); m_infectionStage = AIDS; }
68  void setInFinalAIDSStage() { assert(m_infectionStage == AIDS); m_infectionStage = AIDSFinal; }
69  double getAIDSMortalityTime() const { return m_aidsTodUtil.getTimeOfDeath(); }
70 
71  bool isDiagnosed() const { return (m_diagnoseCount > 0); }
72  void increaseDiagnoseCount() { m_diagnoseCount++; }
73  int getDiagnoseCount() const { return m_diagnoseCount; }
74 
75  double getSetPointViralLoad() const { assert(m_infectionStage != NoInfection); return m_Vsp; }
76  double getViralLoad() const;
77  void lowerViralLoad(double fractionOnLogscale, double treatmentTime);
78  bool hasLoweredViralLoad() const { assert(isInfected()); assert(m_Vsp > 0); return m_VspLowered; }
79  double getLastTreatmentStartTime() const { assert(isInfected()); assert(m_Vsp > 0); assert(m_VspLowered); assert(m_lastTreatmentStartTime >= 0); return m_lastTreatmentStartTime; }
80  void resetViralLoad(double dropoutTime);
81  int getNumberTreatmentStarted() const { assert(isInfected()); return m_treatmentCount; }
82 
83  double getFormationEagernessParameter() const { return m_formationEagerness; }
84  double getPreferredAgeDifference() const { assert(m_preferredAgeDiff < 200.0 && m_preferredAgeDiff > -200.0); return m_preferredAgeDiff; }
85 
86  // TODO: currently, the death of a parent or the death of a child does
87  // not have any influence on this list. I don't think modifying the list
88  // on a mortality event is useful, will only complicate things
89  // TODO: what might be useful is a member function to retrieve the number
90  // of living children?
91  void addChild(Person *pPerson);
92  bool hasChild(Person *pPerson) const;
93  int getNumberOfChildren() const { return m_children.size(); }
94  Person *getChild(int idx);
95 
96  // NOTE: this ignores the call if already in the list
97  void addPersonOfInterest(Person *pPerson);
98  void removePersonOfInterest(Person *pPerson);
99  void clearPersonsOfInterest() { m_personsOfInterest.clear(); }
100  int getNumberOfPersonsOfInterest() const { return m_personsOfInterest.size(); }
101  Person *getPersonOfInterest(int idx) const { assert(idx >= 0 && idx < m_personsOfInterest.size()); Person *pPerson = m_personsOfInterest[idx]; assert(pPerson); return pPerson; }
102 
103  double getCD4Count(double t) const;
104  double getARTAcceptanceThreshold() const { return m_artAcceptanceThreshold; }
105 
106  static void processConfig(ConfigSettings &config, GslRandomNumberGenerator *pRndGen);
107  static void obtainConfig(ConfigWriter &config);
108 
109  static void writeToRelationLog(const Person *pMan, const Person *pWoman, double formationTime, double dissolutionTime);
110  void writeToPersonLog();
111  void writeToTreatmentLog(double dropoutTime, bool justDied);
112 private:
113  double initializeEagerness();
114  double getViralLoadFromSetPointViralLoad(double x) const;
115  void initializeCD4Counts();
116  static double pickSeedSetPointViralLoad();
117  static double pickInheritedSetPointViralLoad(const Person *pOrigin);
118 
119  class Relationship
120  {
121  public:
122  // A negative time is used when not relevant, e.g. when
123  // searching for a relationship with a person
124  Relationship(Person *pPerson, double formationTime) { assert(pPerson != 0); assert(formationTime > 0); m_pPerson = pPerson; m_formationTime = formationTime; }
125  Relationship(Person *pPerson) { assert(pPerson != 0); m_pPerson = pPerson; m_formationTime = -1; }
126 
127  Person *getPartner() const { return m_pPerson; }
128  double getFormationTime() const { return m_formationTime; }
129 
130  bool operator<(const Relationship &rel) const
131  {
132  if (m_pPerson->getPersonID() < rel.m_pPerson->getPersonID())
133  return true;
134  return false;
135  }
136  private:
137  Person *m_pPerson;
138  double m_formationTime;
139  };
140 
141 #ifndef NDEBUG
142  bool m_relIterationBusy;
143 #endif
144 
145  std::set<Relationship> m_relationshipsSet;
146  std::set<Relationship>::const_iterator m_relationshipsIterator;
147  double m_lastRelationChangeTime;
148  bool m_sexuallyActive;
149  double m_debutTime;
150 
151  double m_infectionTime;
152  Person *m_pInfectionOrigin;
153  InfectionType m_infectionType;
154  InfectionStage m_infectionStage;
155  int m_diagnoseCount;
156 
157  double m_Vsp, m_VspOriginal;
158  bool m_VspLowered;
159  double m_lastTreatmentStartTime;
160  int m_treatmentCount;
161 
162  Man *m_pFather;
163  Woman *m_pMother;
164 
165  double m_formationEagerness;
166  double m_preferredAgeDiff;
167 
168  std::vector<Person *> m_children;
169  std::vector<Person *> m_personsOfInterest;
170 
171  AIDSTimeOfDeathUtility m_aidsTodUtil;
172 
173  double m_cd4AtStart, m_cd4AtDeath;
174  double m_artAcceptanceThreshold;
175 
176  static double m_hivSeedWeibullShape;
177  static double m_hivSeedWeibullScale;
178  static double m_VspHeritabilitySigmaFraction;
179  static double m_acuteFromSetPointParamX;
180  static double m_aidsFromSetPointParamX;
181  static double m_finalAidsFromSetPointParamX;
182  static double m_maxValue;
183  static double m_maxViralLoad;
184  static ProbabilityDistribution *m_pEagernessDistribution;
185  static ProbabilityDistribution *m_pMaleAgeGapDistribution;
186  static ProbabilityDistribution *m_pFemaleAgeGapDistribution;
187  static VspModel *m_pVspModel;
188 
189  static ProbabilityDistribution *m_pCD4StartDistribution;
190  static ProbabilityDistribution *m_pCD4EndDistribution;
191  static ProbabilityDistribution *m_pARTAcceptDistribution;
192 };
193 
194 inline double Person::getViralLoad() const
195 {
196  assert(m_infectionStage != NoInfection);
197  if (m_infectionStage == Acute)
198  return getViralLoadFromSetPointViralLoad(m_acuteFromSetPointParamX);
199  else if (m_infectionStage == Chronic)
200  return getSetPointViralLoad();
201  else if (m_infectionStage == AIDS)
202  return getViralLoadFromSetPointViralLoad(m_aidsFromSetPointParamX);
203  else if (m_infectionStage == AIDSFinal)
204  return getViralLoadFromSetPointViralLoad(m_finalAidsFromSetPointParamX);
205 
206  abortWithMessage("Unknown stage in Person::getViralLoad");
207  return -1;
208 }
209 
210 inline void Person::addChild(Person *pPerson)
211 {
212  assert(pPerson != 0);
213  assert(!hasChild(pPerson));
214 
215  m_children.push_back(pPerson);
216 }
217 
218 // TODO: this is currently not fast for large number of children
219 // can always use a 'set' if this becomes a bottleneck
220 inline bool Person::hasChild(Person *pPerson) const
221 {
222  assert(pPerson != 0);
223 
224  for (int i = 0 ; i < m_children.size() ; i++)
225  {
226  assert(m_children[i] != 0);
227 
228  if (m_children[i] == pPerson)
229  return true;
230  }
231 
232  return false;
233 }
234 
235 class Man : public Person
236 {
237 public:
238  Man(double dateOfBirth);
239  ~Man();
240 };
241 
242 class Woman : public Person
243 {
244 public:
245  Woman(double dateOfBirth);
246  ~Woman();
247 
248  void setPregnant(bool f) { m_pregnant = f; }
249  bool isPregnant() const { return m_pregnant; }
250 private:
251  bool m_pregnant;
252 };
253 
254 inline bool Person::hasRelationshipWith(Person *pPerson) const
255 {
256  return m_relationshipsSet.find(Person::Relationship(pPerson)) != m_relationshipsSet.end();
257 }
258 
259 inline Man *MAN(Person *pPerson)
260 {
261  assert(pPerson != 0);
262  assert(pPerson->getGender() == PersonBase::Male);
263 
264  return static_cast<Man*>(pPerson);
265 }
266 
267 inline Woman *WOMAN(Person *pPerson)
268 {
269  assert(pPerson != 0);
270  assert(pPerson->getGender() == PersonBase::Female);
271 
272  return static_cast<Woman*>(pPerson);
273 }
274 
275 inline Person* Person::getChild(int idx)
276 {
277  assert(idx >= 0 && idx < m_children.size());
278  Person *pChild = m_children[idx];
279 
280  assert(pChild != 0);
281 #ifndef NDEBUG
282  if (isWoman())
283  {
284  assert(pChild->getMother() == this);
285  }
286  else // we should be the father of the child
287  {
288  assert(pChild->getFather() == this);
289  }
290 #endif
291  return pChild;
292 }
293 
294 #endif // PERSON_H
295 
The person is a man.
Definition: personbase.h:30
Gender getGender() const
Returns the gender of the person as set at construction time.
Definition: personbase.h:50
Helper class to read configuration settings, more advanced than ConfigReader.
Definition: configsettings.h:21
The person is a woman.
Definition: personbase.h:32
This class allows you to generate random numbers, and uses the GNU Scientific Library for this...
Definition: gslrandomnumbergenerator.h:16
This is the base class for a person in a population-based simulation that used the Population class...
Definition: personbase.h:23
Abstract base class for probability distribution implementations so that they can be used interchange...
Definition: probabilitydistribution.h:15