Stride Reference Manual  - generated for commit 9643b11
Infector.cpp
Go to the documentation of this file.
1 /*
2  * This is free software: you can redistribute it and/or modify it
3  * under the terms of the GNU General Public License as published by
4  * the Free Software Foundation, either version 3 of the License, or
5  * any later version.
6  * The software is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9  * GNU General Public License for more details.
10  * You should have received a copy of the GNU General Public License
11  * along with the software. If not, see <http://www.gnu.org/licenses/>.
12  *
13  * Copyright 2017, Kuylen E, Willem L, Broeckhove J
14  */
15 
21 #include "Infector.h"
22 
23 #include "ContactPool.h"
24 #include "calendar/Calendar.h"
25 #include "pop/Person.h"
26 
27 using namespace std;
28 
29 namespace {
30 
33 template <ContactLogMode::Id LL>
34 class LOG_POLICY
35 {
36 public:
37  static void Contact(const std::shared_ptr<spdlog::logger>&, const Person*, const Person*, ContactType::Id,
38  unsigned short int, const double, const double)
39  {
40  }
41 
42  static void Trans(const std::shared_ptr<spdlog::logger>&, const Person*, const Person*, ContactType::Id,
43  unsigned short int)
44  {
45  }
46 };
47 
49 template <>
50 class LOG_POLICY<ContactLogMode::Id::Transmissions>
51 {
52 public:
53  static void Contact(const std::shared_ptr<spdlog::logger>&, const Person*, const Person*, ContactType::Id,
54  unsigned short int, const double, const double)
55  {
56  }
57 
58  static void Trans(const std::shared_ptr<spdlog::logger>& logger, const Person* p1, const Person* p2,
59  ContactType::Id type, unsigned short int sim_day)
60  {
61  logger->info("[TRAN] {} {} {} {} {} {}", p2->GetId(), p1->GetId(), p2->GetAge(), p1->GetAge(),
62  ToString(type), sim_day);
63  }
64 };
65 
67 template <>
68 class LOG_POLICY<ContactLogMode::Id::All>
69 {
70 public:
71  static void Contact(const std::shared_ptr<spdlog::logger>& logger, const Person* p1, const Person* p2,
72  ContactType::Id type, unsigned short int sim_day, const double c_rate, const double t_rate)
73  {
74  if (p1->IsSurveyParticipant()) {
75  logger->info("[CONT] {} {} {} {} {} {} {} {} {} {} {} {}", p1->GetId(), p1->GetAge(),
76  p2->GetAge(), static_cast<unsigned int>(type == ContactType::Id::Household),
77  static_cast<unsigned int>(type == ContactType::Id::K12School),
78  static_cast<unsigned int>(type == ContactType::Id::College),
79  static_cast<unsigned int>(type == ContactType::Id::Workplace),
80  static_cast<unsigned int>(type == ContactType::Id::PrimaryCommunity),
81  static_cast<unsigned int>(type == ContactType::Id::SecondaryCommunity), sim_day,
82  c_rate, t_rate);
83  }
84  }
85 
86  static void Trans(const std::shared_ptr<spdlog::logger>& logger, const Person* p1, const Person* p2,
87  ContactType::Id type, unsigned short int sim_day)
88  {
89  logger->info("[TRAN] {} {} {} {} {} {}", p2->GetId(), p1->GetId(), p2->GetAge(), p1->GetAge(),
90  ToString(type), sim_day);
91  }
92 };
93 
95 template <>
96 class LOG_POLICY<ContactLogMode::Id::Susceptibles>
97 {
98 public:
99  static void Contact(const std::shared_ptr<spdlog::logger>& logger, const Person* p1, const Person* p2,
100  ContactType::Id, unsigned short int, const double, const double)
101  {
102  if (p1->IsSurveyParticipant() && p1->GetHealth().IsSusceptible() && p2->GetHealth().IsSusceptible()) {
103  logger->info("[CONT] {} {}", p1->GetId(), p2->GetId());
104  }
105  }
106 
107  static void Trans(const std::shared_ptr<spdlog::logger>&, const Person*, const Person*, ContactType::Id,
108  unsigned short int)
109  {
110  }
111 };
112 
113 } // namespace
114 
115 namespace {
116 
117 using namespace stride;
118 using namespace stride::ContactType;
119 
120 inline double GetContactRate(const AgeContactProfile& profile, const Person* p, size_t pool_size)
121 {
122  const double reference_num_contacts{profile[EffectiveAge(static_cast<unsigned int>(p->GetAge()))]};
123  const double potential_num_contacts{static_cast<double>(pool_size - 1)};
124 
125  double individual_contact_rate = reference_num_contacts / potential_num_contacts;
126  if (individual_contact_rate >= 1) {
127  individual_contact_rate = 0.999;
128  }
129  // Contacts are reciprocal, so one needs to apply only half of the contacts here.
130  individual_contact_rate = individual_contact_rate / 2;
131  // Contacts are bi-directional: contact probability for 1=>2 and 2=>1 = indiv_cnt_rate*indiv_cnt_rate
132  individual_contact_rate += (individual_contact_rate * individual_contact_rate);
133 
134  return individual_contact_rate;
135 }
136 
137 } // namespace
138 
139 namespace stride {
140 
141 //-------------------------------------------------------------------------------------------------
142 // Definition for primary template covers the situation for ContactLogMode::None &
143 // ContactLogMode::Transmissions, both with track_index_case false and true.
144 //-------------------------------------------------------------------------------------------------
145 template <ContactLogMode::Id LL, bool TIC, bool TO>
147  const TransmissionProfile& transProfile, ContactHandler& cHandler,
148  unsigned short int simDay, shared_ptr<spdlog::logger> cLogger)
149 {
150  using LP = LOG_POLICY<LL>;
151 
152  // set up some stuff
153  const auto pType = pool.m_pool_type;
154  const auto& pMembers = pool.m_members;
155  const auto pSize = pMembers.size();
156  const auto tProbability = transProfile.GetProbability();
157 
158  // check all contacts
159  for (size_t i_person1 = 0; i_person1 < pSize; i_person1++) {
160  // check if member is present today
161  const auto p1 = pMembers[i_person1];
162  if (!p1->IsInPool(pType)) {
163  continue;
164  }
165  const double c_rate = GetContactRate(profile, p1, pSize);
166  // loop over possible contacts (contacts can be initiated by each member)
167  for (size_t i_person2 = 0; i_person2 < pSize; i_person2++) {
168  // check if not the same person
169  if (i_person1 == i_person2) {
170  continue;
171  }
172  // check if member is present today
173  const auto p2 = pMembers[i_person2];
174  if (!p2->IsInPool(pType)) {
175  continue;
176  }
177  // check for contact
178  if (cHandler.HasContact(c_rate)) {
179  // log contact if person 1 is participating in survey
180  LP::Contact(cLogger, p1, p2, pType, simDay, c_rate, tProbability);
181  // log contact if person 2 is participating in survey
182  LP::Contact(cLogger, p2, p1, pType, simDay, c_rate, tProbability);
183 
184  // transmission & infection.
185  if (cHandler.HasTransmission(tProbability)) {
186  auto& h1 = p1->GetHealth();
187  auto& h2 = p2->GetHealth();
188  // No secondary infections with TIC; just mark p2 'recovered'
189  if (h1.IsInfectious() && h2.IsSusceptible()) {
190  LP::Trans(cLogger, p1, p2, pType, simDay);
191  h2.StartInfection();
192  if (TIC)
193  h2.StopInfection();
194  } else if (h2.IsInfectious() && h1.IsSusceptible()) {
195  LP::Trans(cLogger, p2, p1, pType, simDay);
196  h1.StartInfection();
197  if (TIC)
198  h1.StopInfection();
199  }
200  }
201  }
202  }
203  }
204 }
205 
206 //-------------------------------------------------------------------------------------------
207 // Time optimized implementation for NoLocalInformationPolicy in
208 // combination with None || Transmission logging.
209 //-------------------------------------------------------------------------------------------
210 template <ContactLogMode::Id LL, bool TIC>
212  const TransmissionProfile& transProfile, ContactHandler& cHandler,
213  unsigned short int simDay, shared_ptr<spdlog::logger> cLogger)
214 {
215  using LP = LOG_POLICY<LL>;
216 
217  // check for infected members and sort
218  bool infectious_cases;
219  size_t num_cases;
220  tie(infectious_cases, num_cases) = pool.SortMembers();
221 
222  if (!infectious_cases) {
223  return;
224  }
225 
226  // set up some stuff
227  const auto c_type = pool.m_pool_type;
228  const auto c_immune = pool.m_index_immune;
229  const auto& c_members = pool.m_members;
230  const auto c_size = c_members.size();
231  const auto t_probability = transProfile.GetProbability();
232 
233  // match infectious and susceptible members, skip last part (immune members)
234  for (size_t i_infected = 0; i_infected < num_cases; i_infected++) {
235  // check if member is present today
236  const auto p1 = c_members[i_infected];
237  if (!p1->IsInPool(c_type)) {
238  continue;
239  }
240  auto& h1 = p1->GetHealth();
241  if (h1.IsInfectious()) {
242  const double c_rate_p1 = GetContactRate(profile, p1, c_size);
243  // loop over possible susceptible contacts
244  for (size_t i_contact = num_cases; i_contact < c_immune; i_contact++) {
245  // check if member is present today
246  const auto p2 = c_members[i_contact];
247  if (!p2->IsInPool(c_type)) {
248  continue;
249  }
250  const double c_rate_p2 = GetContactRate(profile, p2, c_size);
251  if (cHandler.HasContactAndTransmission(c_rate_p1, t_probability) ||
252  cHandler.HasContactAndTransmission(c_rate_p2, t_probability)) {
253  auto& h2 = p2->GetHealth();
254  if (h1.IsInfectious() && h2.IsSusceptible()) {
255  h2.StartInfection();
256  // No secondary infections with TIC; just mark p2 'recovered'
257  if (TIC)
258  h2.StopInfection();
259  LP::Trans(cLogger, p1, p2, c_type, simDay);
260  }
261  }
262  }
263  }
264  }
265 }
266 
267 //--------------------------------------------------------------------------
268 // All explicit instantiations.
269 //--------------------------------------------------------------------------
278 
279 } // namespace stride
std::vector< Person * > m_members
Pointers to contactpool members (raw pointers intentional).
Definition: ContactPool.h:90
Health & GetHealth()
Return person&#39;s health status.
Definition: Person.h:56
Id
Enumerates the ContactPool types.
Definition: ContactType.h:34
bool IsSurveyParticipant() const
Does this person participates in the social contact study?
Definition: Person.h:71
Header file for the Person class.
A group of Persons that potentially have contacts with one another.
Definition: ContactPool.h:38
Header for the core ContactPool class.
string ToString(Id l)
Converts a LogMode value to corresponding name.
bool HasContactAndTransmission(double contact_rate, double transmission_probability)
Check if two individuals have contact and transmission.
bool HasTransmission(double transmission_probability)
Check whether transmission occurs.
unsigned int GetId() const
Get the id.
Definition: Person.h:62
Processes the contacts between persons and determines whether transmission occurs.
STL namespace.
float GetAge() const
Get the age.
Definition: Person.h:53
ContactType::Id m_pool_type
The type of the ContactPool (for logging and testing purposes).
Definition: ContactPool.h:89
unsigned int m_index_immune
Index of the first immune member in the ContactPool.
Definition: ContactPool.h:87
Header for the Infector class.
bool IsInPool(const ContactType::Id &poolType) const
Check if a person is present today in a given contact pool.
Definition: Person.h:68
std::tuple< bool, unsigned int > SortMembers()
Sort w.r.t. health status: order: exposed/infected/recovered, susceptible, immune.
Definition: ContactPool.cpp:55
unsigned int EffectiveAge(unsigned int age)
Effective age (topping of at maximum).
Definition: Age.h:32
Actual contacts and transmission in contactpool (primary template).
Definition: Infector.h:69
Transmission probabilities from disease data.
double GetProbability() const
Return transmission probability.
Contact rates as a function of age.
Header file for the Calendar class.
Store and handle person data.
Definition: Person.h:34
Namespace for the simulator and related classes.
Definition: Calendar.cpp:28
bool IsSusceptible() const
Is this person susceptible?
Definition: Health.h:77
void StartInfection()
Start the infection.
Definition: Health.cpp:35
bool HasContact(double contact_rate)
Check if two individuals have contact.
Namespace to manage types of ContactPool.
Definition: ContactType.cpp:28